[
  {
    "path": ".gitattributes",
    "content": "*.js    text eol=lf\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n<!-- Note: sub-optimal but correct code is not a bug -->\n\n**Uglify version (`uglifyjs -V`)**\n\n**JavaScript input**\n\n<!--\nA complete parsable JS program exhibiting the issue with UglifyJS alone\n- without third party tools or libraries.\n\nIdeally the input should be as small as possible, but may be large if isolating\nthe problem proves to be difficult. The most important thing is that the\nstandalone program reliably exhibits the bug when minified. Provide a link to a\ngist if necessary.\n\nSolely providing minified output without the original uglify JS input is not\nuseful in determining the cause of the problem. Issues without a reproducible\ntest case will be closed.\n-->\n\n**The `uglifyjs` CLI command executed or `minify()` options used.**\n\n<!--\nCommand-line or API call to UglifyJS without third party tools or libraries.\n\nFor users using bundlers or transpilers, you may be able to gather the required\ninformation through setting the `UGLIFY_BUG_REPORT` environment variable:\n\n    export UGLIFY_BUG_REPORT=1      (bash)\n    set UGLIFY_BUG_REPORT=1         (Command Prompt)\n    $Env:UGLIFY_BUG_REPORT=1        (PowerShell)\n\nbefore running your usual build process. The resulting \"minified\" output should\ncontain the necessary details for this report.\n-->\n\n**JavaScript output or error produced.**\n\n<!--\nOnly minified code that produces different output (or error) from the original\nupon execution would be considered a bug.\n-->\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build testing\non:\n  pull_request:\n  push:\n    branches: [ master ]\njobs:\n  ufuzz:\n    strategy:\n      fail-fast: false\n      matrix:\n        options:\n          - '--ie -c'\n          - '-mb braces'\n          - '--toplevel -mc'\n          - '-p acorn -mco spidermonkey'\n          - '-mc passes=3,pure_getters,unsafe'\n        script:\n          - acorn.sh\n          - bootstrap.sh\n          - buble.sh\n          - butternut.sh\n          - mathjs.sh\n          - rollup-es.sh\n          - rollup-ts.sh\n          - sucrase.sh\n          - web-tooling-benchmark.sh\n        include:\n          - node: '14'\n            script: acorn.sh\n          - node: '14'\n            script: bootstrap.sh\n          - node: '14'\n            script: buble.sh\n          - node: '14'\n            script: butternut.sh\n          - node: '14'\n            script: mathjs.sh\n          - node: '8'\n            script: rollup-es.sh\n          - node: '14'\n            script: rollup-ts.sh\n          - node: '14'\n            script: sucrase.sh\n          - node: '14'\n            script: web-tooling-benchmark.sh\n    name: ${{ matrix.script }} ${{ matrix.options }}\n    runs-on: ubuntu-latest\n    env:\n      NODE: ${{ matrix.node }}\n      OPTIONS: ${{ matrix.options }}\n      SCRIPT: ${{ matrix.script }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Perform uglify, build & test\n        shell: bash\n        run: |\n          . ./test/release/install.sh\n          ./test/release/$SCRIPT $OPTIONS\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  pull_request:\n  push:\n    branches: [ master ]\njobs:\n  test:\n    strategy:\n      matrix:\n        node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', '18', '20' ]\n        os: [ ubuntu-latest, windows-latest ]\n        script: [ compress, mocha, release/benchmark, release/jetstream ]\n    name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}\n    runs-on: ${{ matrix.os }}\n    env:\n      NODE: ${{ matrix.node }}\n      TYPE: ${{ matrix.script }}\n      UGLIFY_GITHUB_LAG: 10000\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/cache@v4\n        with:\n          path: tmp\n          key: tmp ${{ matrix.script }}\n      - name: Patch OpenSSL on Ubuntu\n        if: runner.os == 'Linux'\n        shell: bash\n        run: |\n          sudo sed -i 's/providers = provider_sect/# providers = provider_sect/' /etc/ssl/openssl.cnf\n      - name: Perform tests\n        shell: bash\n        run: |\n          . ./test/release/install.sh\n          node test/$TYPE\n"
  },
  {
    "path": ".github/workflows/moz.yml",
    "content": "name: ESTree\non:\n  pull_request:\n  push:\n    branches: [ master ]\njobs:\n  test:\n    name: fuzzing\n    runs-on: ubuntu-latest\n    env:\n      NODE: 22\n    steps:\n      - uses: actions/checkout@v4\n      - name: Perform tests\n        shell: bash\n        run: |\n          . ./test/release/install.sh\n          node test/mozilla-ast.js 5000\n"
  },
  {
    "path": ".github/workflows/ufuzz.yml",
    "content": "name: Fuzzing\non:\n  pull_request:\n  schedule:\n    - cron: '*/15 * * * *'\n  workflow_dispatch:\n  workflow_run:\n    branches: [ master ]\n    types: [ completed ]\n    workflows: [ 'Build testing', CI ]\nenv:\n  BASE_URL: https://api.github.com/repos/${{ github.repository }}\n  TOKEN: ${{ github.token }}\njobs:\n  ufuzz:\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - node: '16'\n            os: macos-latest\n          - node: '12'\n            os: ubuntu-latest\n          - node: '8'\n            os: ubuntu-latest\n          - node: '12'\n            os: windows-latest\n          - node: '8'\n            os: windows-latest\n    name: ${{ matrix.node }} ${{ matrix.os }}\n    runs-on: ${{ matrix.os }}\n    env:\n      NODE: ${{ matrix.node }}\n    steps:\n      - uses: actions/checkout@v4\n      - name: Perform fuzzing\n        shell: bash\n        run: |\n          . ./test/release/install.sh\n          if [[ $GITHUB_EVENT_NAME == \"pull_request\" ]]; then\n            node test/ufuzz/job 5000\n          else\n            node test/ufuzz/job $BASE_URL $TOKEN $GITHUB_RUN_NUMBER\n          fi\n"
  },
  {
    "path": ".gitignore",
    "content": "/node_modules/\n/npm-debug.log\ntmp/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing\n============\n\n## Documentation\n\nEvery new feature and API change should be accompanied by a README addition.\n\n## Testing\n\nAll features and bugs should have tests that verify the fix. You can run all\ntests using `npm test`.\n\nThe most common type of test are tests that verify input and output of the\nUglify transforms. These tests exist in `test/compress`. New tests can be added\neither to an existing file or in a new file `issue-xxx.js`.\n\nTests that cannot be expressed as a simple AST can be found in `test/mocha`.\n\n## Code style\n\n- File encoding must be `UTF-8`.\n- `LF` is always used as a line ending.\n- Statements end with semicolons.\n- Indentation uses 4 spaces, switch `case` 2 spaces.\n- Identifiers use `snake_case`.\n- Strings use double quotes (`\"`).\n- Use a trailing comma for multiline array and object literals to minimize diffs.\n- The Uglify code only uses ES5, even in the `harmony` branch.\n- Line length should be at most 80 cols, except when it is easier to read a\n  longer line.\n- If both sides of a comparison are of the same type, `==` and `!=` are used.\n- Multiline conditions place `&&` and `||` first on the line.\n\n**Example feature**\n\n```js\nOPT(AST_Debugger, function(self, compressor) {\n    if (compressor.option(\"drop_debugger\"))\n        return make_node(AST_EmptyStatement, self);\n    return self;\n});\n```\n\n**Example test case**\n\n```js\ndrop_debugger: {\n    options = {\n        drop_debugger: true,\n    }\n    input: {\n        debugger;\n        if (foo) debugger;\n    }\n    expect: {\n        if (foo);\n    }\n}\n```\n\n\n"
  },
  {
    "path": "LICENSE",
    "content": "UglifyJS is released under the BSD license:\n\nCopyright 2012-2024 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n    * Redistributions of source code must retain the above\n      copyright notice, this list of conditions and the following\n      disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials\n      provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\nTORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\nTHE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "UglifyJS 3\n==========\n\nUglifyJS is a JavaScript parser, minifier, compressor and beautifier toolkit.\n\n#### Note:\n- `uglify-js` supports JavaScript and most language features in ECMAScript.\n- For more exotic parts of ECMAScript, process your source file with transpilers\n  like [Babel](https://babeljs.io/) before passing onto `uglify-js`.\n- `uglify-js@3` has a simplified [API](#api-reference) and [CLI](#command-line-usage)\n  that is not backwards compatible with [`uglify-js@2`](https://github.com/mishoo/UglifyJS/tree/v2.x).\n\nInstall\n-------\n\nFirst make sure you have installed the latest version of [node.js](http://nodejs.org/)\n(You may need to restart your computer after this step).\n\nFrom NPM for use as a command line app:\n\n    npm install uglify-js -g\n\nFrom NPM for programmatic use:\n\n    npm install uglify-js\n\n# Command line usage\n\n    uglifyjs [input files] [options]\n\nUglifyJS can take multiple input files.  It's recommended that you pass the\ninput files first, then pass the options.  UglifyJS will parse input files\nin sequence and apply any compression options.  The files are parsed in the\nsame global scope, that is, a reference from a file to some\nvariable/function declared in another file will be matched properly.\n\nIf no input file is specified, UglifyJS will read from STDIN.\n\nIf you wish to pass your options before the input files, separate the two with\na double dash to prevent input files being used as option arguments:\n\n    uglifyjs --compress --mangle -- input.js\n\n### Command line options\n\n```\n    -h, --help                  Print usage information.\n                                `--help options` for details on available options.\n    -V, --version               Print version number.\n    -p, --parse <options>       Specify parser options:\n                                `acorn`  Use Acorn for parsing.\n                                `bare_returns`  Allow return outside of functions.\n                                                Useful when minifying CommonJS\n                                                modules and Userscripts that may\n                                                be anonymous function wrapped (IIFE)\n                                                by the .user.js engine `caller`.\n                                `spidermonkey`  Assume input files are SpiderMonkey\n                                                AST format (as JSON).\n    -c, --compress [options]    Enable compressor/specify compressor options:\n                                `pure_funcs`  List of functions that can be safely\n                                              removed when their return values are\n                                              not used.\n    -m, --mangle [options]      Mangle names/specify mangler options:\n                                `reserved`  List of names that should not be mangled.\n    --mangle-props [options]    Mangle properties/specify mangler options:\n                                `builtins`  Mangle property names that overlaps\n                                            with standard JavaScript globals.\n                                `debug`  Add debug prefix and suffix.\n                                `domprops`  Mangle property names that overlaps\n                                            with DOM properties.\n                                `globals`  Mangle variable access via global object.\n                                `keep_quoted`  Only mangle unquoted properties.\n                                `regex`  Only mangle matched property names.\n                                `reserved`  List of names that should not be mangled.\n    -b, --beautify [options]    Beautify output/specify output options:\n                                `beautify`  Enabled with `--beautify` by default.\n                                `preamble`  Preamble to prepend to the output. You\n                                            can use this to insert a comment, for\n                                            example for licensing information.\n                                            This will not be parsed, but the source\n                                            map will adjust for its presence.\n                                `quote_style`  Quote style:\n                                               0 - auto\n                                               1 - single\n                                               2 - double\n                                               3 - original\n                                `wrap_iife`  Wrap IIFEs in parentheses. Note: you may\n                                             want to disable `negate_iife` under\n                                             compressor options.\n    -O, --output-opts [options] Specify output options (`beautify` disabled by default).\n    -o, --output <file>         Output file path (default STDOUT). Specify `ast` or\n                                `spidermonkey` to write UglifyJS or SpiderMonkey AST\n                                as JSON to STDOUT respectively.\n    --annotations               Process and preserve comment annotations.\n                                (`/*@__PURE__*/` or `/*#__PURE__*/`)\n    --no-annotations            Ignore and discard comment annotations.\n    --comments [filter]         Preserve copyright comments in the output. By\n                                default this works like Google Closure, keeping\n                                JSDoc-style comments that contain \"@license\" or\n                                \"@preserve\". You can optionally pass one of the\n                                following arguments to this flag:\n                                - \"all\" to keep all comments\n                                - a valid JS RegExp like `/foo/` or `/^!/` to\n                                keep only matching comments.\n                                Note that currently not *all* comments can be\n                                kept when compression is on, because of dead\n                                code removal or cascading statements into\n                                sequences.\n    --config-file <file>        Read `minify()` options from JSON file.\n    -d, --define <expr>[=value] Global definitions.\n    -e, --enclose [arg[:value]] Embed everything in a big function, with configurable\n                                argument(s) & value(s).\n    --expression                Parse a single expression, rather than a program\n                                (for parsing JSON).\n    --ie                        Support non-standard Internet Explorer.\n                                Equivalent to setting `ie: true` in `minify()`\n                                for `compress`, `mangle` and `output` options.\n                                By default UglifyJS will not try to be IE-proof.\n    --keep-fargs                Do not mangle/drop function arguments.\n    --keep-fnames               Do not mangle/drop function names.  Useful for\n                                code relying on Function.prototype.name.\n    --module                    Process input as ES module (implies --toplevel)\n    --no-module                 Avoid optimizations which may alter runtime behavior\n                                under prior versions of JavaScript.\n    --name-cache <file>         File to hold mangled name mappings.\n    --self                      Build UglifyJS as a library (implies --wrap UglifyJS)\n    --source-map [options]      Enable source map/specify source map options:\n                                `base`  Path to compute relative paths from input files.\n                                `content`  Input source map, useful if you're compressing\n                                           JS that was generated from some other original\n                                           code. Specify \"inline\" if the source map is\n                                           included within the sources.\n                                `filename`  Filename and/or location of the output source\n                                            (sets `file` attribute in source map).\n                                `includeSources`  Pass this flag if you want to include\n                                                  the content of source files in the\n                                                  source map as sourcesContent property.\n                                `names` Include symbol names in the source map.\n                                `root`  Path to the original source to be included in\n                                        the source map.\n                                `url`  If specified, path to the source map to append in\n                                       `//# sourceMappingURL`.\n    --timings                   Display operations run time on STDERR.\n    --toplevel                  Compress and/or mangle variables in top level scope.\n    --v8                        Support non-standard Chrome & Node.js\n                                Equivalent to setting `v8: true` in `minify()`\n                                for `mangle` and `output` options.\n                                By default UglifyJS will not try to be v8-proof.\n    --verbose                   Print diagnostic messages.\n    --warn                      Print warning messages.\n    --webkit                    Support non-standard Safari/Webkit.\n                                Equivalent to setting `webkit: true` in `minify()`\n                                for `compress`, `mangle` and `output` options.\n                                By default UglifyJS will not try to be Safari-proof.\n    --wrap <name>               Embed everything in a big function, making the\n                                “exports” and “global” variables available. You\n                                need to pass an argument to this option to\n                                specify the name that your module will take\n                                when included in, say, a browser.\n```\n\nSpecify `--output` (`-o`) to declare the output file.  Otherwise the output\ngoes to STDOUT.\n\n## CLI source map options\n\nUglifyJS can generate a source map file, which is highly useful for\ndebugging your compressed JavaScript.  To get a source map, pass\n`--source-map --output output.js` (source map will be written out to\n`output.js.map`).\n\nAdditional options:\n\n- `--source-map \"filename='<NAME>'\"` to specify the name of the source map. The value of\n  `filename` is only used to set `file` attribute (see [the spec][sm-spec])\n  in source map file.\n\n- `--source-map \"root='<URL>'\"` to pass the URL where the original files can be found.\n\n- `--source-map \"names=false\"` to omit symbol names if you want to reduce size\n  of the source map file.\n\n- `--source-map \"url='<URL>'\"` to specify the URL where the source map can be found.\n  Otherwise UglifyJS assumes HTTP `X-SourceMap` is being used and will omit the\n  `//# sourceMappingURL=` directive.\n\nFor example:\n\n    uglifyjs js/file1.js js/file2.js \\\n             -o foo.min.js -c -m \\\n             --source-map \"root='http://foo.com/src',url='foo.min.js.map'\"\n\nThe above will compress and mangle `file1.js` and `file2.js`, will drop the\noutput in `foo.min.js` and the source map in `foo.min.js.map`.  The source\nmapping will refer to `http://foo.com/src/js/file1.js` and\n`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src`\nas the source map root, and the original files as `js/file1.js` and\n`js/file2.js`).\n\n### Composed source map\n\nWhen you're compressing JS code that was output by a compiler such as\nCoffeeScript, mapping to the JS code won't be too helpful.  Instead, you'd\nlike to map back to the original code (i.e. CoffeeScript).  UglifyJS has an\noption to take an input source map.  Assuming you have a mapping from\nCoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript →\ncompressed JS by mapping every token in the compiled JS to its original\nlocation.\n\nTo use this feature pass `--source-map \"content='/path/to/input/source.map'\"`\nor `--source-map \"content=inline\"` if the source map is included inline with\nthe sources.\n\n## CLI compress options\n\nYou need to pass `--compress` (`-c`) to enable the compressor.  Optionally\nyou can pass a comma-separated list of [compress options](#compress-options).\n\nOptions are in the form `foo=bar`, or just `foo` (the latter implies\na boolean option that you want to set `true`; it's effectively a\nshortcut for `foo=true`).\n\nExample:\n\n    uglifyjs file.js -c toplevel,sequences=false\n\n## CLI mangle options\n\nTo enable the mangler you need to pass `--mangle` (`-m`).  The following\n(comma-separated) options are supported:\n\n- `eval` (default: `false`) — mangle names visible in scopes where `eval` or\n  `with` are used.\n\n- `reserved` (default: `[]`) — when mangling is enabled but you want to\n  prevent certain names from being mangled, you can declare those names with\n  `--mangle reserved` — pass a comma-separated list of names.  For example:\n\n      uglifyjs ... -m reserved=['$','require','exports']\n\n  to prevent the `require`, `exports` and `$` names from being changed.\n\n### CLI mangling property names (`--mangle-props`)\n\n**Note:** THIS WILL PROBABLY BREAK YOUR CODE.  Mangling property names\nis a separate step, different from variable name mangling.  Pass\n`--mangle-props` to enable it.  It will mangle all properties in the\ninput code with the exception of built in DOM properties and properties\nin core JavaScript classes.  For example:\n\n```javascript\n// example.js\nvar x = {\n    baz_: 0,\n    foo_: 1,\n    calc: function() {\n        return this.foo_ + this.baz_;\n    }\n};\nx.bar_ = 2;\nx[\"baz_\"] = 3;\nconsole.log(x.calc());\n```\nMangle all properties (except for JavaScript `builtins`):\n```bash\n$ uglifyjs example.js -c -m --mangle-props\n```\n```javascript\nvar x={o:0,_:1,l:function(){return this._+this.o}};x.t=2,x.o=3,console.log(x.l());\n```\nMangle all properties except for `reserved` properties:\n```bash\n$ uglifyjs example.js -c -m --mangle-props reserved=[foo_,bar_]\n```\n```javascript\nvar x={o:0,foo_:1,_:function(){return this.foo_+this.o}};x.bar_=2,x.o=3,console.log(x._());\n```\nMangle all properties matching a `regex`:\n```bash\n$ uglifyjs example.js -c -m --mangle-props regex=/_$/\n```\n```javascript\nvar x={o:0,_:1,calc:function(){return this._+this.o}};x.l=2,x.o=3,console.log(x.calc());\n```\n\nCombining mangle properties options:\n```bash\n$ uglifyjs example.js -c -m --mangle-props regex=/_$/,reserved=[bar_]\n```\n```javascript\nvar x={o:0,_:1,calc:function(){return this._+this.o}};x.bar_=2,x.o=3,console.log(x.calc());\n```\n\nIn order for this to be of any use, we avoid mangling standard JS names by\ndefault (`--mangle-props builtins` to override).\n\nSpecify `--mangle-props globals` to mangle property names of global\nobject (e.g. `self.foo`) as global variables.\n\nA default exclusion file is provided in `tools/domprops.json` which should\ncover most standard JS and DOM properties defined in various browsers.  Pass\n`--mangle-props domprops` to disable this feature.\n\nA regular expression can be used to define which property names should be\nmangled.  For example, `--mangle-props regex=/^_/` will only mangle property\nnames that start with an underscore.\n\nWhen you compress multiple files using this option, in order for them to\nwork together in the end we need to ensure somehow that one property gets\nmangled to the same name in all of them.  For this, pass `--name-cache filename.json`\nand UglifyJS will maintain these mappings in a file which can then be reused.\nIt should be initially empty.  Example:\n\n```bash\n$ rm -f /tmp/cache.json  # start fresh\n$ uglifyjs file1.js file2.js --mangle-props --name-cache /tmp/cache.json -o part1.js\n$ uglifyjs file3.js file4.js --mangle-props --name-cache /tmp/cache.json -o part2.js\n```\n\nNow, `part1.js` and `part2.js` will be consistent with each other in terms\nof mangled property names.\n\nUsing the name cache is not necessary if you compress all your files in a\nsingle call to UglifyJS.\n\n### Mangling unquoted names (`--mangle-props keep_quoted`)\n\nUsing quoted property name (`o[\"foo\"]`) reserves the property name (`foo`)\nso that it is not mangled throughout the entire script even when used in an\nunquoted style (`o.foo`). Example:\n\n```javascript\n// stuff.js\nvar o = {\n    \"foo\": 1,\n    bar: 3,\n};\no.foo += o.bar;\nconsole.log(o.foo);\n```\n```bash\n$ uglifyjs stuff.js --mangle-props keep_quoted -c -m\n```\n```javascript\nvar o={foo:1,o:3};o.foo+=o.o,console.log(o.foo);\n```\n\nIf the minified output will be processed again by UglifyJS, consider specifying\n`keep_quoted_props` so the same property names are preserved:\n\n```bash\n$ uglifyjs stuff.js --mangle-props keep_quoted -c -m -O keep_quoted_props\n```\n```javascript\nvar o={\"foo\":1,o:3};o.foo+=o.o,console.log(o.foo);\n```\n\n### Debugging property name mangling\n\nYou can also pass `--mangle-props debug` in order to mangle property names\nwithout completely obscuring them. For example the property `o.foo`\nwould mangle to `o._$foo$_` with this option. This allows property mangling\nof a large codebase while still being able to debug the code and identify\nwhere mangling is breaking things.\n\n```bash\n$ uglifyjs stuff.js --mangle-props debug -c -m\n```\n```javascript\nvar o={_$foo$_:1,_$bar$_:3};o._$foo$_+=o._$bar$_,console.log(o._$foo$_);\n```\n\nYou can also pass a custom suffix using `--mangle-props debug=XYZ`. This would then\nmangle `o.foo` to `o._$foo$XYZ_`. You can change this each time you compile a\nscript to identify how a property got mangled. One technique is to pass a\nrandom number on every compile to simulate mangling changing with different\ninputs (e.g. as you update the input script with new properties), and to help\nidentify mistakes like writing mangled keys to storage.\n\n\n# API Reference\n\nAssuming installation via NPM, you can load UglifyJS in your application\nlike this:\n```javascript\nvar UglifyJS = require(\"uglify-js\");\n```\n\nThere is a single high level function, **`minify(code, options)`**,\nwhich will perform all minification [phases](#minify-options) in a configurable\nmanner. By default `minify()` will enable the options [`compress`](#compress-options)\nand [`mangle`](#mangle-options). Example:\n```javascript\nvar code = \"function add(first, second) { return first + second; }\";\nvar result = UglifyJS.minify(code);\nconsole.log(result.error); // runtime error, or `undefined` if no error\nconsole.log(result.code);  // minified output: function add(n,d){return n+d}\n```\n\nYou can `minify` more than one JavaScript file at a time by using an object\nfor the first argument where the keys are file names and the values are source\ncode:\n```javascript\nvar code = {\n    \"file1.js\": \"function add(first, second) { return first + second; }\",\n    \"file2.js\": \"console.log(add(1 + 2, 3 + 4));\"\n};\nvar result = UglifyJS.minify(code);\nconsole.log(result.code);\n// function add(d,n){return d+n}console.log(add(3,7));\n```\n\nThe `toplevel` option:\n```javascript\nvar code = {\n    \"file1.js\": \"function add(first, second) { return first + second; }\",\n    \"file2.js\": \"console.log(add(1 + 2, 3 + 4));\"\n};\nvar options = { toplevel: true };\nvar result = UglifyJS.minify(code, options);\nconsole.log(result.code);\n// console.log(3+7);\n```\n\nThe `nameCache` option:\n```javascript\nvar options = {\n    mangle: {\n        toplevel: true,\n    },\n    nameCache: {}\n};\nvar result1 = UglifyJS.minify({\n    \"file1.js\": \"function add(first, second) { return first + second; }\"\n}, options);\nvar result2 = UglifyJS.minify({\n    \"file2.js\": \"console.log(add(1 + 2, 3 + 4));\"\n}, options);\nconsole.log(result1.code);\n// function n(n,r){return n+r}\nconsole.log(result2.code);\n// console.log(n(3,7));\n```\n\nYou may persist the name cache to the file system in the following way:\n```javascript\nvar cacheFileName = \"/tmp/cache.json\";\nvar options = {\n    mangle: {\n        properties: true,\n    },\n    nameCache: JSON.parse(fs.readFileSync(cacheFileName, \"utf8\"))\n};\nfs.writeFileSync(\"part1.js\", UglifyJS.minify({\n    \"file1.js\": fs.readFileSync(\"file1.js\", \"utf8\"),\n    \"file2.js\": fs.readFileSync(\"file2.js\", \"utf8\")\n}, options).code, \"utf8\");\nfs.writeFileSync(\"part2.js\", UglifyJS.minify({\n    \"file3.js\": fs.readFileSync(\"file3.js\", \"utf8\"),\n    \"file4.js\": fs.readFileSync(\"file4.js\", \"utf8\")\n}, options).code, \"utf8\");\nfs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), \"utf8\");\n```\n\nAn example of a combination of `minify()` options:\n```javascript\nvar code = {\n    \"file1.js\": \"function add(first, second) { return first + second; }\",\n    \"file2.js\": \"console.log(add(1 + 2, 3 + 4));\"\n};\nvar options = {\n    toplevel: true,\n    compress: {\n        global_defs: {\n            \"@console.log\": \"alert\"\n        },\n        passes: 2\n    },\n    output: {\n        beautify: false,\n        preamble: \"/* uglified */\"\n    }\n};\nvar result = UglifyJS.minify(code, options);\nconsole.log(result.code);\n// /* uglified */\n// alert(10);\"\n```\n\nTo produce warnings:\n```javascript\nvar code = \"function f(){ var u; return 2 + 3; }\";\nvar options = { warnings: true };\nvar result = UglifyJS.minify(code, options);\nconsole.log(result.error);    // runtime error, `undefined` in this case\nconsole.log(result.warnings); // [ 'Dropping unused variable u [0:1,18]' ]\nconsole.log(result.code);     // function f(){return 5}\n```\n\nAn error example:\n```javascript\nvar result = UglifyJS.minify({\"foo.js\" : \"if (0) else console.log(1);\"});\nconsole.log(JSON.stringify(result.error));\n// {\"message\":\"Unexpected token: keyword (else)\",\"filename\":\"foo.js\",\"line\":1,\"col\":7,\"pos\":7}\n```\nNote: unlike `uglify-js@2.x`, the `3.x` API does not throw errors. To\nachieve a similar effect one could do the following:\n```javascript\nvar result = UglifyJS.minify(code, options);\nif (result.error) throw result.error;\n```\n\n## Minify options\n\n- `annotations` — pass `false` to ignore all comment annotations and elide them\n  from output. Useful when, for instance, external tools incorrectly applied\n  `/*@__PURE__*/` or `/*#__PURE__*/`. Pass `true` to both compress and retain\n  comment annotations in output to allow for further processing downstream.\n\n- `compress` (default: `{}`) — pass `false` to skip compressing entirely.\n  Pass an object to specify custom [compress options](#compress-options).\n\n- `expression` (default: `false`) — parse as a single expression, e.g. JSON.\n\n- `ie` (default: `false`) — enable workarounds for Internet Explorer bugs.\n\n- `keep_fargs` (default: `false`) — pass `true` to prevent discarding or mangling\n  of function arguments.\n\n- `keep_fnames` (default: `false`) — pass `true` to prevent discarding or mangling\n  of function names.  Useful for code relying on `Function.prototype.name`.\n\n- `mangle` (default: `true`) — pass `false` to skip mangling names, or pass\n  an object to specify [mangle options](#mangle-options) (see below).\n\n  - `mangle.properties` (default: `false`) — a subcategory of the mangle option.\n    Pass an object to specify custom [mangle property options](#mangle-properties-options).\n\n- `module` (default: `true`) — process input as ES module, i.e. implicit\n  `\"use strict\";` and support for top-level `await`. When explicitly specified,\n  also enables `toplevel`.\n\n- `nameCache` (default: `null`) — pass an empty object `{}` or a previously\n  used `nameCache` object if you wish to cache mangled variable and\n  property names across multiple invocations of `minify()`. Note: this is\n  a read/write property. `minify()` will read the name cache state of this\n  object and update it during minification so that it may be\n  reused or externally persisted by the user.\n\n- `output` (default: `null`) — pass an object if you wish to specify\n  additional [output options](#output-options).  The defaults are optimized\n  for best compression.\n\n- `parse` (default: `{}`) — pass an object if you wish to specify some\n  additional [parse options](#parse-options).\n\n- `sourceMap` (default: `false`) — pass an object if you wish to specify\n  [source map options](#source-map-options).\n\n- `toplevel` (default: `false`) — set to `true` if you wish to enable top level\n  variable and function name mangling and to drop unused variables and functions.\n\n- `v8` (default: `false`) — enable workarounds for Chrome & Node.js bugs.\n\n- `warnings` (default: `false`) — pass `true` to return compressor warnings\n  in `result.warnings`. Use the value `\"verbose\"` for more detailed warnings.\n\n- `webkit` (default: `false`) — enable workarounds for Safari/WebKit bugs.\n  PhantomJS users should set this option to `true`.\n\n## Minify options structure\n\n```javascript\n{\n    parse: {\n        // parse options\n    },\n    compress: {\n        // compress options\n    },\n    mangle: {\n        // mangle options\n\n        properties: {\n            // mangle property options\n        }\n    },\n    output: {\n        // output options\n    },\n    sourceMap: {\n        // source map options\n    },\n    nameCache: null, // or specify a name cache object\n    toplevel: false,\n    warnings: false,\n}\n```\n\n### Source map options\n\nTo generate a source map:\n```javascript\nvar result = UglifyJS.minify({\"file1.js\": \"var a = function() {};\"}, {\n    sourceMap: {\n        filename: \"out.js\",\n        url: \"out.js.map\"\n    }\n});\nconsole.log(result.code); // minified output\nconsole.log(result.map);  // source map\n```\n\nNote that the source map is not saved in a file, it's just returned in\n`result.map`.  The value passed for `sourceMap.url` is only used to set\n`//# sourceMappingURL=out.js.map` in `result.code`. The value of\n`filename` is only used to set `file` attribute (see [the spec][sm-spec])\nin source map file.\n\nYou can set option `sourceMap.url` to be `\"inline\"` and source map will\nbe appended to code.\n\nYou can also specify sourceRoot property to be included in source map:\n```javascript\nvar result = UglifyJS.minify({\"file1.js\": \"var a = function() {};\"}, {\n    sourceMap: {\n        root: \"http://example.com/src\",\n        url: \"out.js.map\"\n    }\n});\n```\n\nIf you're compressing compiled JavaScript and have a source map for it, you\ncan use `sourceMap.content`:\n```javascript\nvar result = UglifyJS.minify({\"compiled.js\": \"compiled code\"}, {\n    sourceMap: {\n        content: \"content from compiled.js.map\",\n        url: \"minified.js.map\"\n    }\n});\n// same as before, it returns `code` and `map`\n```\n\nIf you're using the `X-SourceMap` header instead, you can just omit `sourceMap.url`.\n\nIf you wish to reduce file size of the source map, set option `sourceMap.names`\nto be `false` and all symbol names will be omitted.\n\n## Parse options\n\n- `bare_returns` (default: `false`) — support top level `return` statements\n\n- `html5_comments` (default: `true`) — process HTML comment as workaround for\n  browsers which do not recognize `<script>` tags\n\n- `module` (default: `false`) — set to `true` if you wish to process input as\n  ES module, i.e. implicit `\"use strict\";` and support for top-level `await`.\n\n- `shebang` (default: `true`) — support `#!command` as the first line\n\n## Compress options\n\n- `annotations` (default: `true`) — Pass `false` to disable potentially dropping\n  functions marked as \"pure\".  A function call is marked as \"pure\" if a comment\n  annotation `/*@__PURE__*/` or `/*#__PURE__*/` immediately precedes the call. For\n  example: `/*@__PURE__*/foo();`\n\n- `arguments` (default: `true`) — replace `arguments[index]` with function\n  parameter name whenever possible.\n\n- `arrows` (default: `true`) — apply optimizations to arrow functions\n\n- `assignments` (default: `true`) — apply optimizations to assignment expressions\n\n- `awaits` (default: `true`) — apply optimizations to `await` expressions\n\n- `booleans` (default: `true`) — various optimizations for boolean context,\n  for example `!!a ? b : c → a ? b : c`\n\n- `collapse_vars` (default: `true`) — Collapse single-use non-constant variables,\n  side effects permitting.\n\n- `comparisons` (default: `true`) — apply certain optimizations to binary nodes,\n  e.g. `!(a <= b) → a > b`, attempts to negate binary nodes, e.g.\n  `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc.\n\n- `conditionals` (default: `true`) — apply optimizations for `if`-s and conditional\n  expressions\n\n- `dead_code` (default: `true`) — remove unreachable code\n\n- `default_values` (default: `true`) — drop overshadowed default values\n\n- `directives` (default: `true`) — remove redundant or non-standard directives\n\n- `drop_console` (default: `false`) — Pass `true` to discard calls to\n  `console.*` functions. If you wish to drop a specific function call\n  such as `console.info` and/or retain side effects from function arguments\n  after dropping the function call then use `pure_funcs` instead.\n\n- `drop_debugger` (default: `true`) — remove `debugger;` statements\n\n- `evaluate` (default: `true`) — Evaluate expression for shorter constant\n  representation. Pass `\"eager\"` to always replace function calls whenever\n  possible, or a positive integer to specify an upper bound for each individual\n  evaluation in number of characters.\n\n- `expression` (default: `false`) — Pass `true` to preserve completion values\n  from terminal statements without `return`, e.g. in bookmarklets.\n\n- `functions` (default: `true`) — convert declarations from `var` to `function`\n  whenever possible.\n\n- `global_defs` (default: `{}`) — see [conditional compilation](#conditional-compilation)\n\n- `hoist_exports` (default: `true`) — hoist `export` statements to facilitate\n  various `compress` and `mangle` optimizations.\n\n- `hoist_funs` (default: `false`) — hoist function declarations\n\n- `hoist_props` (default: `true`) — hoist properties from constant object and\n  array literals into regular variables subject to a set of constraints. For example:\n  `var o={p:1, q:2}; f(o.p, o.q);` is converted to `f(1, 2);`. Note: `hoist_props`\n  works best with `toplevel` and `mangle` enabled, alongside with `compress` option\n  `passes` set to `2` or higher.\n\n- `hoist_vars` (default: `false`) — hoist `var` declarations (this is `false`\n  by default because it seems to increase the size of the output in general)\n\n- `if_return` (default: `true`) — optimizations for if/return and if/continue\n\n- `imports` (default: `true`) — drop unreferenced import symbols when used with `unused`\n\n- `inline` (default: `true`) — inline calls to function with simple/`return` statement:\n  - `false` — same as `0`\n  - `0` — disabled inlining\n  - `1` — inline simple functions\n  - `2` — inline functions with arguments\n  - `3` — inline functions with arguments and variables\n  - `4` — inline functions with arguments, variables and statements\n  - `true` — same as `4`\n\n- `join_vars` (default: `true`) — join consecutive `var` statements\n\n- `keep_fargs` (default: `false`) — discard unused function arguments except\n  when unsafe to do so, e.g. code which relies on `Function.prototype.length`.\n  Pass `true` to always retain function arguments.\n\n- `keep_infinity` (default: `false`) — Pass `true` to prevent `Infinity` from\n  being compressed into `1/0`, which may cause performance issues on Chrome.\n\n- `loops` (default: `true`) — optimizations for `do`, `while` and `for` loops\n  when we can statically determine the condition.\n\n- `merge_vars` (default: `true`) — combine and reuse variables.\n\n- `module` (default: `false`) — set to `true` if you wish to process input as\n  ES module, i.e. implicit `\"use strict\";`.\n\n- `negate_iife` (default: `true`) — negate \"Immediately-Called Function Expressions\"\n  where the return value is discarded, to avoid the parentheses that the\n  code generator would insert.\n\n- `objects` (default: `true`) — compact duplicate keys in object literals.\n\n- `passes` (default: `1`) — The maximum number of times to run compress.\n  In some cases more than one pass leads to further compressed code.  Keep in\n  mind more passes will take more time.\n\n- `properties` (default: `true`) — rewrite property access using the dot notation, for\n  example `foo[\"bar\"] → foo.bar`\n\n- `pure_funcs` (default: `null`) — You can pass an array of names and\n  UglifyJS will assume that those functions do not produce side\n  effects.  DANGER: will not check if the name is redefined in scope.\n  An example case here, for instance `var q = Math.floor(a/b)`.  If\n  variable `q` is not used elsewhere, UglifyJS will drop it, but will\n  still keep the `Math.floor(a/b)`, not knowing what it does.  You can\n  pass `pure_funcs: [ 'Math.floor' ]` to let it know that this\n  function won't produce any side effect, in which case the whole\n  statement would get discarded.  The current implementation adds some\n  overhead (compression will be slower). Make sure symbols under `pure_funcs`\n  are also under `mangle.reserved` to avoid mangling.\n\n- `pure_getters` (default: `\"strict\"`) — Pass `true` for UglifyJS to assume that\n  object property access (e.g. `foo.bar` or `a[42]`) does not throw exception or\n  alter program states via getter function. Pass `\"strict\"` to allow dropping or\n  reordering `foo.bar` only if `foo` is not `null` or `undefined` and is safe to\n  access as a variable. Pass `false` to retain all property accesses.\n\n- `reduce_funcs` (default: `true`) — Allows single-use functions to be\n  inlined as function expressions when permissible allowing further\n  optimization.  Enabled by default.  Option depends on `reduce_vars`\n  being enabled.  Some code runs faster in the Chrome V8 engine if this\n  option is disabled.  Does not negatively impact other major browsers.\n\n- `reduce_vars` (default: `true`) — Improve optimization on variables assigned with and\n  used as constant values.\n\n- `rests` (default: `true`) — apply optimizations to rest parameters\n\n- `sequences` (default: `true`) — join consecutive simple statements using the\n  comma operator.  May be set to a positive integer to specify the maximum number\n  of consecutive comma sequences that will be generated. If this option is set to\n  `true` then the default `sequences` limit is `200`. Set option to `false` or `0`\n  to disable. The smallest `sequences` length is `2`. A `sequences` value of `1`\n  is grandfathered to be equivalent to `true` and as such means `200`. On rare\n  occasions the default sequences limit leads to very slow compress times in which\n  case a value of `20` or less is recommended.\n\n- `side_effects` (default: `true`) — drop extraneous code which does not affect\n  outcome of runtime execution.\n\n- `spreads` (default: `true`) — flatten spread expressions.\n\n- `strings` (default: `true`) — compact string concatenations.\n\n- `switches` (default: `true`) — de-duplicate and remove unreachable `switch` branches\n\n- `templates` (default: `true`) — compact template literals by embedding expressions\n  and/or converting to string literals, e.g. `` `foo ${42}` → \"foo 42\"``\n\n- `top_retain` (default: `null`) — prevent specific toplevel functions and\n  variables from `unused` removal (can be array, comma-separated, RegExp or\n  function. Implies `toplevel`)\n\n- `toplevel` (default: `false`) — drop unreferenced functions (`\"funcs\"`) and/or\n  variables (`\"vars\"`) in the top level scope (`false` by default, `true` to drop\n  both unreferenced functions and variables)\n\n- `typeofs` (default: `true`) — compress `typeof` expressions, e.g.\n  `typeof foo == \"undefined\" → void 0 === foo`\n\n- `unsafe` (default: `false`) — apply \"unsafe\" transformations (discussion below)\n\n- `unsafe_comps` (default: `false`) — assume operands cannot be (coerced to) `NaN`\n  in numeric comparisons, e.g. `a <= b`. In addition, expressions involving `in`\n  or `instanceof` would never throw.\n\n- `unsafe_Function` (default: `false`) — compress and mangle `Function(args, code)`\n  when both `args` and `code` are string literals.\n\n- `unsafe_math` (default: `false`) — optimize numerical expressions like\n  `2 * x * 3` into `6 * x`, which may give imprecise floating point results.\n\n- `unsafe_proto` (default: `false`) — optimize expressions like\n  `Array.prototype.slice.call(a)` into `[].slice.call(a)`\n\n- `unsafe_regexp` (default: `false`) — enable substitutions of variables with\n  `RegExp` values the same way as if they are constants.\n\n- `unsafe_undefined` (default: `false`) — substitute `void 0` if there is a\n  variable named `undefined` in scope (variable name will be mangled, typically\n  reduced to a single character)\n\n- `unused` (default: `true`) — drop unreferenced functions and variables (simple\n  direct variable assignments do not count as references unless set to `\"keep_assign\"`)\n\n- `varify` (default: `true`) — convert block-scoped declarations into `var`\n  whenever safe to do so\n\n- `yields` (default: `true`) — apply optimizations to `yield` expressions\n\n## Mangle options\n\n- `eval` (default: `false`) — Pass `true` to mangle names visible in scopes\n  where `eval` or `with` are used.\n\n- `reserved` (default: `[]`) — Pass an array of identifiers that should be\n  excluded from mangling. Example: `[\"foo\", \"bar\"]`.\n\n- `toplevel` (default: `false`) — Pass `true` to mangle names declared in the\n  top level scope.\n\nExamples:\n\n```javascript\n// test.js\nvar globalVar;\nfunction funcName(firstLongName, anotherLongName) {\n    var myVariable = firstLongName +  anotherLongName;\n}\n```\n```javascript\nvar code = fs.readFileSync(\"test.js\", \"utf8\");\n\nUglifyJS.minify(code).code;\n// 'function funcName(a,n){}var globalVar;'\n\nUglifyJS.minify(code, { mangle: { reserved: ['firstLongName'] } }).code;\n// 'function funcName(firstLongName,a){}var globalVar;'\n\nUglifyJS.minify(code, { mangle: { toplevel: true } }).code;\n// 'function n(n,a){}var a;'\n```\n\n### Mangle properties options\n\n- `builtins` (default: `false`) — Use `true` to allow the mangling of built-in\n  properties of JavaScript API. Not recommended to override this setting.\n\n- `debug` (default: `false`) — Mangle names with the original name still present.\n  Pass an empty string `\"\"` to enable, or a non-empty string to set the debug suffix.\n\n- `domprops` (default: `false`) — Use `true` to allow the mangling of properties\n  commonly found in Document Object Model. Not recommended to override this setting.\n\n- `globals` (default: `false`) — Use `true` to mangle properties of global object\n  alongside undeclared variables.\n\n- `keep_fargs` (default: `false`) — Use `true` to prevent mangling of function\n  arguments.\n\n- `keep_quoted` (default: `false`) — Only mangle unquoted property names.\n\n- `regex` (default: `null`) — Pass a RegExp literal to only mangle property\n  names matching the regular expression.\n\n- `reserved` (default: `[]`) — Do not mangle property names listed in the\n  `reserved` array.\n\n## Output options\n\nThe code generator tries to output shortest code possible by default.  In\ncase you want beautified output, pass `--beautify` (`-b`).  Optionally you\ncan pass additional arguments that control the code output:\n\n- `annotations` (default: `false`) — pass `true` to retain comment annotations\n  `/*@__PURE__*/` or `/*#__PURE__*/`, otherwise they will be discarded even if\n  `comments` is set.\n\n- `ascii_only` (default: `false`) — escape Unicode characters in strings and\n  regexps (affects directives with non-ascii characters becoming invalid)\n\n- `beautify` (default: `true`) — whether to actually beautify the output.\n  Passing `-b` will set this to true. Use `-O` if you want to generate minified\n  code and specify additional arguments.\n\n- `braces` (default: `false`) — always insert braces in `if`, `for`,\n  `do`, `while` or `with` statements, even if their body is a single\n  statement.\n\n- `comments` (default: `false`) — pass `true` or `\"all\"` to preserve all\n  comments, `\"some\"` to preserve multi-line comments that contain `@cc_on`,\n  `@license`, or `@preserve` (case-insensitive), a regular expression string\n  (e.g. `/^!/`), or a function which returns `boolean`, e.g.\n  ```javascript\n  function(node, comment) {\n      return comment.value.indexOf(\"@type \" + node.TYPE) >= 0;\n  }\n  ```\n\n- `extendscript` (default: `false`) — enable workarounds for Adobe ExtendScript\n  bugs\n\n- `galio` (default: `false`) — enable workarounds for ANT Galio bugs\n\n- `indent_level` (default: `4`) — indent by specified number of spaces or the\n  exact whitespace sequence supplied, e.g. `\"\\t\"`.\n\n- `indent_start` (default: `0`) — prefix all lines by whitespace sequence\n  specified in the same format as `indent_level`.\n\n- `inline_script` (default: `true`) — escape HTML comments and the slash in\n  occurrences of `</script>` in strings\n\n- `keep_quoted_props` (default: `false`) — when turned on, prevents stripping\n  quotes from property names in object literals.\n\n- `max_line_len` (default: `false`) — maximum line length (for uglified code)\n\n- `preamble` (default: `null`) — when passed it must be a string and\n  it will be prepended to the output literally.  The source map will\n  adjust for this text.  Can be used to insert a comment containing\n  licensing information, for example.\n\n- `preserve_line` (default: `false`) — pass `true` to retain line numbering on\n  a best effort basis.\n\n- `quote_keys` (default: `false`) — pass `true` to quote all keys in literal\n  objects\n\n- `quote_style` (default: `0`) — preferred quote style for strings (affects\n  quoted property names and directives as well):\n  - `0` — prefers double quotes, switches to single quotes when there are\n    more double quotes in the string itself. `0` is best for gzip size.\n  - `1` — always use single quotes\n  - `2` — always use double quotes\n  - `3` — always use the original quotes\n\n- `semicolons` (default: `true`) — separate statements with semicolons.  If\n  you pass `false` then whenever possible we will use a newline instead of a\n  semicolon, leading to more readable output of uglified code (size before\n  gzip could be smaller; size after gzip insignificantly larger).\n\n- `shebang` (default: `true`) — preserve shebang `#!` in preamble (bash scripts)\n\n- `width` (default: `80`) — only takes effect when beautification is on, this\n  specifies an (orientative) line width that the beautifier will try to\n  obey.  It refers to the width of the line text (excluding indentation).\n  It doesn't work very well currently, but it does make the code generated\n  by UglifyJS more readable.\n\n- `wrap_iife` (default: `false`) — pass `true` to wrap immediately invoked\n  function expressions. See\n  [#640](https://github.com/mishoo/UglifyJS/issues/640) for more details.\n\n# Miscellaneous\n\n### Keeping copyright notices or other comments\n\nYou can pass `--comments` to retain certain comments in the output.  By\ndefault it will keep JSDoc-style comments that contain \"@preserve\",\n\"@license\" or \"@cc_on\" (conditional compilation for IE).  You can pass\n`--comments all` to keep all the comments, or a valid JavaScript regexp to\nkeep only comments that match this regexp.  For example `--comments /^!/`\nwill keep comments like `/*! Copyright Notice */`.\n\nNote, however, that there might be situations where comments are lost.  For\nexample:\n```javascript\nfunction f() {\n    /** @preserve Foo Bar */\n    function g() {\n        // this function is never called\n    }\n    return something();\n}\n```\n\nEven though it has \"@preserve\", the comment will be lost because the inner\nfunction `g` (which is the AST node to which the comment is attached to) is\ndiscarded by the compressor as not referenced.\n\nThe safest comments where to place copyright information (or other info that\nneeds to be kept in the output) are comments attached to toplevel nodes.\n\n### The `unsafe` `compress` option\n\nIt enables some transformations that *might* break code logic in certain\ncontrived cases, but should be fine for most code.  You might want to try it\non your own code, it should reduce the minified size.  Here's what happens\nwhen this flag is on:\n\n- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[ 1, 2, 3 ]`\n- `new Object()` → `{}`\n- `String(exp)` or `exp.toString()` → `\"\" + exp`\n- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`\n\n### Conditional compilation\n\nYou can use the `--define` (`-d`) switch in order to declare global\nvariables that UglifyJS will assume to be constants (unless defined in\nscope).  For example if you pass `--define DEBUG=false` then, coupled with\ndead code removal UglifyJS will discard the following from the output:\n```javascript\nif (DEBUG) {\n    console.log(\"debug stuff\");\n}\n```\n\nYou can specify nested constants in the form of `--define env.DEBUG=false`.\n\nUglifyJS will warn about the condition being always false and about dropping\nunreachable code; for now there is no option to turn off only this specific\nwarning, you can pass `warnings=false` to turn off *all* warnings.\n\nAnother way of doing that is to declare your globals as constants in a\nseparate file and include it into the build.  For example you can have a\n`build/defines.js` file with the following:\n```javascript\nvar DEBUG = false;\nvar PRODUCTION = true;\n// etc.\n```\n\nand build your code like this:\n\n    uglifyjs build/defines.js js/foo.js js/bar.js... -c\n\nUglifyJS will notice the constants and, since they cannot be altered, it\nwill evaluate references to them to the value itself and drop unreachable\ncode as usual.  The build will contain the `const` declarations if you use\nthem. If you are targeting < ES6 environments which does not support `const`,\nusing `var` with `reduce_vars` (enabled by default) should suffice.\n\n### Conditional compilation API\n\nYou can also use conditional compilation via the programmatic API. With the difference that the\nproperty name is `global_defs` and is a compressor property:\n\n```javascript\nvar result = UglifyJS.minify(fs.readFileSync(\"input.js\", \"utf8\"), {\n    compress: {\n        dead_code: true,\n        global_defs: {\n            DEBUG: false\n        }\n    }\n});\n```\n\nTo replace an identifier with an arbitrary non-constant expression it is\nnecessary to prefix the `global_defs` key with `\"@\"` to instruct UglifyJS\nto parse the value as an expression:\n```javascript\nUglifyJS.minify(\"alert('hello');\", {\n    compress: {\n        global_defs: {\n            \"@alert\": \"console.log\"\n        }\n    }\n}).code;\n// returns: 'console.log(\"hello\");'\n```\n\nOtherwise it would be replaced as string literal:\n```javascript\nUglifyJS.minify(\"alert('hello');\", {\n    compress: {\n        global_defs: {\n            \"alert\": \"console.log\"\n        }\n    }\n}).code;\n// returns: '\"console.log\"(\"hello\");'\n```\n\n### Using native Uglify AST with `minify()`\n```javascript\n// example: parse only, produce native Uglify AST\n\nvar result = UglifyJS.minify(code, {\n    parse: {},\n    compress: false,\n    mangle: false,\n    output: {\n        ast: true,\n        code: false  // optional - faster if false\n    }\n});\n\n// result.ast contains native Uglify AST\n```\n```javascript\n// example: accept native Uglify AST input and then compress and mangle\n//          to produce both code and native AST.\n\nvar result = UglifyJS.minify(ast, {\n    compress: {},\n    mangle: {},\n    output: {\n        ast: true,\n        code: true  // optional - faster if false\n    }\n});\n\n// result.ast contains native Uglify AST\n// result.code contains the minified code in string form.\n```\n\n### Working with Uglify AST\n\nTransversal and transformation of the native AST can be performed through\n[`TreeWalker`](https://github.com/mishoo/UglifyJS/blob/master/lib/ast.js) and\n[`TreeTransformer`](https://github.com/mishoo/UglifyJS/blob/master/lib/transform.js)\nrespectively.\n\n### ESTree / SpiderMonkey AST\n\nUglifyJS has its own abstract syntax tree format; for\n[practical reasons](http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/)\nwe can't easily change to using the SpiderMonkey AST internally.  However,\nUglifyJS now has a converter which can import a SpiderMonkey AST.\n\nFor example [Acorn][acorn] is a super-fast parser that produces a\nSpiderMonkey AST.  It has a small CLI utility that parses one file and dumps\nthe AST in JSON on the standard output.  To use UglifyJS to mangle and\ncompress that:\n\n    acorn file.js | uglifyjs -p spidermonkey -m -c\n\nThe `-p spidermonkey` option tells UglifyJS that all input files are not\nJavaScript, but JS code described in SpiderMonkey AST in JSON.  Therefore we\ndon't use our own parser in this case, but just transform that AST into our\ninternal AST.\n\n### Use Acorn for parsing\n\nMore for fun, I added the `-p acorn` option which will use Acorn to do all\nthe parsing.  If you pass this option, UglifyJS will `require(\"acorn\")`.\n\nAcorn is really fast (e.g. 250ms instead of 380ms on some 650K code), but\nconverting the SpiderMonkey tree that Acorn produces takes another 150ms so\nin total it's a bit more than just using UglifyJS's own parser.\n\n[acorn]: https://github.com/ternjs/acorn\n[sm-spec]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k\n\n### Uglify Fast Minify Mode\n\nIt's not well known, but whitespace removal and symbol mangling accounts\nfor 95% of the size reduction in minified code for most JavaScript - not\nelaborate code transforms. One can simply disable `compress` to speed up\nUglify builds by 3 to 5 times.\n\n| d3.js | minify size | gzip size | minify time (seconds) |\n| --- | ---: | ---: | ---: |\n| original | 511,371 | 119,932 | - |\n| uglify-js@3.13.0 mangle=false, compress=false | 363,988 | 95,695 | 0.56 |\n| uglify-js@3.13.0 mangle=true, compress=false | 253,305 | 81,281 | 0.99 |\n| uglify-js@3.13.0 mangle=true, compress=true | 244,436 | 79,854 | 5.30 |\n\nTo enable fast minify mode from the CLI use:\n```\nuglifyjs file.js -m\n```\nTo enable fast minify mode with the API use:\n```javascript\nUglifyJS.minify(code, { compress: false, mangle: true });\n```\n\n### Source maps and debugging\n\nVarious `compress` transforms that simplify, rearrange, inline and remove code\nare known to have an adverse effect on debugging with source maps. This is\nexpected as code is optimized and mappings are often simply not possible as\nsome code no longer exists. For highest fidelity in source map debugging\ndisable the Uglify `compress` option and just use `mangle`.\n\n### Compiler assumptions\n\nTo allow for better optimizations, the compiler makes various assumptions:\n\n- The code does not rely on preserving its runtime performance characteristics.\n  Typically uglified code will run faster due to less instructions and easier\n  inlining, but may be slower on rare occasions for a specific platform, e.g.\n  see [`reduce_funcs`](#compress-options).\n- `.toString()` and `.valueOf()` don't have side effects, and for built-in\n  objects they have not been overridden.\n- `undefined`, `NaN` and `Infinity` have not been externally redefined.\n- `arguments.callee`, `arguments.caller` and `Function.prototype.caller` are not used.\n- The code doesn't expect the contents of `Function.prototype.toString()` or\n  `Error.prototype.stack` to be anything in particular.\n- Getting and setting properties on a plain object does not cause other side effects\n  (using `.watch()` or `Proxy`).\n- Object properties can be added, removed and modified (not prevented with\n  `Object.defineProperty()`, `Object.defineProperties()`, `Object.freeze()`,\n  `Object.preventExtensions()` or `Object.seal()`).\n- If array destructuring is present, index-like properties in `Array.prototype`\n  have not been overridden:\n  ```javascript\n  Object.prototype[0] = 42;\n  var [ a ] = [];\n  var { 0: b } = {};\n  // 42 undefined\n  console.log([][0], a);\n  // 42 42\n  console.log({}[0], b);\n  ```\n- Earlier versions of JavaScript will throw `SyntaxError` with the following:\n  ```javascript\n  ({\n      p: 42,\n      get p() {},\n  });\n  // SyntaxError: Object literal may not have data and accessor property with\n  //              the same name\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Iteration order of keys over an object which contains spread syntax in later\n  versions of Chrome and Node.js may be altered.\n- When `toplevel` is enabled, UglifyJS effectively assumes input code is wrapped\n  within `function(){ ... }`, thus forbids aliasing of declared global variables:\n  ```javascript\n  A = \"FAIL\";\n  var B = \"FAIL\";\n  // can be `global`, `self`, `window` etc.\n  var top = function() {\n      return this;\n  }();\n  // \"PASS\"\n  top.A = \"PASS\";\n  console.log(A);\n  // \"FAIL\" after compress and/or mangle\n  top.B = \"PASS\";\n  console.log(B);\n  ```\n- Use of `arguments` alongside destructuring as function parameters, e.g.\n  `function({}, arguments) {}` will result in `SyntaxError` in earlier versions\n  of Chrome and Node.js - UglifyJS may modify the input which in turn may\n  suppress those errors.\n- Earlier versions of Chrome and Node.js will throw `ReferenceError` with the\n  following:\n  ```javascript\n  var a;\n  try {\n      throw 42;\n  } catch ({\n      [a]: b,\n      // ReferenceError: a is not defined\n  }) {\n      let a;\n  }\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of JavaScript will throw `SyntaxError` with the following:\n  ```javascript\n  a => {\n      let a;\n  };\n  // SyntaxError: Identifier 'a' has already been declared\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of JavaScript will throw `SyntaxError` with the following:\n  ```javascript\n  try {\n      // ...\n  } catch ({ message: a }) {\n      var a;\n  }\n  // SyntaxError: Identifier 'a' has already been declared\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some versions of Chrome and Node.js will throw `ReferenceError` with the\n  following:\n  ```javascript\n  console.log(((a, b = function() {\n      return a;\n      // ReferenceError: a is not defined\n  }()) => b)());\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some arithmetic operations with `BigInt` may throw `TypeError`:\n  ```javascript\n  1n + 1;\n  // TypeError: can't convert BigInt to number\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some versions of JavaScript will throw `SyntaxError` with the\n  following:\n  ```javascript\n  console.log(String.raw`\\uFo`);\n  // SyntaxError: Invalid Unicode escape sequence\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some versions of JavaScript will throw `SyntaxError` with the\n  following:\n  ```javascript\n  try {} catch (e) {\n      for (var e of []);\n  }\n  // SyntaxError: Identifier 'e' has already been declared\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some versions of Chrome and Node.js will give incorrect results with the\n  following:\n  ```javascript\n  console.log({\n      ...{\n          set 42(v) {},\n          42: \"PASS\",\n      },\n  });\n  // Expected: { '42': 'PASS' }\n  // Actual:   { '42': undefined }\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of JavaScript will throw `SyntaxError` with the following:\n  ```javascript\n  var await;\n  class A {\n      static p = await;\n  }\n  // SyntaxError: Unexpected reserved word\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of JavaScript will throw `SyntaxError` with the following:\n  ```javascript\n  var async;\n  for (async of []);\n  // SyntaxError: The left-hand side of a for-of loop may not be 'async'.\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some versions of Chrome and Node.js will give incorrect results with the\n  following:\n  ```javascript\n  console.log({\n      ...console,\n      get 42() {\n          return \"FAIL\";\n      },\n      [42]: \"PASS\",\n  }[42], {\n      ...console,\n      get 42() {\n          return \"FAIL\";\n      },\n      42: \"PASS\",\n  }[42]);\n  // Expected: \"PASS PASS\"\n  // Actual:   \"PASS FAIL\"\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Earlier versions of JavaScript will throw `TypeError` with the following:\n  ```javascript\n  (function() {\n      {\n          const a = \"foo\";\n      }\n      {\n          const a = \"bar\";\n      }\n  })();\n  // TypeError: const 'a' has already been declared\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of Chrome and Node.js will give incorrect results with the\n  following:\n  ```javascript\n  try {\n      class A {\n          static 42;\n          static get 42() {}\n      }\n      console.log(\"PASS\");\n  } catch (e) {\n      console.log(\"FAIL\");\n  }\n  // Expected: \"PASS\"\n  // Actual:   \"FAIL\"\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Some versions of Chrome and Node.js will give incorrect results with the\n  following:\n  ```javascript\n  (async function(a) {\n      (function() {\n          var b = await => console.log(\"PASS\");\n          b();\n      })();\n  })().catch(console.error);\n  // Expected: \"PASS\"\n  // Actual:   SyntaxError: Unexpected reserved word\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of Chrome and Node.js will give incorrect results with the\n  following:\n  ```javascript\n  try {\n      f();\n      function f() {\n          throw 42;\n      }\n  } catch (e) {\n      console.log(typeof f, e);\n  }\n  // Expected: \"function 42\"\n  // Actual:   \"undefined 42\"\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Later versions of JavaScript will throw `SyntaxError` with the following:\n  ```javascript\n  \"use strict\";\n  console.log(function f() {\n      return f = \"PASS\";\n  }());\n  // Expected: \"PASS\"\n  // Actual:   TypeError: invalid assignment to const 'f'\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Adobe ExtendScript will give incorrect results with the following:\n  ```javascript\n  alert(true ? \"PASS\" : false ? \"FAIL\" : null);\n  // Expected: \"PASS\"\n  // Actual:   \"FAIL\"\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n- Adobe ExtendScript will give incorrect results with the following:\n  ```javascript\n  alert(42 ? null ? \"FAIL\" : \"PASS\" : \"FAIL\");\n  // Expected: \"PASS\"\n  // Actual:   SyntaxError: Expected: :\n  ```\n  UglifyJS may modify the input which in turn may suppress those errors.\n"
  },
  {
    "path": "bin/uglifyjs",
    "content": "#! /usr/bin/env node\n// -*- js -*-\n\n\"use strict\";\n\nrequire(\"../tools/tty\");\n\nvar fs = require(\"fs\");\nvar info = require(\"../package.json\");\nvar path = require(\"path\");\nvar UglifyJS = require(\"../tools/node\");\n\nvar skip_keys = [ \"cname\", \"fixed\", \"in_arg\", \"inlined\", \"length_read\", \"parent_scope\", \"redef\", \"scope\", \"unused\" ];\nvar truthy_keys = [ \"optional\", \"pure\", \"terminal\", \"uses_arguments\", \"uses_eval\", \"uses_with\" ];\n\nvar files = {};\nvar options = {};\nvar short_forms = {\n    b: \"beautify\",\n    c: \"compress\",\n    d: \"define\",\n    e: \"enclose\",\n    h: \"help\",\n    m: \"mangle\",\n    o: \"output\",\n    O: \"output-opts\",\n    p: \"parse\",\n    v: \"version\",\n    V: \"version\",\n};\nvar args = process.argv.slice(2);\nvar paths = [];\nvar output, nameCache;\nvar specified = {};\nwhile (args.length) {\n    var arg = args.shift();\n    if (arg[0] != \"-\") {\n        paths.push(arg);\n    } else if (arg == \"--\") {\n        paths = paths.concat(args);\n        break;\n    } else if (arg[1] == \"-\") {\n        process_option(arg.slice(2));\n    } else [].forEach.call(arg.slice(1), function(letter, index, arg) {\n        if (!(letter in short_forms)) fatal(\"invalid option -\" + letter);\n        process_option(short_forms[letter], index + 1 < arg.length);\n    });\n}\n\nfunction process_option(name, no_value) {\n    specified[name] = true;\n    switch (name) {\n      case \"help\":\n        switch (read_value()) {\n          case \"ast\":\n            print(UglifyJS.describe_ast());\n            break;\n          case \"options\":\n            var text = [];\n            var toplevels = [];\n            var padding = \"\";\n            var defaults = UglifyJS.default_options();\n            for (var name in defaults) {\n                var option = defaults[name];\n                if (option && typeof option == \"object\") {\n                    text.push(\"--\" + ({\n                        output: \"beautify\",\n                        sourceMap: \"source-map\",\n                    }[name] || name) + \" options:\");\n                    text.push(format_object(option));\n                    text.push(\"\");\n                } else {\n                    if (padding.length < name.length) padding = Array(name.length + 1).join(\" \");\n                    toplevels.push([ {\n                        keep_fargs: \"keep-fargs\",\n                        keep_fnames: \"keep-fnames\",\n                        nameCache: \"name-cache\",\n                    }[name] || name, option ]);\n                }\n            }\n            toplevels.forEach(function(tokens) {\n                text.push(\"--\" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);\n            });\n            print(text.join(\"\\n\"));\n            break;\n          default:\n            print([\n                \"Usage: uglifyjs [files...] [options]\",\n                \"\",\n                \"Options:\",\n                \"  -h, --help                               Print usage information.\",\n                \"                                           `--help options` for details on available options.\",\n                \"  -v, -V, --version                        Print version number.\",\n                \"  -p, --parse <options>                    Specify parser options.\",\n                \"  -c, --compress [options]                 Enable compressor/specify compressor options.\",\n                \"  -m, --mangle [options]                   Mangle names/specify mangler options.\",\n                \"  --mangle-props [options]                 Mangle properties/specify mangler options.\",\n                \"  -b, --beautify [options]                 Beautify output/specify output options.\",\n                \"  -O, --output-opts <options>              Output options (beautify disabled).\",\n                \"  -o, --output <file>                      Output file (default STDOUT).\",\n                \"  --annotations                            Process and preserve comment annotations.\",\n                \"  --no-annotations                         Ignore and discard comment annotations.\",\n                \"  --comments [filter]                      Preserve copyright comments in the output.\",\n                \"  --config-file <file>                     Read minify() options from JSON file.\",\n                \"  -d, --define <expr>[=value]              Global definitions.\",\n                \"  -e, --enclose [arg[,...][:value[,...]]]  Embed everything in a big function, with configurable argument(s) & value(s).\",\n                \"  --expression                             Parse a single expression, rather than a program.\",\n                \"  --ie                                     Support non-standard Internet Explorer.\",\n                \"  --keep-fargs                             Do not mangle/drop function arguments.\",\n                \"  --keep-fnames                            Do not mangle/drop function names. Useful for code relying on Function.prototype.name.\",\n                \"  --module                                 Process input as ES module (implies --toplevel).\",\n                \"  --no-module                              Process input with improved JavaScript compatibility.\",\n                \"  --name-cache <file>                      File to hold mangled name mappings.\",\n                \"  --rename                                 Force symbol expansion.\",\n                \"  --no-rename                              Disable symbol expansion.\",\n                \"  --self                                   Build UglifyJS as a library (implies --wrap UglifyJS)\",\n                \"  --source-map [options]                   Enable source map/specify source map options.\",\n                \"  --timings                                Display operations run time on STDERR.\",\n                \"  --toplevel                               Compress and/or mangle variables in toplevel scope.\",\n                \"  --v8                                     Support non-standard Chrome & Node.js.\",\n                \"  --validate                               Perform validation during AST manipulations.\",\n                \"  --verbose                                Print diagnostic messages.\",\n                \"  --warn                                   Print warning messages.\",\n                \"  --webkit                                 Support non-standard Safari/Webkit.\",\n                \"  --wrap <name>                            Embed everything as a function with “exports” corresponding to “name” globally.\",\n                \"\",\n                \"(internal debug use only)\",\n                \"  --in-situ                                Warning: replaces original source files with minified output.\",\n                \"  --reduce-test                            Reduce a standalone test case (assumes cloned repository).\",\n            ].join(\"\\n\"));\n        }\n        process.exit();\n      case \"version\":\n        print(info.name + \" \" + info.version);\n        process.exit();\n      case \"config-file\":\n        var config = JSON.parse(read_file(read_value(true)));\n        if (config.mangle && config.mangle.properties && config.mangle.properties.regex) {\n            config.mangle.properties.regex = UglifyJS.parse(config.mangle.properties.regex, {\n                expression: true,\n            }).value;\n        }\n        for (var key in config) if (!(key in options)) options[key] = config[key];\n        break;\n      case \"compress\":\n      case \"mangle\":\n        options[name] = parse_js(read_value(), options[name]);\n        break;\n      case \"source-map\":\n        options.sourceMap = parse_js(read_value(), options.sourceMap);\n        break;\n      case \"enclose\":\n        options[name] = read_value();\n        break;\n      case \"annotations\":\n      case \"expression\":\n      case \"ie\":\n      case \"ie8\":\n      case \"timings\":\n      case \"toplevel\":\n      case \"v8\":\n      case \"validate\":\n      case \"webkit\":\n        options[name] = true;\n        break;\n      case \"no-annotations\":\n        options.annotations = false;\n        break;\n      case \"keep-fargs\":\n        options.keep_fargs = true;\n        break;\n      case \"keep-fnames\":\n        options.keep_fnames = true;\n        break;\n      case \"wrap\":\n        options[name] = read_value(true);\n        break;\n      case \"verbose\":\n        options.warnings = \"verbose\";\n        break;\n      case \"warn\":\n        if (!options.warnings) options.warnings = true;\n        break;\n      case \"beautify\":\n        options.output = parse_js(read_value(), options.output);\n        if (!(\"beautify\" in options.output)) options.output.beautify = true;\n        break;\n      case \"output-opts\":\n        options.output = parse_js(read_value(true), options.output);\n        break;\n      case \"comments\":\n        if (typeof options.output != \"object\") options.output = {};\n        options.output.comments = read_value();\n        if (options.output.comments === true) options.output.comments = \"some\";\n        break;\n      case \"define\":\n        if (typeof options.compress != \"object\") options.compress = {};\n        options.compress.global_defs = parse_js(read_value(true), options.compress.global_defs, \"define\");\n        break;\n      case \"mangle-props\":\n        if (typeof options.mangle != \"object\") options.mangle = {};\n        options.mangle.properties = parse_js(read_value(), options.mangle.properties);\n        break;\n      case \"module\":\n        options.module = true;\n        break;\n      case \"no-module\":\n        options.module = false;\n        break;\n      case \"name-cache\":\n        nameCache = read_value(true);\n        options.nameCache = JSON.parse(read_file(nameCache, \"{}\"));\n        break;\n      case \"output\":\n        output = read_value(true);\n        break;\n      case \"parse\":\n        options.parse = parse_js(read_value(true), options.parse);\n        break;\n      case \"rename\":\n        options.rename = true;\n        break;\n      case \"no-rename\":\n        options.rename = false;\n        break;\n      case \"in-situ\":\n      case \"reduce-test\":\n      case \"self\":\n        break;\n      default:\n        fatal(\"invalid option --\" + name);\n    }\n\n    function read_value(required) {\n        if (no_value || !args.length || args[0][0] == \"-\") {\n            if (required) fatal(\"missing option argument for --\" + name);\n            return true;\n        }\n        return args.shift();\n    }\n}\nif (!output && options.sourceMap && options.sourceMap.url != \"inline\") fatal(\"cannot write source map to STDOUT\");\nif (specified[\"beautify\"] && specified[\"output-opts\"]) fatal(\"--beautify cannot be used with --output-opts\");\n[ \"compress\", \"mangle\" ].forEach(function(name) {\n    if (!(name in options)) options[name] = false;\n});\nif (/^ast|spidermonkey$/.test(output)) {\n    if (typeof options.output != \"object\") options.output = {};\n    options.output.ast = true;\n    options.output.code = false;\n}\nif (options.parse && (options.parse.acorn || options.parse.spidermonkey)\n    && options.sourceMap && options.sourceMap.content == \"inline\") {\n    fatal(\"inline source map only works with built-in parser\");\n}\nif (options.warnings) {\n    UglifyJS.AST_Node.log_function(print_error, options.warnings == \"verbose\");\n    delete options.warnings;\n}\nvar convert_path = function(name) {\n    return name;\n};\nif (typeof options.sourceMap == \"object\" && \"base\" in options.sourceMap) {\n    convert_path = function() {\n        var base = options.sourceMap.base;\n        delete options.sourceMap.base;\n        return function(name) {\n            return path.relative(base, name);\n        };\n    }();\n}\nif (specified[\"self\"]) {\n    if (paths.length) UglifyJS.AST_Node.warn(\"Ignoring input files since --self was passed\");\n    if (!options.wrap) options.wrap = \"UglifyJS\";\n    paths = UglifyJS.FILES;\n} else if (paths.length) {\n    paths = simple_glob(paths);\n}\nif (specified[\"in-situ\"]) {\n    if (output && output != \"spidermonkey\" || specified[\"reduce-test\"] || specified[\"self\"]) {\n        fatal(\"incompatible options specified\");\n    }\n    paths.forEach(function(name) {\n        print(name);\n        if (/^ast|spidermonkey$/.test(name)) fatal(\"invalid file name specified\");\n        files = {};\n        files[convert_path(name)] = read_file(name);\n        output = name;\n        run();\n    });\n} else if (paths.length) {\n    paths.forEach(function(name) {\n        files[convert_path(name)] = read_file(name);\n    });\n    run();\n} else {\n    var timerId = process.stdin.isTTY && process.argv.length < 3 && setTimeout(function() {\n        print_error(\"Waiting for input... (use `--help` to print usage information)\");\n    }, 1500);\n    var chunks = [];\n    process.stdin.setEncoding(\"utf8\");\n    process.stdin.once(\"data\", function() {\n        clearTimeout(timerId);\n    }).on(\"data\", process.stdin.isTTY ? function(chunk) {\n        // emulate console input termination via Ctrl+D / Ctrl+Z\n        var match = /[\\x04\\x1a]\\r?\\n?$/.exec(chunk);\n        if (match) {\n            chunks.push(chunk.slice(0, -match[0].length));\n            process.stdin.pause();\n            process.stdin.emit(\"end\");\n        } else {\n            chunks.push(chunk);\n        }\n    } : function(chunk) {\n        chunks.push(chunk);\n    }).once(\"end\", function() {\n        files = { STDIN: chunks.join(\"\") };\n        run();\n    });\n    process.stdin.resume();\n}\n\nfunction convert_ast(fn) {\n    return UglifyJS.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));\n}\n\nfunction run() {\n    var content = options.sourceMap && options.sourceMap.content;\n    if (content && content != \"inline\") {\n        UglifyJS.AST_Node.info(\"Using input source map: {content}\", {\n            content : content,\n        });\n        options.sourceMap.content = read_file(content, content);\n    }\n    try {\n        if (options.parse) {\n            if (options.parse.acorn) {\n                var annotations = Object.create(null);\n                files = convert_ast(function(toplevel, name) {\n                    var content = files[name];\n                    var list = annotations[name] = [];\n                    var prev = -1;\n                    return require(\"acorn\").parse(content, {\n                        allowHashBang: true,\n                        ecmaVersion: \"latest\",\n                        locations: true,\n                        onComment: function(block, text, start, end) {\n                            var match = /[@#]__PURE__/.exec(text);\n                            if (!match) {\n                                if (start != prev) return;\n                                match = [ list[prev] ];\n                            }\n                            while (/\\s/.test(content[end])) end++;\n                            list[end] = match[0];\n                            prev = end;\n                        },\n                        preserveParens: true,\n                        program: toplevel,\n                        sourceFile: name,\n                        sourceType: \"module\",\n                    });\n                });\n                files.walk(new UglifyJS.TreeWalker(function(node) {\n                    if (!(node instanceof UglifyJS.AST_Call)) return;\n                    var list = annotations[node.start.file];\n                    var pure = list[node.start.pos];\n                    if (!pure) {\n                        var tokens = node.start.parens;\n                        if (tokens) for (var i = 0; !pure && i < tokens.length; i++) {\n                            pure = list[tokens[i].pos];\n                        }\n                    }\n                    if (pure) node.pure = pure;\n                }));\n            } else if (options.parse.spidermonkey) {\n                files = convert_ast(function(toplevel, name) {\n                    var obj = JSON.parse(files[name]);\n                    if (!toplevel) return obj;\n                    toplevel.body = toplevel.body.concat(obj.body);\n                    return toplevel;\n                });\n            }\n        }\n    } catch (ex) {\n        fatal(ex);\n    }\n    var result;\n    if (specified[\"reduce-test\"]) {\n        // load on demand - assumes cloned repository\n        var reduce_test = require(\"../test/reduce\");\n        if (Object.keys(files).length != 1) fatal(\"can only test on a single file\");\n        result = reduce_test(files[Object.keys(files)[0]], options, {\n            log: print_error,\n            verbose: true,\n        });\n    } else {\n        result = UglifyJS.minify(files, options);\n    }\n    if (result.error) {\n        var ex = result.error;\n        if (ex.name == \"SyntaxError\") {\n            print_error(\"Parse error at \" + ex.filename + \":\" + ex.line + \",\" + ex.col);\n            var file = files[ex.filename];\n            if (file) {\n                var col = ex.col;\n                var lines = file.split(/\\r?\\n/);\n                var line = lines[ex.line - 1];\n                if (!line && !col) {\n                    line = lines[ex.line - 2];\n                    col = line.length;\n                }\n                if (line) {\n                    var limit = 70;\n                    if (col > limit) {\n                        line = line.slice(col - limit);\n                        col = limit;\n                    }\n                    print_error(line.slice(0, 80));\n                    print_error(line.slice(0, col).replace(/\\S/g, \" \") + \"^\");\n                }\n            }\n        } else if (ex.defs) {\n            print_error(\"Supported options:\");\n            print_error(format_object(ex.defs));\n        }\n        fatal(ex);\n    } else if (output == \"ast\") {\n        if (!options.compress && !options.mangle) {\n            var toplevel = result.ast;\n            if (!(toplevel instanceof UglifyJS.AST_Toplevel)) {\n                if (!(toplevel instanceof UglifyJS.AST_Statement)) toplevel = new UglifyJS.AST_SimpleStatement({\n                    body: toplevel,\n                });\n                toplevel = new UglifyJS.AST_Toplevel({\n                    body: [ toplevel ],\n                });\n            }\n            toplevel.figure_out_scope({});\n        }\n        print(JSON.stringify(result.ast, function(key, value) {\n            if (value) switch (key) {\n              case \"enclosed\":\n                return value.length ? value.map(symdef) : undefined;\n              case \"functions\":\n              case \"globals\":\n              case \"variables\":\n                return value.size() ? value.map(symdef) : undefined;\n              case \"thedef\":\n                return symdef(value);\n            }\n            if (skip_property(key, value)) return;\n            if (value instanceof UglifyJS.AST_Token) return;\n            if (value instanceof UglifyJS.Dictionary) return;\n            if (value instanceof UglifyJS.AST_Node) {\n                var result = {\n                    _class: \"AST_\" + value.TYPE\n                };\n                value.CTOR.PROPS.forEach(function(prop) {\n                    result[prop] = value[prop];\n                });\n                return result;\n            }\n            return value;\n        }, 2));\n    } else if (output == \"spidermonkey\") {\n        print(JSON.stringify(result.ast.to_mozilla_ast(), null, 2));\n    } else if (output) {\n        var code;\n        if (result.ast) {\n            var output_options = {};\n            for (var name in UglifyJS.default_options(\"output\")) {\n                if (name in options) output_options[name] = options[name];\n            }\n            for (var name in options.output) {\n                if (!/^ast|code$/.test(name)) output_options[name] = options.output[name];\n            }\n            code = UglifyJS.AST_Node.from_mozilla_ast(result.ast.to_mozilla_ast()).print_to_string(output_options);\n        } else {\n            code = result.code;\n        }\n        fs.writeFileSync(output, code);\n        if (result.map) fs.writeFileSync(output + \".map\", result.map);\n    } else {\n        print(result.code);\n    }\n    if (nameCache) fs.writeFileSync(nameCache, JSON.stringify(options.nameCache));\n    if (result.timings) for (var phase in result.timings) {\n        print_error(\"- \" + phase + \": \" + result.timings[phase].toFixed(3) + \"s\");\n    }\n}\n\nfunction fatal(message) {\n    if (message instanceof Error) {\n        message = message.stack.replace(/^\\S*?Error:/, \"ERROR:\")\n    } else {\n        message = \"ERROR: \" + message;\n    }\n    print_error(message);\n    process.exit(1);\n}\n\n// A file glob function that only supports \"*\" and \"?\" wildcards in the basename.\n// Example: \"foo/bar/*baz??.*.js\"\n// Argument `paths` must be an array of strings.\n// Returns an array of strings. Garbage in, garbage out.\nfunction simple_glob(paths) {\n    return paths.reduce(function(paths, glob) {\n        if (/\\*|\\?/.test(glob)) {\n            var dir = path.dirname(glob);\n            try {\n                var entries = fs.readdirSync(dir).filter(function(name) {\n                    try {\n                        return fs.statSync(path.join(dir, name)).isFile();\n                    } catch (ex) {\n                        return false;\n                    }\n                });\n            } catch (ex) {}\n            if (entries) {\n                var pattern = \"^\" + path.basename(glob)\n                    .replace(/[.+^$[\\]\\\\(){}]/g, \"\\\\$&\")\n                    .replace(/\\*/g, \"[^/\\\\\\\\]*\")\n                    .replace(/\\?/g, \"[^/\\\\\\\\]\") + \"$\";\n                var mod = process.platform === \"win32\" ? \"i\" : \"\";\n                var rx = new RegExp(pattern, mod);\n                var results = entries.filter(function(name) {\n                    return rx.test(name);\n                }).sort().map(function(name) {\n                    return path.join(dir, name);\n                });\n                if (results.length) {\n                    [].push.apply(paths, results);\n                    return paths;\n                }\n            }\n        }\n        paths.push(glob);\n        return paths;\n    }, []);\n}\n\nfunction read_file(path, default_value) {\n    try {\n        return fs.readFileSync(path, \"utf8\");\n    } catch (ex) {\n        if (ex.code == \"ENOENT\" && default_value != null) return default_value;\n        fatal(ex);\n    }\n}\n\nfunction parse_js(value, options, flag) {\n    if (!options || typeof options != \"object\") options = Object.create(null);\n    if (typeof value == \"string\") try {\n        UglifyJS.parse(value, {\n            expression: true\n        }).walk(new UglifyJS.TreeWalker(function(node) {\n            if (node instanceof UglifyJS.AST_Assign) {\n                var name = node.left.print_to_string();\n                var value = node.right;\n                if (flag) {\n                    options[name] = value;\n                } else if (value instanceof UglifyJS.AST_Array) {\n                    options[name] = value.elements.map(to_string);\n                } else {\n                    options[name] = to_string(value);\n                }\n                return true;\n            }\n            if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) {\n                var name = node.print_to_string();\n                options[name] = true;\n                return true;\n            }\n            if (!(node instanceof UglifyJS.AST_Sequence)) throw node;\n\n            function to_string(value) {\n                return value instanceof UglifyJS.AST_Constant ? value.value : value.print_to_string({\n                    quote_keys: true\n                });\n            }\n        }));\n    } catch (ex) {\n        if (flag) {\n            fatal(\"cannot parse arguments for '\" + flag + \"': \" + value);\n        } else {\n            options[value] = null;\n        }\n    }\n    return options;\n}\n\nfunction skip_property(key, value) {\n    return skip_keys.indexOf(key) >= 0\n        // only skip truthy_keys if their value is falsy\n        || truthy_keys.indexOf(key) >= 0 && !value;\n}\n\nfunction symdef(def) {\n    var ret = (1e6 + def.id) + \" \" + def.name;\n    if (def.mangled_name) ret += \" \" + def.mangled_name;\n    return ret;\n}\n\nfunction format_object(obj) {\n    var lines = [];\n    var padding = \"\";\n    Object.keys(obj).map(function(name) {\n        if (padding.length < name.length) padding = Array(name.length + 1).join(\" \");\n        return [ name, JSON.stringify(obj[name]) ];\n    }).forEach(function(tokens) {\n        lines.push(\"  \" + tokens[0] + padding.slice(tokens[0].length - 2) + tokens[1]);\n    });\n    return lines.join(\"\\n\");\n}\n\nfunction print_error(msg) {\n    process.stderr.write(msg);\n    process.stderr.write(\"\\n\");\n}\n\nfunction print(txt) {\n    process.stdout.write(txt);\n    process.stdout.write(\"\\n\");\n}\n"
  },
  {
    "path": "lib/ast.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction DEFNODE(type, props, methods, base) {\n    if (typeof base === \"undefined\") base = AST_Node;\n    props = props ? props.split(/\\s+/) : [];\n    var self_props = props;\n    if (base && base.PROPS) props = props.concat(base.PROPS);\n    var code = [\n        \"return function AST_\", type, \"(props){\",\n        // not essential, but speeds up compress by a few percent\n        \"this._bits=0;\",\n        \"if(props){\",\n    ];\n    props.forEach(function(prop) {\n        code.push(\"this.\", prop, \"=props.\", prop, \";\");\n    });\n    code.push(\"}\");\n    var proto = Object.create(base && base.prototype);\n    if (methods.initialize || proto.initialize) code.push(\"this.initialize();\");\n    code.push(\"};\");\n    var ctor = new Function(code.join(\"\"))();\n    ctor.prototype = proto;\n    ctor.prototype.CTOR = ctor;\n    ctor.prototype.TYPE = ctor.TYPE = type;\n    if (base) {\n        ctor.BASE = base;\n        base.SUBCLASSES.push(ctor);\n    }\n    ctor.DEFMETHOD = function(name, method) {\n        this.prototype[name] = method;\n    };\n    ctor.PROPS = props;\n    ctor.SELF_PROPS = self_props;\n    ctor.SUBCLASSES = [];\n    for (var name in methods) if (HOP(methods, name)) {\n        if (/^\\$/.test(name)) {\n            ctor[name.substr(1)] = methods[name];\n        } else {\n            ctor.DEFMETHOD(name, methods[name]);\n        }\n    }\n    if (typeof exports !== \"undefined\") exports[\"AST_\" + type] = ctor;\n    return ctor;\n}\n\nvar AST_Token = DEFNODE(\"Token\", \"type value line col pos endline endcol endpos nlb comments_before comments_after file raw\", {\n}, null);\n\nvar AST_Node = DEFNODE(\"Node\", \"start end\", {\n    _clone: function(deep) {\n        if (deep) {\n            var self = this.clone();\n            return self.transform(new TreeTransformer(function(node) {\n                if (node !== self) {\n                    return node.clone(true);\n                }\n            }));\n        }\n        return new this.CTOR(this);\n    },\n    clone: function(deep) {\n        return this._clone(deep);\n    },\n    $documentation: \"Base class of all AST nodes\",\n    $propdoc: {\n        start: \"[AST_Token] The first token of this node\",\n        end: \"[AST_Token] The last token of this node\"\n    },\n    equals: function(node) {\n        return this.TYPE == node.TYPE && this._equals(node);\n    },\n    walk: function(visitor) {\n        visitor.visit(this);\n    },\n    _validate: function() {\n        if (this.TYPE == \"Node\") throw new Error(\"should not instantiate AST_Node\");\n    },\n    validate: function() {\n        var ctor = this.CTOR;\n        do {\n            ctor.prototype._validate.call(this);\n        } while (ctor = ctor.BASE);\n    },\n    validate_ast: function() {\n        var marker = {};\n        this.walk(new TreeWalker(function(node) {\n            if (node.validate_visited === marker) {\n                throw new Error(string_template(\"cannot reuse AST_{TYPE} from [{start}]\", node));\n            }\n            node.validate_visited = marker;\n        }));\n    },\n}, null);\n\nDEF_BITPROPS(AST_Node, [\n    // AST_Node\n    \"_optimized\",\n    \"_squeezed\",\n    // AST_Call\n    \"call_only\",\n    // AST_Lambda\n    \"collapse_scanning\",\n    // AST_SymbolRef\n    \"defined\",\n    \"evaluating\",\n    \"falsy\",\n    // AST_SymbolRef\n    \"in_arg\",\n    // AST_Return\n    \"in_bool\",\n    // AST_SymbolRef\n    \"is_undefined\",\n    // AST_LambdaExpression\n    // AST_LambdaDefinition\n    \"inlined\",\n    // AST_Lambda\n    \"length_read\",\n    // AST_Yield\n    \"nested\",\n    // AST_Lambda\n    \"new\",\n    // AST_Call\n    // AST_PropAccess\n    \"optional\",\n    // AST_ClassProperty\n    \"private\",\n    // AST_Call\n    \"pure\",\n    // AST_Node\n    \"single_use\",\n    // AST_ClassProperty\n    \"static\",\n    // AST_Call\n    // AST_PropAccess\n    \"terminal\",\n    \"truthy\",\n    // AST_Scope\n    \"uses_eval\",\n    // AST_Scope\n    \"uses_with\",\n]);\n\n(AST_Node.log_function = function(fn, verbose) {\n    if (typeof fn != \"function\") {\n        AST_Node.info = AST_Node.warn = noop;\n        return;\n    }\n    var printed = Object.create(null);\n    AST_Node.info = verbose ? function(text, props) {\n        log(\"INFO: \" + string_template(text, props));\n    } : noop;\n    AST_Node.warn = function(text, props) {\n        log(\"WARN: \" + string_template(text, props));\n    };\n\n    function log(msg) {\n        if (printed[msg]) return;\n        printed[msg] = true;\n        fn(msg);\n    }\n})();\n\nvar restore_transforms = [];\nAST_Node.enable_validation = function() {\n    AST_Node.disable_validation();\n    (function validate_transform(ctor) {\n        ctor.SUBCLASSES.forEach(validate_transform);\n        if (!HOP(ctor.prototype, \"transform\")) return;\n        var transform = ctor.prototype.transform;\n        ctor.prototype.transform = function(tw, in_list) {\n            var node = transform.call(this, tw, in_list);\n            if (node instanceof AST_Node) {\n                node.validate();\n            } else if (!(node === null || in_list && List.is_op(node))) {\n                throw new Error(\"invalid transformed value: \" + node);\n            }\n            return node;\n        };\n        restore_transforms.push(function() {\n            ctor.prototype.transform = transform;\n        });\n    })(this);\n};\n\nAST_Node.disable_validation = function() {\n    var restore;\n    while (restore = restore_transforms.pop()) restore();\n};\n\nfunction all_equals(k, l) {\n    return k.length == l.length && all(k, function(m, i) {\n        return m.equals(l[i]);\n    });\n}\n\nfunction list_equals(s, t) {\n    return s.length == t.length && all(s, function(u, i) {\n        return u == t[i];\n    });\n}\n\nfunction prop_equals(u, v) {\n    if (u === v) return true;\n    if (u == null) return v == null;\n    return u instanceof AST_Node && v instanceof AST_Node && u.equals(v);\n}\n\n/* -----[ statements ]----- */\n\nvar AST_Statement = DEFNODE(\"Statement\", null, {\n    $documentation: \"Base class of all statements\",\n    _validate: function() {\n        if (this.TYPE == \"Statement\") throw new Error(\"should not instantiate AST_Statement\");\n    },\n});\n\nvar AST_Debugger = DEFNODE(\"Debugger\", null, {\n    $documentation: \"Represents a debugger statement\",\n    _equals: return_true,\n}, AST_Statement);\n\nvar AST_Directive = DEFNODE(\"Directive\", \"quote value\", {\n    $documentation: \"Represents a directive, like \\\"use strict\\\";\",\n    $propdoc: {\n        quote: \"[string?] the original quote character\",\n        value: \"[string] The value of this directive as a plain string (it's not an AST_String!)\",\n    },\n    _equals: function(node) {\n        return this.value == node.value;\n    },\n    _validate: function() {\n        if (this.quote != null) {\n            if (typeof this.quote != \"string\") throw new Error(\"quote must be string\");\n            if (!/^[\"']$/.test(this.quote)) throw new Error(\"invalid quote: \" + this.quote);\n        }\n        if (typeof this.value != \"string\") throw new Error(\"value must be string\");\n    },\n}, AST_Statement);\n\nvar AST_EmptyStatement = DEFNODE(\"EmptyStatement\", null, {\n    $documentation: \"The empty statement (empty block or simply a semicolon)\",\n    _equals: return_true,\n}, AST_Statement);\n\nfunction is_statement(node) {\n    return node instanceof AST_Statement\n        && !(node instanceof AST_ClassExpression)\n        && !(node instanceof AST_LambdaExpression);\n}\n\nfunction validate_expression(value, prop, multiple, allow_spread, allow_hole) {\n    multiple = multiple ? \"contain\" : \"be\";\n    if (!(value instanceof AST_Node)) throw new Error(prop + \" must \" + multiple + \" AST_Node\");\n    if (value instanceof AST_DefaultValue) throw new Error(prop + \" cannot \" + multiple + \" AST_DefaultValue\");\n    if (value instanceof AST_Destructured) throw new Error(prop + \" cannot \" + multiple + \" AST_Destructured\");\n    if (value instanceof AST_Hole && !allow_hole) throw new Error(prop + \" cannot \" + multiple + \" AST_Hole\");\n    if (value instanceof AST_Spread && !allow_spread) throw new Error(prop + \" cannot \" + multiple + \" AST_Spread\");\n    if (is_statement(value)) throw new Error(prop + \" cannot \" + multiple + \" AST_Statement\");\n    if (value instanceof AST_SymbolDeclaration) {\n        throw new Error(prop + \" cannot \" + multiple + \" AST_SymbolDeclaration\");\n    }\n}\n\nfunction must_be_expression(node, prop) {\n    validate_expression(node[prop], prop);\n}\n\nvar AST_SimpleStatement = DEFNODE(\"SimpleStatement\", \"body\", {\n    $documentation: \"A statement consisting of an expression, i.e. a = 1 + 2\",\n    $propdoc: {\n        body: \"[AST_Node] an expression node (should not be instanceof AST_Statement)\",\n    },\n    _equals: function(node) {\n        return this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.body.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"body\");\n    },\n}, AST_Statement);\n\nvar AST_BlockScope = DEFNODE(\"BlockScope\", \"_var_names enclosed functions make_def parent_scope variables\", {\n    $documentation: \"Base class for all statements introducing a lexical scope\",\n    $propdoc: {\n        enclosed: \"[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any inner scopes\",\n        functions: \"[Dictionary/S] like `variables`, but only lists function declarations\",\n        parent_scope: \"[AST_Scope?/S] link to the parent scope\",\n        variables: \"[Dictionary/S] a map of name ---> SymbolDef for all variables/functions defined in this scope\",\n    },\n    clone: function(deep) {\n        var node = this._clone(deep);\n        if (this.enclosed) node.enclosed = this.enclosed.slice();\n        if (this.functions) node.functions = this.functions.clone();\n        if (this.variables) node.variables = this.variables.clone();\n        return node;\n    },\n    pinned: function() {\n        return this.resolve().pinned();\n    },\n    resolve: function() {\n        return this.parent_scope.resolve();\n    },\n    _validate: function() {\n        if (this.TYPE == \"BlockScope\") throw new Error(\"should not instantiate AST_BlockScope\");\n        if (this.parent_scope == null) return;\n        if (!(this.parent_scope instanceof AST_BlockScope)) throw new Error(\"parent_scope must be AST_BlockScope\");\n        if (!(this.resolve() instanceof AST_Scope)) throw new Error(\"must be contained within AST_Scope\");\n    },\n}, AST_Statement);\n\nfunction walk_body(node, visitor) {\n    node.body.forEach(function(node) {\n        node.walk(visitor);\n    });\n}\n\nvar AST_Block = DEFNODE(\"Block\", \"body\", {\n    $documentation: \"A body of statements (usually braced)\",\n    $propdoc: {\n        body: \"[AST_Statement*] an array of statements\"\n    },\n    _equals: function(node) {\n        return all_equals(this.body, node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            walk_body(node, visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"Block\") throw new Error(\"should not instantiate AST_Block\");\n        this.body.forEach(function(node) {\n            if (!is_statement(node)) throw new Error(\"body must contain AST_Statement\");\n        });\n    },\n}, AST_BlockScope);\n\nvar AST_BlockStatement = DEFNODE(\"BlockStatement\", null, {\n    $documentation: \"A block statement\",\n}, AST_Block);\n\nvar AST_StatementWithBody = DEFNODE(\"StatementWithBody\", \"body\", {\n    $documentation: \"Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`\",\n    $propdoc: {\n        body: \"[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement\"\n    },\n    _validate: function() {\n        if (this.TYPE == \"StatementWithBody\") throw new Error(\"should not instantiate AST_StatementWithBody\");\n        if (!is_statement(this.body)) throw new Error(\"body must be AST_Statement\");\n    },\n}, AST_BlockScope);\n\nvar AST_LabeledStatement = DEFNODE(\"LabeledStatement\", \"label\", {\n    $documentation: \"Statement with a label\",\n    $propdoc: {\n        label: \"[AST_Label] a label definition\"\n    },\n    _equals: function(node) {\n        return this.label.equals(node.label)\n            && this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.label.walk(visitor);\n            node.body.walk(visitor);\n        });\n    },\n    clone: function(deep) {\n        var node = this._clone(deep);\n        if (deep) {\n            var label = node.label;\n            var def = this.label;\n            node.walk(new TreeWalker(function(node) {\n                if (node instanceof AST_LoopControl) {\n                    if (!node.label || node.label.thedef !== def) return;\n                    node.label.thedef = label;\n                    label.references.push(node);\n                    return true;\n                }\n                if (node instanceof AST_Scope) return true;\n            }));\n        }\n        return node;\n    },\n    _validate: function() {\n        if (!(this.label instanceof AST_Label)) throw new Error(\"label must be AST_Label\");\n    },\n}, AST_StatementWithBody);\n\nvar AST_IterationStatement = DEFNODE(\"IterationStatement\", null, {\n    $documentation: \"Internal class.  All loops inherit from it.\",\n    _validate: function() {\n        if (this.TYPE == \"IterationStatement\") throw new Error(\"should not instantiate AST_IterationStatement\");\n    },\n}, AST_StatementWithBody);\n\nvar AST_DWLoop = DEFNODE(\"DWLoop\", \"condition\", {\n    $documentation: \"Base class for do/while statements\",\n    $propdoc: {\n        condition: \"[AST_Node] the loop condition.  Should not be instanceof AST_Statement\"\n    },\n    _equals: function(node) {\n        return this.body.equals(node.body)\n            && this.condition.equals(node.condition);\n    },\n    _validate: function() {\n        if (this.TYPE == \"DWLoop\") throw new Error(\"should not instantiate AST_DWLoop\");\n        must_be_expression(this, \"condition\");\n    },\n}, AST_IterationStatement);\n\nvar AST_Do = DEFNODE(\"Do\", null, {\n    $documentation: \"A `do` statement\",\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.body.walk(visitor);\n            node.condition.walk(visitor);\n        });\n    },\n}, AST_DWLoop);\n\nvar AST_While = DEFNODE(\"While\", null, {\n    $documentation: \"A `while` statement\",\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.condition.walk(visitor);\n            node.body.walk(visitor);\n        });\n    },\n}, AST_DWLoop);\n\nvar AST_For = DEFNODE(\"For\", \"init condition step\", {\n    $documentation: \"A `for` statement\",\n    $propdoc: {\n        init: \"[AST_Node?] the `for` initialization code, or null if empty\",\n        condition: \"[AST_Node?] the `for` termination clause, or null if empty\",\n        step: \"[AST_Node?] the `for` update clause, or null if empty\"\n    },\n    _equals: function(node) {\n        return prop_equals(this.init, node.init)\n            && prop_equals(this.condition, node.condition)\n            && prop_equals(this.step, node.step)\n            && this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.init) node.init.walk(visitor);\n            if (node.condition) node.condition.walk(visitor);\n            if (node.step) node.step.walk(visitor);\n            node.body.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.init != null) {\n            if (!(this.init instanceof AST_Node)) throw new Error(\"init must be AST_Node\");\n            if (is_statement(this.init) && !(this.init instanceof AST_Definitions)) {\n                throw new Error(\"init cannot be AST_Statement\");\n            }\n        }\n        if (this.condition != null) must_be_expression(this, \"condition\");\n        if (this.step != null) must_be_expression(this, \"step\");\n    },\n}, AST_IterationStatement);\n\nvar AST_ForEnumeration = DEFNODE(\"ForEnumeration\", \"init object\", {\n    $documentation: \"Base class for enumeration loops, i.e. `for ... in`, `for ... of` & `for await ... of`\",\n    $propdoc: {\n        init: \"[AST_Node] the assignment target during iteration\",\n        object: \"[AST_Node] the object to iterate over\"\n    },\n    _equals: function(node) {\n        return this.init.equals(node.init)\n            && this.object.equals(node.object)\n            && this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.init.walk(visitor);\n            node.object.walk(visitor);\n            node.body.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"ForEnumeration\") throw new Error(\"should not instantiate AST_ForEnumeration\");\n        if (this.init instanceof AST_Definitions) {\n            if (this.init.definitions.length != 1) throw new Error(\"init must have single declaration\");\n        } else {\n            validate_destructured(this.init, function(node) {\n                if (!(node instanceof AST_PropAccess || node instanceof AST_SymbolRef)) {\n                    throw new Error(\"init must be assignable: \" + node.TYPE);\n                }\n            });\n        }\n        must_be_expression(this, \"object\");\n    },\n}, AST_IterationStatement);\n\nvar AST_ForIn = DEFNODE(\"ForIn\", null, {\n    $documentation: \"A `for ... in` statement\",\n}, AST_ForEnumeration);\n\nvar AST_ForOf = DEFNODE(\"ForOf\", null, {\n    $documentation: \"A `for ... of` statement\",\n}, AST_ForEnumeration);\n\nvar AST_ForAwaitOf = DEFNODE(\"ForAwaitOf\", null, {\n    $documentation: \"A `for await ... of` statement\",\n}, AST_ForOf);\n\nvar AST_With = DEFNODE(\"With\", \"expression\", {\n    $documentation: \"A `with` statement\",\n    $propdoc: {\n        expression: \"[AST_Node] the `with` expression\"\n    },\n    _equals: function(node) {\n        return this.expression.equals(node.expression)\n            && this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n            node.body.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"expression\");\n    },\n}, AST_StatementWithBody);\n\n/* -----[ scope and functions ]----- */\n\nvar AST_Scope = DEFNODE(\"Scope\", \"fn_defs may_call_this uses_eval uses_with\", {\n    $documentation: \"Base class for all statements introducing a lambda scope\",\n    $propdoc: {\n        uses_eval: \"[boolean/S] tells whether this scope contains a direct call to the global `eval`\",\n        uses_with: \"[boolean/S] tells whether this scope uses the `with` statement\",\n    },\n    pinned: function() {\n        return this.uses_eval || this.uses_with;\n    },\n    resolve: return_this,\n    _validate: function() {\n        if (this.TYPE == \"Scope\") throw new Error(\"should not instantiate AST_Scope\");\n    },\n}, AST_Block);\n\nvar AST_Toplevel = DEFNODE(\"Toplevel\", \"globals\", {\n    $documentation: \"The toplevel scope\",\n    $propdoc: {\n        globals: \"[Dictionary/S] a map of name ---> SymbolDef for all undeclared names\",\n    },\n    wrap: function(name) {\n        var body = this.body;\n        return parse([\n            \"(function(exports){'$ORIG';})(typeof \",\n            name,\n            \"=='undefined'?(\",\n            name,\n            \"={}):\",\n            name,\n            \");\"\n        ].join(\"\"), {\n            filename: \"wrap=\" + JSON.stringify(name)\n        }).transform(new TreeTransformer(function(node) {\n            if (node instanceof AST_Directive && node.value == \"$ORIG\") {\n                return List.splice(body);\n            }\n        }));\n    },\n    enclose: function(args_values) {\n        if (typeof args_values != \"string\") args_values = \"\";\n        var index = args_values.indexOf(\":\");\n        if (index < 0) index = args_values.length;\n        var body = this.body;\n        return parse([\n            \"(function(\",\n            args_values.slice(0, index),\n            '){\"$ORIG\"})(',\n            args_values.slice(index + 1),\n            \")\"\n        ].join(\"\"), {\n            filename: \"enclose=\" + JSON.stringify(args_values)\n        }).transform(new TreeTransformer(function(node) {\n            if (node instanceof AST_Directive && node.value == \"$ORIG\") {\n                return List.splice(body);\n            }\n        }));\n    }\n}, AST_Scope);\n\nvar AST_ClassInitBlock = DEFNODE(\"ClassInitBlock\", null, {\n    $documentation: \"Value for `class` static initialization blocks\",\n}, AST_Scope);\n\nvar AST_Lambda = DEFNODE(\"Lambda\", \"argnames length_read rest safe_ids uses_arguments\", {\n    $documentation: \"Base class for functions\",\n    $propdoc: {\n        argnames: \"[(AST_DefaultValue|AST_Destructured|AST_SymbolFunarg)*] array of function arguments and/or destructured literals\",\n        length_read: \"[boolean/S] whether length property of this function is accessed\",\n        rest: \"[(AST_Destructured|AST_SymbolFunarg)?] rest parameter, or null if absent\",\n        uses_arguments: \"[boolean|number/S] whether this function accesses the arguments array\",\n    },\n    each_argname: function(visit) {\n        var tw = new TreeWalker(function(node) {\n            if (node instanceof AST_DefaultValue) {\n                node.name.walk(tw);\n                return true;\n            }\n            if (node instanceof AST_DestructuredKeyVal) {\n                node.value.walk(tw);\n                return true;\n            }\n            if (node instanceof AST_SymbolFunarg) visit(node);\n        });\n        this.argnames.forEach(function(argname) {\n            argname.walk(tw);\n        });\n        if (this.rest) this.rest.walk(tw);\n    },\n    _equals: function(node) {\n        return prop_equals(this.rest, node.rest)\n            && prop_equals(this.name, node.name)\n            && prop_equals(this.value, node.value)\n            && all_equals(this.argnames, node.argnames)\n            && all_equals(this.body, node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.name) node.name.walk(visitor);\n            node.argnames.forEach(function(argname) {\n                argname.walk(visitor);\n            });\n            if (node.rest) node.rest.walk(visitor);\n            walk_body(node, visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"Lambda\") throw new Error(\"should not instantiate AST_Lambda\");\n        this.argnames.forEach(function(node) {\n            validate_destructured(node, function(node) {\n                if (!(node instanceof AST_SymbolFunarg)) throw new Error(\"argnames must be AST_SymbolFunarg[]\");\n            }, true);\n        });\n        if (this.rest != null) validate_destructured(this.rest, function(node) {\n            if (!(node instanceof AST_SymbolFunarg)) throw new Error(\"rest must be AST_SymbolFunarg\");\n        });\n    },\n}, AST_Scope);\n\nvar AST_Accessor = DEFNODE(\"Accessor\", null, {\n    $documentation: \"A getter/setter function\",\n    _validate: function() {\n        if (this.name != null) throw new Error(\"name must be null\");\n    },\n}, AST_Lambda);\n\nvar AST_LambdaExpression = DEFNODE(\"LambdaExpression\", \"inlined\", {\n    $documentation: \"Base class for function expressions\",\n    $propdoc: {\n        inlined: \"[boolean/S] whether this function has been inlined\",\n    },\n    _validate: function() {\n        if (this.TYPE == \"LambdaExpression\") throw new Error(\"should not instantiate AST_LambdaExpression\");\n    },\n}, AST_Lambda);\n\nfunction is_arrow(node) {\n    return node instanceof AST_Arrow || node instanceof AST_AsyncArrow;\n}\n\nfunction is_async(node) {\n    return node instanceof AST_AsyncArrow\n        || node instanceof AST_AsyncDefun\n        || node instanceof AST_AsyncFunction\n        || node instanceof AST_AsyncGeneratorDefun\n        || node instanceof AST_AsyncGeneratorFunction;\n}\n\nfunction is_generator(node) {\n    return node instanceof AST_AsyncGeneratorDefun\n        || node instanceof AST_AsyncGeneratorFunction\n        || node instanceof AST_GeneratorDefun\n        || node instanceof AST_GeneratorFunction;\n}\n\nfunction walk_lambda(node, tw) {\n    if (is_arrow(node) && node.value) {\n        node.value.walk(tw);\n    } else {\n        walk_body(node, tw);\n    }\n}\n\nvar AST_Arrow = DEFNODE(\"Arrow\", \"value\", {\n    $documentation: \"An arrow function expression\",\n    $propdoc: {\n        value: \"[AST_Node?] simple return expression, or null if using function body.\",\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.argnames.forEach(function(argname) {\n                argname.walk(visitor);\n            });\n            if (node.rest) node.rest.walk(visitor);\n            if (node.value) {\n                node.value.walk(visitor);\n            } else {\n                walk_body(node, visitor);\n            }\n        });\n    },\n    _validate: function() {\n        if (this.name != null) throw new Error(\"name must be null\");\n        if (this.uses_arguments) throw new Error(\"uses_arguments must be false\");\n        if (this.value != null) {\n            must_be_expression(this, \"value\");\n            if (this.body.length) throw new Error(\"body must be empty if value exists\");\n        }\n    },\n}, AST_LambdaExpression);\n\nvar AST_AsyncArrow = DEFNODE(\"AsyncArrow\", \"value\", {\n    $documentation: \"An asynchronous arrow function expression\",\n    $propdoc: {\n        value: \"[AST_Node?] simple return expression, or null if using function body.\",\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.argnames.forEach(function(argname) {\n                argname.walk(visitor);\n            });\n            if (node.rest) node.rest.walk(visitor);\n            if (node.value) {\n                node.value.walk(visitor);\n            } else {\n                walk_body(node, visitor);\n            }\n        });\n    },\n    _validate: function() {\n        if (this.name != null) throw new Error(\"name must be null\");\n        if (this.uses_arguments) throw new Error(\"uses_arguments must be false\");\n        if (this.value != null) {\n            must_be_expression(this, \"value\");\n            if (this.body.length) throw new Error(\"body must be empty if value exists\");\n        }\n    },\n}, AST_LambdaExpression);\n\nvar AST_AsyncFunction = DEFNODE(\"AsyncFunction\", \"name\", {\n    $documentation: \"An asynchronous function expression\",\n    $propdoc: {\n        name: \"[AST_SymbolLambda?] the name of this function, or null if not specified\",\n    },\n    _validate: function() {\n        if (this.name != null) {\n            if (!(this.name instanceof AST_SymbolLambda)) throw new Error(\"name must be AST_SymbolLambda\");\n        }\n    },\n}, AST_LambdaExpression);\n\nvar AST_AsyncGeneratorFunction = DEFNODE(\"AsyncGeneratorFunction\", \"name\", {\n    $documentation: \"An asynchronous generator function expression\",\n    $propdoc: {\n        name: \"[AST_SymbolLambda?] the name of this function, or null if not specified\",\n    },\n    _validate: function() {\n        if (this.name != null) {\n            if (!(this.name instanceof AST_SymbolLambda)) throw new Error(\"name must be AST_SymbolLambda\");\n        }\n    },\n}, AST_LambdaExpression);\n\nvar AST_Function = DEFNODE(\"Function\", \"name\", {\n    $documentation: \"A function expression\",\n    $propdoc: {\n        name: \"[AST_SymbolLambda?] the name of this function, or null if not specified\",\n    },\n    _validate: function() {\n        if (this.name != null) {\n            if (!(this.name instanceof AST_SymbolLambda)) throw new Error(\"name must be AST_SymbolLambda\");\n        }\n    },\n}, AST_LambdaExpression);\n\nvar AST_GeneratorFunction = DEFNODE(\"GeneratorFunction\", \"name\", {\n    $documentation: \"A generator function expression\",\n    $propdoc: {\n        name: \"[AST_SymbolLambda?] the name of this function, or null if not specified\",\n    },\n    _validate: function() {\n        if (this.name != null) {\n            if (!(this.name instanceof AST_SymbolLambda)) throw new Error(\"name must be AST_SymbolLambda\");\n        }\n    },\n}, AST_LambdaExpression);\n\nvar AST_LambdaDefinition = DEFNODE(\"LambdaDefinition\", \"inlined name\", {\n    $documentation: \"Base class for function definitions\",\n    $propdoc: {\n        inlined: \"[boolean/S] whether this function has been inlined\",\n        name: \"[AST_SymbolDefun] the name of this function\",\n    },\n    _validate: function() {\n        if (this.TYPE == \"LambdaDefinition\") throw new Error(\"should not instantiate AST_LambdaDefinition\");\n        if (!(this.name instanceof AST_SymbolDefun)) throw new Error(\"name must be AST_SymbolDefun\");\n    },\n}, AST_Lambda);\n\nvar AST_AsyncDefun = DEFNODE(\"AsyncDefun\", null, {\n    $documentation: \"An asynchronous function definition\",\n}, AST_LambdaDefinition);\n\nvar AST_AsyncGeneratorDefun = DEFNODE(\"AsyncGeneratorDefun\", null, {\n    $documentation: \"An asynchronous generator function definition\",\n}, AST_LambdaDefinition);\n\nvar AST_Defun = DEFNODE(\"Defun\", null, {\n    $documentation: \"A function definition\",\n}, AST_LambdaDefinition);\n\nvar AST_GeneratorDefun = DEFNODE(\"GeneratorDefun\", null, {\n    $documentation: \"A generator function definition\",\n}, AST_LambdaDefinition);\n\n/* -----[ classes ]----- */\n\nvar AST_Class = DEFNODE(\"Class\", \"extends name properties\", {\n    $documentation: \"Base class for class literals\",\n    $propdoc: {\n        extends: \"[AST_Node?] the super class, or null if not specified\",\n        properties: \"[AST_ClassProperty*] array of class properties\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.name, node.name)\n            && prop_equals(this.extends, node.extends)\n            && all_equals(this.properties, node.properties);\n    },\n    resolve: function(def_class) {\n        return def_class ? this : this.parent_scope.resolve();\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.name) node.name.walk(visitor);\n            if (node.extends) node.extends.walk(visitor);\n            node.properties.forEach(function(prop) {\n                prop.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"Class\") throw new Error(\"should not instantiate AST_Class\");\n        if (this.extends != null) must_be_expression(this, \"extends\");\n        this.properties.forEach(function(node) {\n            if (!(node instanceof AST_ClassProperty)) throw new Error(\"properties must contain AST_ClassProperty\");\n        });\n    },\n}, AST_BlockScope);\n\nvar AST_DefClass = DEFNODE(\"DefClass\", null, {\n    $documentation: \"A class definition\",\n    $propdoc: {\n        name: \"[AST_SymbolDefClass] the name of this class\",\n    },\n    _validate: function() {\n        if (!(this.name instanceof AST_SymbolDefClass)) throw new Error(\"name must be AST_SymbolDefClass\");\n    },\n}, AST_Class);\n\nvar AST_ClassExpression = DEFNODE(\"ClassExpression\", null, {\n    $documentation: \"A class expression\",\n    $propdoc: {\n        name: \"[AST_SymbolClass?] the name of this class, or null if not specified\",\n    },\n    _validate: function() {\n        if (this.name != null) {\n            if (!(this.name instanceof AST_SymbolClass)) throw new Error(\"name must be AST_SymbolClass\");\n        }\n    },\n}, AST_Class);\n\nvar AST_ClassProperty = DEFNODE(\"ClassProperty\", \"key private static value\", {\n    $documentation: \"Base class for `class` properties\",\n    $propdoc: {\n        key: \"[string|AST_Node?] property name (AST_Node for computed property, null for initialization block)\",\n        private: \"[boolean] whether this is a private property\",\n        static: \"[boolean] whether this is a static property\",\n        value: \"[AST_Node?] property value (AST_Accessor for getters/setters, AST_LambdaExpression for methods, null if not specified for fields)\",\n    },\n    _equals: function(node) {\n        return !this.private == !node.private\n            && !this.static == !node.static\n            && prop_equals(this.key, node.key)\n            && prop_equals(this.value, node.value);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.key instanceof AST_Node) node.key.walk(visitor);\n            if (node.value) node.value.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"ClassProperty\") throw new Error(\"should not instantiate AST_ClassProperty\");\n        if (this instanceof AST_ClassInit) {\n            if (this.key != null) throw new Error(\"key must be null\");\n        } else if (typeof this.key != \"string\") {\n            if (!(this.key instanceof AST_Node)) throw new Error(\"key must be string or AST_Node\");\n            if (this.private) throw new Error(\"computed key cannot be private\");\n            must_be_expression(this, \"key\");\n        } else if (this.private) {\n            if (!/^#/.test(this.key)) throw new Error(\"private key must prefix with #\");\n        }\n        if (this.value != null) {\n            if (!(this.value instanceof AST_Node)) throw new Error(\"value must be AST_Node\");\n        }\n    },\n});\n\nvar AST_ClassField = DEFNODE(\"ClassField\", null, {\n    $documentation: \"A `class` field\",\n    _validate: function() {\n        if (this.value != null) must_be_expression(this, \"value\");\n    },\n}, AST_ClassProperty);\n\nvar AST_ClassGetter = DEFNODE(\"ClassGetter\", null, {\n    $documentation: \"A `class` getter\",\n    _validate: function() {\n        if (!(this.value instanceof AST_Accessor)) throw new Error(\"value must be AST_Accessor\");\n    },\n}, AST_ClassProperty);\n\nvar AST_ClassSetter = DEFNODE(\"ClassSetter\", null, {\n    $documentation: \"A `class` setter\",\n    _validate: function() {\n        if (!(this.value instanceof AST_Accessor)) throw new Error(\"value must be AST_Accessor\");\n    },\n}, AST_ClassProperty);\n\nvar AST_ClassMethod = DEFNODE(\"ClassMethod\", null, {\n    $documentation: \"A `class` method\",\n    _validate: function() {\n        if (!(this.value instanceof AST_LambdaExpression)) throw new Error(\"value must be AST_LambdaExpression\");\n        if (is_arrow(this.value)) throw new Error(\"value cannot be AST_Arrow or AST_AsyncArrow\");\n        if (this.value.name != null) throw new Error(\"name of class method's lambda must be null\");\n    },\n}, AST_ClassProperty);\n\nvar AST_ClassInit = DEFNODE(\"ClassInit\", null, {\n    $documentation: \"A `class` static initialization block\",\n    _validate: function() {\n        if (!this.static) throw new Error(\"static must be true\");\n        if (!(this.value instanceof AST_ClassInitBlock)) throw new Error(\"value must be AST_ClassInitBlock\");\n    },\n    initialize: function() {\n        this.static = true;\n    },\n}, AST_ClassProperty);\n\n/* -----[ JUMPS ]----- */\n\nvar AST_Jump = DEFNODE(\"Jump\", null, {\n    $documentation: \"Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)\",\n    _validate: function() {\n        if (this.TYPE == \"Jump\") throw new Error(\"should not instantiate AST_Jump\");\n    },\n}, AST_Statement);\n\nvar AST_Exit = DEFNODE(\"Exit\", \"value\", {\n    $documentation: \"Base class for “exits” (`return` and `throw`)\",\n    $propdoc: {\n        value: \"[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return\"\n    },\n    _equals: function(node) {\n        return prop_equals(this.value, node.value);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.value) node.value.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"Exit\") throw new Error(\"should not instantiate AST_Exit\");\n    },\n}, AST_Jump);\n\nvar AST_Return = DEFNODE(\"Return\", null, {\n    $documentation: \"A `return` statement\",\n    _validate: function() {\n        if (this.value != null) must_be_expression(this, \"value\");\n    },\n}, AST_Exit);\n\nvar AST_Throw = DEFNODE(\"Throw\", null, {\n    $documentation: \"A `throw` statement\",\n    _validate: function() {\n        must_be_expression(this, \"value\");\n    },\n}, AST_Exit);\n\nvar AST_LoopControl = DEFNODE(\"LoopControl\", \"label\", {\n    $documentation: \"Base class for loop control statements (`break` and `continue`)\",\n    $propdoc: {\n        label: \"[AST_LabelRef?] the label, or null if none\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.label, node.label);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.label) node.label.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"LoopControl\") throw new Error(\"should not instantiate AST_LoopControl\");\n        if (this.label != null) {\n            if (!(this.label instanceof AST_LabelRef)) throw new Error(\"label must be AST_LabelRef\");\n        }\n    },\n}, AST_Jump);\n\nvar AST_Break = DEFNODE(\"Break\", null, {\n    $documentation: \"A `break` statement\"\n}, AST_LoopControl);\n\nvar AST_Continue = DEFNODE(\"Continue\", null, {\n    $documentation: \"A `continue` statement\"\n}, AST_LoopControl);\n\n/* -----[ IF ]----- */\n\nvar AST_If = DEFNODE(\"If\", \"condition alternative\", {\n    $documentation: \"A `if` statement\",\n    $propdoc: {\n        condition: \"[AST_Node] the `if` condition\",\n        alternative: \"[AST_Statement?] the `else` part, or null if not present\"\n    },\n    _equals: function(node) {\n        return this.body.equals(node.body)\n            && this.condition.equals(node.condition)\n            && prop_equals(this.alternative, node.alternative);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.condition.walk(visitor);\n            node.body.walk(visitor);\n            if (node.alternative) node.alternative.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"condition\");\n        if (this.alternative != null) {\n            if (!is_statement(this.alternative)) throw new Error(\"alternative must be AST_Statement\");\n        }\n    },\n}, AST_StatementWithBody);\n\n/* -----[ SWITCH ]----- */\n\nvar AST_Switch = DEFNODE(\"Switch\", \"expression\", {\n    $documentation: \"A `switch` statement\",\n    $propdoc: {\n        expression: \"[AST_Node] the `switch` “discriminant”\"\n    },\n    _equals: function(node) {\n        return this.expression.equals(node.expression)\n            && all_equals(this.body, node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n            walk_body(node, visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"expression\");\n        this.body.forEach(function(node) {\n            if (!(node instanceof AST_SwitchBranch)) throw new Error(\"body must be AST_SwitchBranch[]\");\n        });\n    },\n}, AST_Block);\n\nvar AST_SwitchBranch = DEFNODE(\"SwitchBranch\", null, {\n    $documentation: \"Base class for `switch` branches\",\n    _validate: function() {\n        if (this.TYPE == \"SwitchBranch\") throw new Error(\"should not instantiate AST_SwitchBranch\");\n    },\n}, AST_Block);\n\nvar AST_Default = DEFNODE(\"Default\", null, {\n    $documentation: \"A `default` switch branch\",\n}, AST_SwitchBranch);\n\nvar AST_Case = DEFNODE(\"Case\", \"expression\", {\n    $documentation: \"A `case` switch branch\",\n    $propdoc: {\n        expression: \"[AST_Node] the `case` expression\"\n    },\n    _equals: function(node) {\n        return this.expression.equals(node.expression)\n            && all_equals(this.body, node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n            walk_body(node, visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"expression\");\n    },\n}, AST_SwitchBranch);\n\n/* -----[ EXCEPTIONS ]----- */\n\nvar AST_Try = DEFNODE(\"Try\", \"bcatch bfinally\", {\n    $documentation: \"A `try` statement\",\n    $propdoc: {\n        bcatch: \"[AST_Catch?] the catch block, or null if not present\",\n        bfinally: \"[AST_Finally?] the finally block, or null if not present\"\n    },\n    _equals: function(node) {\n        return all_equals(this.body, node.body)\n            && prop_equals(this.bcatch, node.bcatch)\n            && prop_equals(this.bfinally, node.bfinally);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            walk_body(node, visitor);\n            if (node.bcatch) node.bcatch.walk(visitor);\n            if (node.bfinally) node.bfinally.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.bcatch != null) {\n            if (!(this.bcatch instanceof AST_Catch)) throw new Error(\"bcatch must be AST_Catch\");\n        }\n        if (this.bfinally != null) {\n            if (!(this.bfinally instanceof AST_Finally)) throw new Error(\"bfinally must be AST_Finally\");\n        }\n    },\n}, AST_Block);\n\nvar AST_Catch = DEFNODE(\"Catch\", \"argname\", {\n    $documentation: \"A `catch` node; only makes sense as part of a `try` statement\",\n    $propdoc: {\n        argname: \"[(AST_Destructured|AST_SymbolCatch)?] symbol for the exception, or null if not present\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.argname, node.argname)\n            && all_equals(this.body, node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.argname) node.argname.walk(visitor);\n            walk_body(node, visitor);\n        });\n    },\n    _validate: function() {\n        if (this.argname != null) validate_destructured(this.argname, function(node) {\n            if (!(node instanceof AST_SymbolCatch)) throw new Error(\"argname must be AST_SymbolCatch\");\n        });\n    },\n}, AST_Block);\n\nvar AST_Finally = DEFNODE(\"Finally\", null, {\n    $documentation: \"A `finally` node; only makes sense as part of a `try` statement\"\n}, AST_Block);\n\n/* -----[ VAR ]----- */\n\nvar AST_Definitions = DEFNODE(\"Definitions\", \"definitions\", {\n    $documentation: \"Base class for `var` nodes (variable declarations/initializations)\",\n    $propdoc: {\n        definitions: \"[AST_VarDef*] array of variable definitions\"\n    },\n    _equals: function(node) {\n        return all_equals(this.definitions, node.definitions);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.definitions.forEach(function(defn) {\n                defn.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"Definitions\") throw new Error(\"should not instantiate AST_Definitions\");\n        if (this.definitions.length < 1) throw new Error(\"must have at least one definition\");\n    },\n}, AST_Statement);\n\nvar AST_Const = DEFNODE(\"Const\", null, {\n    $documentation: \"A `const` statement\",\n    _validate: function() {\n        this.definitions.forEach(function(node) {\n            if (!(node instanceof AST_VarDef)) throw new Error(\"definitions must be AST_VarDef[]\");\n            validate_destructured(node.name, function(node) {\n                if (!(node instanceof AST_SymbolConst)) throw new Error(\"name must be AST_SymbolConst\");\n            });\n        });\n    },\n}, AST_Definitions);\n\nvar AST_Let = DEFNODE(\"Let\", null, {\n    $documentation: \"A `let` statement\",\n    _validate: function() {\n        this.definitions.forEach(function(node) {\n            if (!(node instanceof AST_VarDef)) throw new Error(\"definitions must be AST_VarDef[]\");\n            validate_destructured(node.name, function(node) {\n                if (!(node instanceof AST_SymbolLet)) throw new Error(\"name must be AST_SymbolLet\");\n            });\n        });\n    },\n}, AST_Definitions);\n\nvar AST_Var = DEFNODE(\"Var\", null, {\n    $documentation: \"A `var` statement\",\n    _validate: function() {\n        this.definitions.forEach(function(node) {\n            if (!(node instanceof AST_VarDef)) throw new Error(\"definitions must be AST_VarDef[]\");\n            validate_destructured(node.name, function(node) {\n                if (!(node instanceof AST_SymbolVar)) throw new Error(\"name must be AST_SymbolVar\");\n            });\n        });\n    },\n}, AST_Definitions);\n\nvar AST_VarDef = DEFNODE(\"VarDef\", \"name value\", {\n    $documentation: \"A variable declaration; only appears in a AST_Definitions node\",\n    $propdoc: {\n        name: \"[AST_Destructured|AST_SymbolVar] name of the variable\",\n        value: \"[AST_Node?] initializer, or null of there's no initializer\",\n    },\n    _equals: function(node) {\n        return this.name.equals(node.name)\n            && prop_equals(this.value, node.value);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.name.walk(visitor);\n            if (node.value) node.value.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.value != null) must_be_expression(this, \"value\");\n    },\n});\n\n/* -----[ OTHER ]----- */\n\nvar AST_ExportDeclaration = DEFNODE(\"ExportDeclaration\", \"body\", {\n    $documentation: \"An `export` statement\",\n    $propdoc: {\n        body: \"[AST_DefClass|AST_Definitions|AST_LambdaDefinition] the statement to export\",\n    },\n    _equals: function(node) {\n        return this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.body.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (!(this.body instanceof AST_DefClass\n            || this.body instanceof AST_Definitions\n            || this.body instanceof AST_LambdaDefinition)) {\n            throw new Error(\"body must be AST_DefClass, AST_Definitions or AST_LambdaDefinition\");\n        }\n    },\n}, AST_Statement);\n\nvar AST_ExportDefault = DEFNODE(\"ExportDefault\", \"body\", {\n    $documentation: \"An `export default` statement\",\n    $propdoc: {\n        body: \"[AST_Node] the default export\",\n    },\n    _equals: function(node) {\n        return this.body.equals(node.body);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.body.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (!(this.body instanceof AST_DefClass || this.body instanceof AST_LambdaDefinition)) {\n            must_be_expression(this, \"body\");\n        }\n    },\n}, AST_Statement);\n\nvar AST_ExportForeign = DEFNODE(\"ExportForeign\", \"aliases keys path\", {\n    $documentation: \"An `export ... from '...'` statement\",\n    $propdoc: {\n        aliases: \"[AST_String*] array of aliases to export\",\n        keys: \"[AST_String*] array of keys to import\",\n        path: \"[AST_String] the path to import module\",\n    },\n    _equals: function(node) {\n        return this.path.equals(node.path)\n            && all_equals(this.aliases, node.aliases)\n            && all_equals(this.keys, node.keys);\n    },\n    _validate: function() {\n        if (this.aliases.length != this.keys.length) {\n            throw new Error(\"aliases:key length mismatch: \" + this.aliases.length + \" != \" + this.keys.length);\n        }\n        this.aliases.forEach(function(name) {\n            if (!(name instanceof AST_String)) throw new Error(\"aliases must contain AST_String\");\n        });\n        this.keys.forEach(function(name) {\n            if (!(name instanceof AST_String)) throw new Error(\"keys must contain AST_String\");\n        });\n        if (!(this.path instanceof AST_String)) throw new Error(\"path must be AST_String\");\n    },\n}, AST_Statement);\n\nvar AST_ExportReferences = DEFNODE(\"ExportReferences\", \"properties\", {\n    $documentation: \"An `export { ... }` statement\",\n    $propdoc: {\n        properties: \"[AST_SymbolExport*] array of aliases to export\",\n    },\n    _equals: function(node) {\n        return all_equals(this.properties, node.properties);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.properties.forEach(function(prop) {\n                prop.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        this.properties.forEach(function(prop) {\n            if (!(prop instanceof AST_SymbolExport)) throw new Error(\"properties must contain AST_SymbolExport\");\n        });\n    },\n}, AST_Statement);\n\nvar AST_Import = DEFNODE(\"Import\", \"all default path properties\", {\n    $documentation: \"An `import` statement\",\n    $propdoc: {\n        all: \"[AST_SymbolImport?] the imported namespace, or null if not specified\",\n        default: \"[AST_SymbolImport?] the alias for default `export`, or null if not specified\",\n        path: \"[AST_String] the path to import module\",\n        properties: \"[(AST_SymbolImport*)?] array of aliases, or null if not specified\",\n    },\n    _equals: function(node) {\n        return this.path.equals(node.path)\n            && prop_equals(this.all, node.all)\n            && prop_equals(this.default, node.default)\n            && !this.properties == !node.properties\n            && (!this.properties || all_equals(this.properties, node.properties));\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.all) node.all.walk(visitor);\n            if (node.default) node.default.walk(visitor);\n            if (node.properties) node.properties.forEach(function(prop) {\n                prop.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        if (this.all != null) {\n            if (!(this.all instanceof AST_SymbolImport)) throw new Error(\"all must be AST_SymbolImport\");\n            if (this.properties != null) throw new Error(\"cannot import both * and {} in the same statement\");\n        }\n        if (this.default != null) {\n            if (!(this.default instanceof AST_SymbolImport)) throw new Error(\"default must be AST_SymbolImport\");\n            if (this.default.key.value !== \"\") throw new Error(\"invalid default key: \" + this.default.key.value);\n        }\n        if (!(this.path instanceof AST_String)) throw new Error(\"path must be AST_String\");\n        if (this.properties != null) this.properties.forEach(function(node) {\n            if (!(node instanceof AST_SymbolImport)) throw new Error(\"properties must contain AST_SymbolImport\");\n        });\n    },\n}, AST_Statement);\n\nvar AST_DefaultValue = DEFNODE(\"DefaultValue\", \"name value\", {\n    $documentation: \"A default value declaration\",\n    $propdoc: {\n        name: \"[AST_Destructured|AST_SymbolDeclaration] name of the variable\",\n        value: \"[AST_Node] value to assign if variable is `undefined`\",\n    },\n    _equals: function(node) {\n        return this.name.equals(node.name)\n            && this.value.equals(node.value);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.name.walk(visitor);\n            node.value.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"value\");\n    },\n});\n\nfunction must_be_expressions(node, prop, allow_spread, allow_hole) {\n    node[prop].forEach(function(node) {\n        validate_expression(node, prop, true, allow_spread, allow_hole);\n    });\n}\n\nvar AST_Call = DEFNODE(\"Call\", \"args expression optional pure terminal\", {\n    $documentation: \"A function call expression\",\n    $propdoc: {\n        args: \"[AST_Node*] array of arguments\",\n        expression: \"[AST_Node] expression to invoke as function\",\n        optional: \"[boolean] whether the expression is optional chaining\",\n        pure: \"[boolean/S] marker for side-effect-free call expression\",\n        terminal: \"[boolean] whether the chain has ended\",\n    },\n    _equals: function(node) {\n        return !this.optional == !node.optional\n            && this.expression.equals(node.expression)\n            && all_equals(this.args, node.args);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n            node.args.forEach(function(arg) {\n                arg.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"expression\");\n        must_be_expressions(this, \"args\", true);\n    },\n});\n\nvar AST_New = DEFNODE(\"New\", null, {\n    $documentation: \"An object instantiation.  Derives from a function call since it has exactly the same properties\",\n    _validate: function() {\n        if (this.optional) throw new Error(\"optional must be false\");\n        if (this.terminal) throw new Error(\"terminal must be false\");\n    },\n}, AST_Call);\n\nvar AST_Sequence = DEFNODE(\"Sequence\", \"expressions\", {\n    $documentation: \"A sequence expression (comma-separated expressions)\",\n    $propdoc: {\n        expressions: \"[AST_Node*] array of expressions (at least two)\",\n    },\n    _equals: function(node) {\n        return all_equals(this.expressions, node.expressions);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expressions.forEach(function(expr) {\n                expr.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        if (this.expressions.length < 2) throw new Error(\"expressions must contain multiple elements\");\n        must_be_expressions(this, \"expressions\");\n    },\n});\n\nfunction root_expr(prop) {\n    while (prop instanceof AST_PropAccess) prop = prop.expression;\n    return prop;\n}\n\nvar AST_PropAccess = DEFNODE(\"PropAccess\", \"expression optional property terminal\", {\n    $documentation: \"Base class for property access expressions, i.e. `a.foo` or `a[\\\"foo\\\"]`\",\n    $propdoc: {\n        expression: \"[AST_Node] the “container” expression\",\n        optional: \"[boolean] whether the expression is optional chaining\",\n        property: \"[AST_Node|string] the property to access.  For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node\",\n        terminal: \"[boolean] whether the chain has ended\",\n    },\n    _equals: function(node) {\n        return !this.optional == !node.optional\n            && prop_equals(this.property, node.property)\n            && this.expression.equals(node.expression);\n    },\n    get_property: function() {\n        var p = this.property;\n        if (p instanceof AST_Constant) return p.value;\n        if (p instanceof AST_UnaryPrefix && p.operator == \"void\" && p.expression instanceof AST_Constant) return;\n        return p;\n    },\n    _validate: function() {\n        if (this.TYPE == \"PropAccess\") throw new Error(\"should not instantiate AST_PropAccess\");\n        must_be_expression(this, \"expression\");\n    },\n});\n\nvar AST_Dot = DEFNODE(\"Dot\", \"quoted\", {\n    $documentation: \"A dotted property access expression\",\n    $propdoc: {\n        quoted: \"[boolean] whether property is transformed from a quoted string\",\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (typeof this.property != \"string\") throw new Error(\"property must be string\");\n    },\n}, AST_PropAccess);\n\nvar AST_Sub = DEFNODE(\"Sub\", null, {\n    $documentation: \"Index-style property access, i.e. `a[\\\"foo\\\"]`\",\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n            node.property.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"property\");\n    },\n}, AST_PropAccess);\n\nvar AST_Spread = DEFNODE(\"Spread\", \"expression\", {\n    $documentation: \"Spread expression in array/object literals or function calls\",\n    $propdoc: {\n        expression: \"[AST_Node] expression to be expanded\",\n    },\n    _equals: function(node) {\n        return this.expression.equals(node.expression);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"expression\");\n    },\n});\n\nvar AST_Unary = DEFNODE(\"Unary\", \"operator expression\", {\n    $documentation: \"Base class for unary expressions\",\n    $propdoc: {\n        operator: \"[string] the operator\",\n        expression: \"[AST_Node] expression that this unary operator applies to\",\n    },\n    _equals: function(node) {\n        return this.operator == node.operator\n            && this.expression.equals(node.expression);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"Unary\") throw new Error(\"should not instantiate AST_Unary\");\n        if (typeof this.operator != \"string\") throw new Error(\"operator must be string\");\n        must_be_expression(this, \"expression\");\n    },\n});\n\nvar AST_UnaryPrefix = DEFNODE(\"UnaryPrefix\", null, {\n    $documentation: \"Unary prefix expression, i.e. `typeof i` or `++i`\"\n}, AST_Unary);\n\nvar AST_UnaryPostfix = DEFNODE(\"UnaryPostfix\", null, {\n    $documentation: \"Unary postfix expression, i.e. `i++`\"\n}, AST_Unary);\n\nvar AST_Binary = DEFNODE(\"Binary\", \"operator left right\", {\n    $documentation: \"Binary expression, i.e. `a + b`\",\n    $propdoc: {\n        left: \"[AST_Node] left-hand side expression\",\n        operator: \"[string] the operator\",\n        right: \"[AST_Node] right-hand side expression\"\n    },\n    _equals: function(node) {\n        return this.operator == node.operator\n            && this.left.equals(node.left)\n            && this.right.equals(node.right);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.left.walk(visitor);\n            node.right.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (!(this instanceof AST_Assign)) must_be_expression(this, \"left\");\n        if (typeof this.operator != \"string\") throw new Error(\"operator must be string\");\n        must_be_expression(this, \"right\");\n    },\n});\n\nvar AST_Conditional = DEFNODE(\"Conditional\", \"condition consequent alternative\", {\n    $documentation: \"Conditional expression using the ternary operator, i.e. `a ? b : c`\",\n    $propdoc: {\n        condition: \"[AST_Node]\",\n        consequent: \"[AST_Node]\",\n        alternative: \"[AST_Node]\"\n    },\n    _equals: function(node) {\n        return this.condition.equals(node.condition)\n            && this.consequent.equals(node.consequent)\n            && this.alternative.equals(node.alternative);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.condition.walk(visitor);\n            node.consequent.walk(visitor);\n            node.alternative.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"condition\");\n        must_be_expression(this, \"consequent\");\n        must_be_expression(this, \"alternative\");\n    },\n});\n\nvar AST_Assign = DEFNODE(\"Assign\", null, {\n    $documentation: \"An assignment expression — `a = b + 5`\",\n    _validate: function() {\n        if (this.operator.indexOf(\"=\") < 0) throw new Error('operator must contain \"=\"');\n        if (this.left instanceof AST_Destructured) {\n            if (this.operator != \"=\") throw new Error(\"invalid destructuring operator: \" + this.operator);\n            validate_destructured(this.left, function(node) {\n                if (!(node instanceof AST_PropAccess || node instanceof AST_SymbolRef)) {\n                    throw new Error(\"left must be assignable: \" + node.TYPE);\n                }\n            });\n        } else if (!(this.left instanceof AST_Infinity\n            || this.left instanceof AST_NaN\n            || this.left instanceof AST_PropAccess && !this.left.optional\n            || this.left instanceof AST_SymbolRef\n            || this.left instanceof AST_Undefined)) {\n            throw new Error(\"left must be assignable\");\n        }\n    },\n}, AST_Binary);\n\nvar AST_Await = DEFNODE(\"Await\", \"expression\", {\n    $documentation: \"An await expression\",\n    $propdoc: {\n        expression: \"[AST_Node] expression with Promise to resolve on\",\n    },\n    _equals: function(node) {\n        return this.expression.equals(node.expression);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.expression.walk(visitor);\n        });\n    },\n    _validate: function() {\n        must_be_expression(this, \"expression\");\n    },\n});\n\nvar AST_Yield = DEFNODE(\"Yield\", \"expression nested\", {\n    $documentation: \"A yield expression\",\n    $propdoc: {\n        expression: \"[AST_Node?] return value for iterator, or null if undefined\",\n        nested: \"[boolean] whether to iterate over expression as generator\",\n    },\n    _equals: function(node) {\n        return !this.nested == !node.nested\n            && prop_equals(this.expression, node.expression);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.expression) node.expression.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.expression != null) {\n            must_be_expression(this, \"expression\");\n        } else if (this.nested) {\n            throw new Error(\"yield* must contain expression\");\n        }\n    },\n});\n\n/* -----[ LITERALS ]----- */\n\nvar AST_Array = DEFNODE(\"Array\", \"elements\", {\n    $documentation: \"An array literal\",\n    $propdoc: {\n        elements: \"[AST_Node*] array of elements\"\n    },\n    _equals: function(node) {\n        return all_equals(this.elements, node.elements);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.elements.forEach(function(element) {\n                element.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        must_be_expressions(this, \"elements\", true, true);\n    },\n});\n\nvar AST_Destructured = DEFNODE(\"Destructured\", \"rest\", {\n    $documentation: \"Base class for destructured literal\",\n    $propdoc: {\n        rest: \"[(AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)?] rest parameter, or null if absent\",\n    },\n    _validate: function() {\n        if (this.TYPE == \"Destructured\") throw new Error(\"should not instantiate AST_Destructured\");\n    },\n});\n\nfunction validate_destructured(node, check, allow_default) {\n    if (node instanceof AST_DefaultValue && allow_default) return validate_destructured(node.name, check);\n    if (node instanceof AST_Destructured) {\n        if (node.rest != null) validate_destructured(node.rest, check);\n        if (node instanceof AST_DestructuredArray) return node.elements.forEach(function(node) {\n            if (!(node instanceof AST_Hole)) validate_destructured(node, check, true);\n        });\n        if (node instanceof AST_DestructuredObject) return node.properties.forEach(function(prop) {\n            validate_destructured(prop.value, check, true);\n        });\n    }\n    check(node);\n}\n\nvar AST_DestructuredArray = DEFNODE(\"DestructuredArray\", \"elements\", {\n    $documentation: \"A destructured array literal\",\n    $propdoc: {\n        elements: \"[(AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)*] array of elements\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.rest, node.rest)\n            && all_equals(this.elements, node.elements);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.elements.forEach(function(element) {\n                element.walk(visitor);\n            });\n            if (node.rest) node.rest.walk(visitor);\n        });\n    },\n}, AST_Destructured);\n\nvar AST_DestructuredKeyVal = DEFNODE(\"DestructuredKeyVal\", \"key value\", {\n    $documentation: \"A key: value destructured property\",\n    $propdoc: {\n        key: \"[string|AST_Node] property name.  For computed property this is an AST_Node.\",\n        value: \"[AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef] property value\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.key, node.key)\n            && this.value.equals(node.value);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.key instanceof AST_Node) node.key.walk(visitor);\n            node.value.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (typeof this.key != \"string\") {\n            if (!(this.key instanceof AST_Node)) throw new Error(\"key must be string or AST_Node\");\n            must_be_expression(this, \"key\");\n        }\n        if (!(this.value instanceof AST_Node)) throw new Error(\"value must be AST_Node\");\n    },\n});\n\nvar AST_DestructuredObject = DEFNODE(\"DestructuredObject\", \"properties\", {\n    $documentation: \"A destructured object literal\",\n    $propdoc: {\n        properties: \"[AST_DestructuredKeyVal*] array of properties\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.rest, node.rest)\n            && all_equals(this.properties, node.properties);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.properties.forEach(function(prop) {\n                prop.walk(visitor);\n            });\n            if (node.rest) node.rest.walk(visitor);\n        });\n    },\n    _validate: function() {\n        this.properties.forEach(function(node) {\n            if (!(node instanceof AST_DestructuredKeyVal)) throw new Error(\"properties must be AST_DestructuredKeyVal[]\");\n        });\n    },\n}, AST_Destructured);\n\nvar AST_Object = DEFNODE(\"Object\", \"properties\", {\n    $documentation: \"An object literal\",\n    $propdoc: {\n        properties: \"[(AST_ObjectProperty|AST_Spread)*] array of properties\"\n    },\n    _equals: function(node) {\n        return all_equals(this.properties, node.properties);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            node.properties.forEach(function(prop) {\n                prop.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        this.properties.forEach(function(node) {\n            if (!(node instanceof AST_ObjectProperty || node instanceof AST_Spread)) {\n                throw new Error(\"properties must contain AST_ObjectProperty and/or AST_Spread only\");\n            }\n        });\n    },\n});\n\nvar AST_ObjectProperty = DEFNODE(\"ObjectProperty\", \"key value\", {\n    $documentation: \"Base class for literal object properties\",\n    $propdoc: {\n        key: \"[string|AST_Node] property name.  For computed property this is an AST_Node.\",\n        value: \"[AST_Node] property value.  For getters and setters this is an AST_Accessor.\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.key, node.key)\n            && this.value.equals(node.value);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.key instanceof AST_Node) node.key.walk(visitor);\n            node.value.walk(visitor);\n        });\n    },\n    _validate: function() {\n        if (this.TYPE == \"ObjectProperty\") throw new Error(\"should not instantiate AST_ObjectProperty\");\n        if (typeof this.key != \"string\") {\n            if (!(this.key instanceof AST_Node)) throw new Error(\"key must be string or AST_Node\");\n            must_be_expression(this, \"key\");\n        }\n        if (!(this.value instanceof AST_Node)) throw new Error(\"value must be AST_Node\");\n    },\n});\n\nvar AST_ObjectKeyVal = DEFNODE(\"ObjectKeyVal\", null, {\n    $documentation: \"A key: value object property\",\n    _validate: function() {\n        must_be_expression(this, \"value\");\n    },\n}, AST_ObjectProperty);\n\nvar AST_ObjectMethod = DEFNODE(\"ObjectMethod\", null, {\n    $documentation: \"A key(){} object property\",\n    _validate: function() {\n        if (!(this.value instanceof AST_LambdaExpression)) throw new Error(\"value must be AST_LambdaExpression\");\n        if (is_arrow(this.value)) throw new Error(\"value cannot be AST_Arrow or AST_AsyncArrow\");\n        if (this.value.name != null) throw new Error(\"name of object method's lambda must be null\");\n    },\n}, AST_ObjectKeyVal);\n\nvar AST_ObjectSetter = DEFNODE(\"ObjectSetter\", null, {\n    $documentation: \"An object setter property\",\n    _validate: function() {\n        if (!(this.value instanceof AST_Accessor)) throw new Error(\"value must be AST_Accessor\");\n    },\n}, AST_ObjectProperty);\n\nvar AST_ObjectGetter = DEFNODE(\"ObjectGetter\", null, {\n    $documentation: \"An object getter property\",\n    _validate: function() {\n        if (!(this.value instanceof AST_Accessor)) throw new Error(\"value must be AST_Accessor\");\n    },\n}, AST_ObjectProperty);\n\nvar AST_Symbol = DEFNODE(\"Symbol\", \"scope name thedef\", {\n    $documentation: \"Base class for all symbols\",\n    $propdoc: {\n        name: \"[string] name of this symbol\",\n        scope: \"[AST_Scope/S] the current scope (not necessarily the definition scope)\",\n        thedef: \"[SymbolDef/S] the definition of this symbol\"\n    },\n    _equals: function(node) {\n        return this.thedef ? this.thedef === node.thedef : this.name == node.name;\n    },\n    _validate: function() {\n        if (this.TYPE == \"Symbol\") throw new Error(\"should not instantiate AST_Symbol\");\n        if (typeof this.name != \"string\") throw new Error(\"name must be string\");\n    },\n});\n\nvar AST_SymbolDeclaration = DEFNODE(\"SymbolDeclaration\", \"init\", {\n    $documentation: \"A declaration symbol (symbol in var, function name or argument, symbol in catch)\",\n}, AST_Symbol);\n\nvar AST_SymbolConst = DEFNODE(\"SymbolConst\", null, {\n    $documentation: \"Symbol defining a constant\",\n}, AST_SymbolDeclaration);\n\nvar AST_SymbolImport = DEFNODE(\"SymbolImport\", \"key\", {\n    $documentation: \"Symbol defined by an `import` statement\",\n    $propdoc: {\n        key: \"[AST_String] the original `export` name\",\n    },\n    _equals: function(node) {\n        return this.name == node.name\n            && this.key.equals(node.key);\n    },\n    _validate: function() {\n        if (!(this.key instanceof AST_String)) throw new Error(\"key must be AST_String\");\n    },\n}, AST_SymbolConst);\n\nvar AST_SymbolLet = DEFNODE(\"SymbolLet\", null, {\n    $documentation: \"Symbol defining a lexical-scoped variable\",\n}, AST_SymbolDeclaration);\n\nvar AST_SymbolVar = DEFNODE(\"SymbolVar\", null, {\n    $documentation: \"Symbol defining a variable\",\n}, AST_SymbolDeclaration);\n\nvar AST_SymbolFunarg = DEFNODE(\"SymbolFunarg\", \"unused\", {\n    $documentation: \"Symbol naming a function argument\",\n}, AST_SymbolVar);\n\nvar AST_SymbolDefun = DEFNODE(\"SymbolDefun\", null, {\n    $documentation: \"Symbol defining a function\",\n}, AST_SymbolDeclaration);\n\nvar AST_SymbolLambda = DEFNODE(\"SymbolLambda\", null, {\n    $documentation: \"Symbol naming a function expression\",\n}, AST_SymbolDeclaration);\n\nvar AST_SymbolDefClass = DEFNODE(\"SymbolDefClass\", null, {\n    $documentation: \"Symbol defining a class\",\n}, AST_SymbolConst);\n\nvar AST_SymbolClass = DEFNODE(\"SymbolClass\", null, {\n    $documentation: \"Symbol naming a class expression\",\n}, AST_SymbolConst);\n\nvar AST_SymbolCatch = DEFNODE(\"SymbolCatch\", null, {\n    $documentation: \"Symbol naming the exception in catch\",\n}, AST_SymbolDeclaration);\n\nvar AST_Label = DEFNODE(\"Label\", \"references\", {\n    $documentation: \"Symbol naming a label (declaration)\",\n    $propdoc: {\n        references: \"[AST_LoopControl*] a list of nodes referring to this label\"\n    },\n    initialize: function() {\n        this.references = [];\n        this.thedef = this;\n    },\n}, AST_Symbol);\n\nvar AST_SymbolRef = DEFNODE(\"SymbolRef\", \"fixed in_arg redef\", {\n    $documentation: \"Reference to some symbol (not definition/declaration)\",\n}, AST_Symbol);\n\nvar AST_SymbolExport = DEFNODE(\"SymbolExport\", \"alias\", {\n    $documentation: \"Reference in an `export` statement\",\n    $propdoc: {\n        alias: \"[AST_String] the `export` alias\",\n    },\n    _equals: function(node) {\n        return this.name == node.name\n            && this.alias.equals(node.alias);\n    },\n    _validate: function() {\n        if (!(this.alias instanceof AST_String)) throw new Error(\"alias must be AST_String\");\n    },\n}, AST_SymbolRef);\n\nvar AST_LabelRef = DEFNODE(\"LabelRef\", null, {\n    $documentation: \"Reference to a label symbol\",\n}, AST_Symbol);\n\nvar AST_ObjectIdentity = DEFNODE(\"ObjectIdentity\", null, {\n    $documentation: \"Base class for `super` & `this`\",\n    _equals: return_true,\n    _validate: function() {\n        if (this.TYPE == \"ObjectIdentity\") throw new Error(\"should not instantiate AST_ObjectIdentity\");\n    },\n}, AST_Symbol);\n\nvar AST_Super = DEFNODE(\"Super\", null, {\n    $documentation: \"The `super` symbol\",\n    _validate: function() {\n        if (this.name !== \"super\") throw new Error('name must be \"super\"');\n    },\n}, AST_ObjectIdentity);\n\nvar AST_This = DEFNODE(\"This\", null, {\n    $documentation: \"The `this` symbol\",\n    _validate: function() {\n        if (this.TYPE == \"This\" && this.name !== \"this\") throw new Error('name must be \"this\"');\n    },\n}, AST_ObjectIdentity);\n\nvar AST_NewTarget = DEFNODE(\"NewTarget\", null, {\n    $documentation: \"The `new.target` symbol\",\n    initialize: function() {\n        this.name = \"new.target\";\n    },\n    _validate: function() {\n        if (this.name !== \"new.target\") throw new Error('name must be \"new.target\": ' + this.name);\n    },\n}, AST_This);\n\nvar AST_Template = DEFNODE(\"Template\", \"expressions strings tag\", {\n    $documentation: \"A template literal, i.e. tag`str1${expr1}...strN${exprN}strN+1`\",\n    $propdoc: {\n        expressions: \"[AST_Node*] the placeholder expressions\",\n        strings: \"[string*] the raw text segments\",\n        tag: \"[AST_Node?] tag function, or null if absent\",\n    },\n    _equals: function(node) {\n        return prop_equals(this.tag, node.tag)\n            && list_equals(this.strings, node.strings)\n            && all_equals(this.expressions, node.expressions);\n    },\n    walk: function(visitor) {\n        var node = this;\n        visitor.visit(node, function() {\n            if (node.tag) node.tag.walk(visitor);\n            node.expressions.forEach(function(expr) {\n                expr.walk(visitor);\n            });\n        });\n    },\n    _validate: function() {\n        if (this.expressions.length + 1 != this.strings.length) {\n            throw new Error(\"malformed template with \" + this.expressions.length + \" placeholder(s) but \" + this.strings.length + \" text segment(s)\");\n        }\n        must_be_expressions(this, \"expressions\");\n        this.strings.forEach(function(string) {\n            if (typeof string != \"string\") throw new Error(\"strings must contain string\");\n        });\n        if (this.tag != null) must_be_expression(this, \"tag\");\n    },\n});\n\nvar AST_Constant = DEFNODE(\"Constant\", null, {\n    $documentation: \"Base class for all constants\",\n    _equals: function(node) {\n        return this.value === node.value;\n    },\n    _validate: function() {\n        if (this.TYPE == \"Constant\") throw new Error(\"should not instantiate AST_Constant\");\n    },\n});\n\nvar AST_String = DEFNODE(\"String\", \"quote value\", {\n    $documentation: \"A string literal\",\n    $propdoc: {\n        quote: \"[string?] the original quote character\",\n        value: \"[string] the contents of this string\",\n    },\n    _validate: function() {\n        if (this.quote != null) {\n            if (typeof this.quote != \"string\") throw new Error(\"quote must be string\");\n            if (!/^[\"']$/.test(this.quote)) throw new Error(\"invalid quote: \" + this.quote);\n        }\n        if (typeof this.value != \"string\") throw new Error(\"value must be string\");\n    },\n}, AST_Constant);\n\nvar AST_Number = DEFNODE(\"Number\", \"value\", {\n    $documentation: \"A number literal\",\n    $propdoc: {\n        value: \"[number] the numeric value\",\n    },\n    _validate: function() {\n        if (typeof this.value != \"number\") throw new Error(\"value must be number\");\n        if (!isFinite(this.value)) throw new Error(\"value must be finite\");\n        if (this.value < 0) throw new Error(\"value cannot be negative\");\n    },\n}, AST_Constant);\n\nvar AST_BigInt = DEFNODE(\"BigInt\", \"value\", {\n    $documentation: \"A BigInt literal\",\n    $propdoc: {\n        value: \"[string] the numeric representation\",\n    },\n    _validate: function() {\n        if (typeof this.value != \"string\") throw new Error(\"value must be string\");\n        if (this.value[0] == \"-\") throw new Error(\"value cannot be negative\");\n    },\n}, AST_Constant);\n\nvar AST_RegExp = DEFNODE(\"RegExp\", \"value\", {\n    $documentation: \"A regexp literal\",\n    $propdoc: {\n        value: \"[RegExp] the actual regexp\"\n    },\n    _equals: function(node) {\n        return \"\" + this.value == \"\" + node.value;\n    },\n    _validate: function() {\n        if (!(this.value instanceof RegExp)) throw new Error(\"value must be RegExp\");\n    },\n}, AST_Constant);\n\nvar AST_Atom = DEFNODE(\"Atom\", null, {\n    $documentation: \"Base class for atoms\",\n    _equals: return_true,\n    _validate: function() {\n        if (this.TYPE == \"Atom\") throw new Error(\"should not instantiate AST_Atom\");\n    },\n}, AST_Constant);\n\nvar AST_Null = DEFNODE(\"Null\", null, {\n    $documentation: \"The `null` atom\",\n    value: null,\n}, AST_Atom);\n\nvar AST_NaN = DEFNODE(\"NaN\", null, {\n    $documentation: \"The impossible value\",\n    value: 0/0,\n}, AST_Atom);\n\nvar AST_Undefined = DEFNODE(\"Undefined\", null, {\n    $documentation: \"The `undefined` value\",\n    value: function(){}(),\n}, AST_Atom);\n\nvar AST_Hole = DEFNODE(\"Hole\", null, {\n    $documentation: \"A hole in an array\",\n    value: function(){}(),\n}, AST_Atom);\n\nvar AST_Infinity = DEFNODE(\"Infinity\", null, {\n    $documentation: \"The `Infinity` value\",\n    value: 1/0,\n}, AST_Atom);\n\nvar AST_Boolean = DEFNODE(\"Boolean\", null, {\n    $documentation: \"Base class for booleans\",\n    _validate: function() {\n        if (this.TYPE == \"Boolean\") throw new Error(\"should not instantiate AST_Boolean\");\n    },\n}, AST_Atom);\n\nvar AST_False = DEFNODE(\"False\", null, {\n    $documentation: \"The `false` atom\",\n    value: false,\n}, AST_Boolean);\n\nvar AST_True = DEFNODE(\"True\", null, {\n    $documentation: \"The `true` atom\",\n    value: true,\n}, AST_Boolean);\n\n/* -----[ TreeWalker ]----- */\n\nfunction TreeWalker(callback) {\n    this.callback = callback;\n    this.directives = Object.create(null);\n    this.stack = [];\n}\nTreeWalker.prototype = {\n    visit: function(node, descend) {\n        this.push(node);\n        var done = this.callback(node, descend || noop);\n        if (!done && descend) descend();\n        this.pop();\n    },\n    parent: function(n) {\n        return this.stack[this.stack.length - 2 - (n || 0)];\n    },\n    push: function(node) {\n        var value;\n        if (node instanceof AST_Class) {\n            this.directives = Object.create(this.directives);\n            value = \"use strict\";\n        } else if (node instanceof AST_Directive) {\n            value = node.value;\n        } else if (node instanceof AST_Lambda) {\n            this.directives = Object.create(this.directives);\n        }\n        if (value && !this.directives[value]) this.directives[value] = node;\n        this.stack.push(node);\n    },\n    pop: function() {\n        var node = this.stack.pop();\n        if (node instanceof AST_Class || node instanceof AST_Lambda) {\n            this.directives = Object.getPrototypeOf(this.directives);\n        }\n    },\n    self: function() {\n        return this.stack[this.stack.length - 1];\n    },\n    find_parent: function(type) {\n        var stack = this.stack;\n        for (var i = stack.length - 1; --i >= 0;) {\n            var x = stack[i];\n            if (x instanceof type) return x;\n        }\n    },\n    has_directive: function(type) {\n        var dir = this.directives[type];\n        if (dir) return dir;\n        var node = this.stack[this.stack.length - 1];\n        if (node instanceof AST_Scope) {\n            for (var i = 0; i < node.body.length; ++i) {\n                var st = node.body[i];\n                if (!(st instanceof AST_Directive)) break;\n                if (st.value == type) return st;\n            }\n        }\n    },\n    loopcontrol_target: function(node) {\n        var stack = this.stack;\n        if (node.label) for (var i = stack.length; --i >= 0;) {\n            var x = stack[i];\n            if (x instanceof AST_LabeledStatement && x.label.name == node.label.name)\n                return x.body;\n        } else for (var i = stack.length; --i >= 0;) {\n            var x = stack[i];\n            if (x instanceof AST_IterationStatement\n                || node instanceof AST_Break && x instanceof AST_Switch)\n                return x;\n        }\n    },\n    in_boolean_context: function() {\n        for (var drop = true, level = 0, parent, self = this.self(); parent = this.parent(level++); self = parent) {\n            if (parent instanceof AST_Binary) switch (parent.operator) {\n              case \"&&\":\n              case \"||\":\n                if (parent.left === self) drop = false;\n                continue;\n              default:\n                return false;\n            }\n            if (parent instanceof AST_Conditional) {\n                if (parent.condition === self) return true;\n                continue;\n            }\n            if (parent instanceof AST_DWLoop) return parent.condition === self;\n            if (parent instanceof AST_For) return parent.condition === self;\n            if (parent instanceof AST_If) return parent.condition === self;\n            if (parent instanceof AST_Return) {\n                if (parent.in_bool) return true;\n                while (parent = this.parent(level++)) {\n                    if (parent instanceof AST_Lambda) {\n                        if (parent.name) return false;\n                        parent = this.parent(level++);\n                        if (parent.TYPE != \"Call\") return false;\n                        break;\n                    }\n                }\n            }\n            if (parent instanceof AST_Sequence) {\n                if (parent.tail_node() === self) continue;\n                return drop ? \"d\" : true;\n            }\n            if (parent instanceof AST_SimpleStatement) return drop ? \"d\" : true;\n            if (parent instanceof AST_UnaryPrefix) return parent.operator == \"!\";\n            return false;\n        }\n    }\n};\n"
  },
  {
    "path": "lib/compress.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction Compressor(options, false_by_default) {\n    if (!(this instanceof Compressor))\n        return new Compressor(options, false_by_default);\n    TreeTransformer.call(this, this.before, this.after);\n    this.options = defaults(options, {\n        annotations     : !false_by_default,\n        arguments       : !false_by_default,\n        arrows          : !false_by_default,\n        assignments     : !false_by_default,\n        awaits          : !false_by_default,\n        booleans        : !false_by_default,\n        collapse_vars   : !false_by_default,\n        comparisons     : !false_by_default,\n        conditionals    : !false_by_default,\n        dead_code       : !false_by_default,\n        default_values  : !false_by_default,\n        directives      : !false_by_default,\n        drop_console    : false,\n        drop_debugger   : !false_by_default,\n        evaluate        : !false_by_default,\n        expression      : false,\n        functions       : !false_by_default,\n        global_defs     : false,\n        hoist_exports   : !false_by_default,\n        hoist_funs      : false,\n        hoist_props     : !false_by_default,\n        hoist_vars      : false,\n        ie              : false,\n        if_return       : !false_by_default,\n        imports         : !false_by_default,\n        inline          : !false_by_default,\n        join_vars       : !false_by_default,\n        keep_fargs      : false_by_default,\n        keep_fnames     : false,\n        keep_infinity   : false,\n        loops           : !false_by_default,\n        merge_vars      : !false_by_default,\n        module          : false,\n        negate_iife     : !false_by_default,\n        objects         : !false_by_default,\n        optional_chains : !false_by_default,\n        passes          : 1,\n        properties      : !false_by_default,\n        pure_funcs      : null,\n        pure_getters    : !false_by_default && \"strict\",\n        reduce_funcs    : !false_by_default,\n        reduce_vars     : !false_by_default,\n        rests           : !false_by_default,\n        sequences       : !false_by_default,\n        side_effects    : !false_by_default,\n        spreads         : !false_by_default,\n        strings         : !false_by_default,\n        switches        : !false_by_default,\n        templates       : !false_by_default,\n        top_retain      : null,\n        toplevel        : !!(options && !options[\"expression\"] && options[\"top_retain\"]),\n        typeofs         : !false_by_default,\n        unsafe          : false,\n        unsafe_comps    : false,\n        unsafe_Function : false,\n        unsafe_math     : false,\n        unsafe_proto    : false,\n        unsafe_regexp   : false,\n        unsafe_undefined: false,\n        unused          : !false_by_default,\n        varify          : !false_by_default,\n        webkit          : false,\n        yields          : !false_by_default,\n    }, true);\n    var evaluate = this.options[\"evaluate\"];\n    this.eval_threshold = /eager/.test(evaluate) ? 1 / 0 : +evaluate;\n    var global_defs = this.options[\"global_defs\"];\n    if (typeof global_defs == \"object\") for (var key in global_defs) {\n        if (/^@/.test(key) && HOP(global_defs, key)) {\n            global_defs[key.slice(1)] = parse(global_defs[key], { expression: true });\n        }\n    }\n    if (this.options[\"inline\"] === true) this.options[\"inline\"] = 4;\n    this.drop_fargs = this.options[\"keep_fargs\"] ? return_false : function(lambda, parent) {\n        if (lambda.length_read) return false;\n        var name = lambda.name;\n        if (!name) return parent && parent.TYPE == \"Call\" && parent.expression === lambda;\n        if (name.fixed_value() !== lambda) return false;\n        var def = name.definition();\n        if (def.direct_access) return false;\n        var escaped = def.escaped;\n        return escaped && escaped.depth != 1;\n    };\n    if (this.options[\"module\"]) this.directives[\"use strict\"] = true;\n    var pure_funcs = this.options[\"pure_funcs\"];\n    if (typeof pure_funcs == \"function\") {\n        this.pure_funcs = pure_funcs;\n    } else if (typeof pure_funcs == \"string\") {\n        this.pure_funcs = function(node) {\n            var expr;\n            if (node instanceof AST_Call) {\n                expr = node.expression;\n            } else if (node instanceof AST_Template) {\n                expr = node.tag;\n            }\n            return !(expr && pure_funcs === expr.print_to_string());\n        };\n    } else if (Array.isArray(pure_funcs)) {\n        this.pure_funcs = function(node) {\n            var expr;\n            if (node instanceof AST_Call) {\n                expr = node.expression;\n            } else if (node instanceof AST_Template) {\n                expr = node.tag;\n            }\n            return !(expr && member(expr.print_to_string(), pure_funcs));\n        };\n    } else {\n        this.pure_funcs = return_true;\n    }\n    var sequences = this.options[\"sequences\"];\n    this.sequences_limit = sequences == 1 ? 800 : sequences | 0;\n    var top_retain = this.options[\"top_retain\"];\n    if (top_retain instanceof RegExp) {\n        this.top_retain = function(def) {\n            return top_retain.test(def.name);\n        };\n    } else if (typeof top_retain == \"function\") {\n        this.top_retain = top_retain;\n    } else if (top_retain) {\n        if (typeof top_retain == \"string\") {\n            top_retain = top_retain.split(/,/);\n        }\n        this.top_retain = function(def) {\n            return member(def.name, top_retain);\n        };\n    }\n    var toplevel = this.options[\"toplevel\"];\n    this.toplevel = typeof toplevel == \"string\" ? {\n        funcs: /funcs/.test(toplevel),\n        vars: /vars/.test(toplevel)\n    } : {\n        funcs: toplevel,\n        vars: toplevel\n    };\n}\n\nCompressor.prototype = new TreeTransformer(function(node, descend) {\n    if (node._squeezed) return node;\n    var is_scope = node instanceof AST_Scope;\n    if (is_scope) {\n        if (this.option(\"arrows\") && is_arrow(node) && node.value) {\n            node.body = [ node.first_statement() ];\n            node.value = null;\n        }\n        node.hoist_properties(this);\n        node.hoist_declarations(this);\n        node.process_returns(this);\n    }\n    // Before https://github.com/mishoo/UglifyJS/pull/1602 AST_Node.optimize()\n    // would call AST_Node.transform() if a different instance of AST_Node is\n    // produced after OPT().\n    // This corrupts TreeWalker.stack, which cause AST look-ups to malfunction.\n    // Migrate and defer all children's AST_Node.transform() to below, which\n    // will now happen after this parent AST_Node has been properly substituted\n    // thus gives a consistent AST snapshot.\n    descend(node, this);\n    // Existing code relies on how AST_Node.optimize() worked, and omitting the\n    // following replacement call would result in degraded efficiency of both\n    // output and performance.\n    descend(node, this);\n    var opt = node.optimize(this);\n    if (is_scope) {\n        if (opt === node && !this.has_directive(\"use asm\") && !opt.pinned()) {\n            opt.drop_unused(this);\n            if (opt.merge_variables(this)) opt.drop_unused(this);\n            descend(opt, this);\n        }\n        if (this.option(\"arrows\") && is_arrow(opt) && opt.body.length == 1) {\n            var stat = opt.body[0];\n            if (stat instanceof AST_Return) {\n                opt.body.length = 0;\n                opt.value = stat.value;\n            }\n        }\n    }\n    if (opt === node) opt._squeezed = true;\n    return opt;\n});\nCompressor.prototype.option = function(key) {\n    return this.options[key];\n};\nCompressor.prototype.exposed = function(def) {\n    if (def.exported) return true;\n    if (def.undeclared) return true;\n    if (!(def.global || def.scope.resolve() instanceof AST_Toplevel)) return false;\n    var toplevel = this.toplevel;\n    return !all(def.orig, function(sym) {\n        return toplevel[sym instanceof AST_SymbolDefun ? \"funcs\" : \"vars\"];\n    });\n};\nCompressor.prototype.compress = function(node) {\n    node = node.resolve_defines(this);\n    node.hoist_exports(this);\n    if (this.option(\"expression\")) node.process_expression(true);\n    var merge_vars = this.options.merge_vars;\n    var passes = +this.options.passes || 1;\n    var min_count = 1 / 0;\n    var stopping = false;\n    var mangle = { ie: this.option(\"ie\") };\n    for (var pass = 0; pass < passes; pass++) {\n        node.figure_out_scope(mangle);\n        if (pass > 0 || this.option(\"reduce_vars\"))\n            node.reset_opt_flags(this);\n        this.options.merge_vars = merge_vars && (stopping || pass == passes - 1);\n        node = node.transform(this);\n        if (passes > 1) {\n            var count = 0;\n            node.walk(new TreeWalker(function() {\n                count++;\n            }));\n            AST_Node.info(\"pass {pass}: last_count: {min_count}, count: {count}\", {\n                pass: pass,\n                min_count: min_count,\n                count: count,\n            });\n            if (count < min_count) {\n                min_count = count;\n                stopping = false;\n            } else if (stopping) {\n                break;\n            } else {\n                stopping = true;\n            }\n        }\n    }\n    if (this.option(\"expression\")) node.process_expression(false);\n    return node;\n};\n\n(function(OPT) {\n    OPT(AST_Node, function(self) {\n        return self;\n    });\n\n    AST_Toplevel.DEFMETHOD(\"hoist_exports\", function(compressor) {\n        if (!compressor.option(\"hoist_exports\")) return;\n        var body = this.body, props = [];\n        for (var i = 0; i < body.length; i++) {\n            var stat = body[i];\n            if (stat instanceof AST_ExportDeclaration) {\n                body[i] = stat = stat.body;\n                if (stat instanceof AST_Definitions) {\n                    stat.definitions.forEach(function(defn) {\n                        defn.name.match_symbol(export_symbol, true);\n                    });\n                } else {\n                    export_symbol(stat.name);\n                }\n            } else if (stat instanceof AST_ExportReferences) {\n                body.splice(i--, 1);\n                [].push.apply(props, stat.properties);\n            }\n        }\n        if (props.length) body.push(make_node(AST_ExportReferences, this, { properties: props }));\n\n        function export_symbol(sym) {\n            if (!(sym instanceof AST_SymbolDeclaration)) return;\n            var node = make_node(AST_SymbolExport, sym);\n            node.alias = make_node(AST_String, node, { value: node.name });\n            props.push(node);\n        }\n    });\n\n    AST_Scope.DEFMETHOD(\"process_expression\", function(insert, transform) {\n        var self = this;\n        var tt = new TreeTransformer(function(node) {\n            if (insert) {\n                if (node instanceof AST_Directive) node = make_node(AST_SimpleStatement, node, {\n                    body: make_node(AST_String, node),\n                });\n                if (node instanceof AST_SimpleStatement) {\n                    return transform ? transform(node) : make_node(AST_Return, node, { value: node.body });\n                }\n            } else if (node instanceof AST_Return) {\n                if (transform) return transform(node);\n                var value = node.value;\n                if (value instanceof AST_String) return make_node(AST_Directive, value);\n                return make_node(AST_SimpleStatement, node, {\n                    body: value || make_node(AST_UnaryPrefix, node, {\n                        operator: \"void\",\n                        expression: make_node(AST_Number, node, { value: 0 }),\n                    }),\n                });\n            }\n            if (node instanceof AST_Block) {\n                if (node instanceof AST_Lambda) {\n                    if (node !== self) return node;\n                } else if (insert === \"awaits\" && node instanceof AST_Try) {\n                    if (node.bfinally) return node;\n                }\n                for (var index = node.body.length; --index >= 0;) {\n                    var stat = node.body[index];\n                    if (!is_declaration(stat, true)) {\n                        node.body[index] = stat.transform(tt);\n                        break;\n                    }\n                }\n            } else if (node instanceof AST_If) {\n                node.body = node.body.transform(tt);\n                if (node.alternative) node.alternative = node.alternative.transform(tt);\n            } else if (node instanceof AST_With) {\n                node.body = node.body.transform(tt);\n            }\n            return node;\n        });\n        self.transform(tt);\n    });\n    AST_Toplevel.DEFMETHOD(\"unwrap_expression\", function() {\n        var self = this;\n        switch (self.body.length) {\n          case 0:\n            return make_node(AST_UnaryPrefix, self, {\n                operator: \"void\",\n                expression: make_node(AST_Number, self, { value: 0 }),\n            });\n          case 1:\n            var stat = self.body[0];\n            if (stat instanceof AST_Directive) return make_node(AST_String, stat);\n            if (stat instanceof AST_SimpleStatement) return stat.body;\n          default:\n            return make_node(AST_Call, self, {\n                expression: make_node(AST_Function, self, {\n                    argnames: [],\n                    body: self.body,\n                }).init_vars(self, self),\n                args: [],\n            });\n        }\n    });\n    AST_Node.DEFMETHOD(\"wrap_expression\", function() {\n        var self = this;\n        if (!is_statement(self)) self = make_node(AST_SimpleStatement, self, { body: self });\n        if (!(self instanceof AST_Toplevel)) self = make_node(AST_Toplevel, self, { body: [ self ] });\n        return self;\n    });\n\n    function read_property(obj, node) {\n        var key = node.get_property();\n        if (key instanceof AST_Node) return;\n        var value;\n        if (obj instanceof AST_Array) {\n            var elements = obj.elements;\n            if (key == \"length\") return make_node_from_constant(elements.length, obj);\n            if (typeof key == \"number\" && key in elements) value = elements[key];\n        } else if (obj instanceof AST_Lambda) {\n            if (key == \"length\") {\n                obj.length_read = true;\n                return make_node_from_constant(obj.argnames.length, obj);\n            }\n        } else if (obj instanceof AST_Object) {\n            key = \"\" + key;\n            var props = obj.properties;\n            for (var i = props.length; --i >= 0;) {\n                var prop = props[i];\n                if (!can_hoist_property(prop)) return;\n                if (!value && props[i].key === key) value = props[i].value;\n            }\n        }\n        return value instanceof AST_SymbolRef && value.fixed_value() || value;\n    }\n\n    function is_read_only_fn(value, name) {\n        if (value instanceof AST_Boolean) return native_fns.Boolean[name];\n        if (value instanceof AST_Number) return native_fns.Number[name];\n        if (value instanceof AST_String) return native_fns.String[name];\n        if (name == \"valueOf\") return false;\n        if (value instanceof AST_Array) return native_fns.Array[name];\n        if (value instanceof AST_Lambda) return native_fns.Function[name];\n        if (value instanceof AST_Object) return native_fns.Object[name];\n        if (value instanceof AST_RegExp) return native_fns.RegExp[name] && !value.value.global;\n    }\n\n    function is_modified(compressor, tw, node, value, level, immutable, recursive) {\n        var parent = tw.parent(level);\n        if (compressor.option(\"unsafe\") && parent instanceof AST_Dot && is_read_only_fn(value, parent.property)) {\n            return;\n        }\n        var lhs = is_lhs(node, parent);\n        if (lhs) return lhs;\n        if (level == 0 && value && value.is_constant()) return;\n        if (parent instanceof AST_Array) return is_modified(compressor, tw, parent, parent, level + 1);\n        if (parent instanceof AST_Assign) switch (parent.operator) {\n          case \"=\":\n            return is_modified(compressor, tw, parent, value, level + 1, immutable, recursive);\n          case \"&&=\":\n          case \"||=\":\n          case \"??=\":\n            return is_modified(compressor, tw, parent, parent, level + 1);\n          default:\n            return;\n        }\n        if (parent instanceof AST_Binary) {\n            if (!lazy_op[parent.operator]) return;\n            return is_modified(compressor, tw, parent, parent, level + 1);\n        }\n        if (parent instanceof AST_Call) {\n            return !immutable\n                && parent.expression === node\n                && !parent.is_expr_pure(compressor)\n                && (!(value instanceof AST_LambdaExpression) || !(parent instanceof AST_New) && value.contains_this());\n        }\n        if (parent instanceof AST_Conditional) {\n            if (parent.condition === node) return;\n            return is_modified(compressor, tw, parent, parent, level + 1);\n        }\n        if (parent instanceof AST_ForEnumeration) return parent.init === node;\n        if (parent instanceof AST_ObjectKeyVal) {\n            if (parent.value !== node) return;\n            var obj = tw.parent(level + 1);\n            return is_modified(compressor, tw, obj, obj, level + 2);\n        }\n        if (parent instanceof AST_PropAccess) {\n            if (parent.expression !== node) return;\n            var prop = read_property(value, parent);\n            return (!immutable || recursive) && is_modified(compressor, tw, parent, prop, level + 1);\n        }\n        if (parent instanceof AST_Sequence) {\n            if (parent.tail_node() !== node) return;\n            return is_modified(compressor, tw, parent, value, level + 1, immutable, recursive);\n        }\n    }\n\n    function is_lambda(node) {\n        return node instanceof AST_Class || node instanceof AST_Lambda;\n    }\n\n    function safe_for_extends(node) {\n        return node instanceof AST_Class || node instanceof AST_Defun || node instanceof AST_Function;\n    }\n\n    function is_arguments(def) {\n        return def.name == \"arguments\" && def.scope.uses_arguments;\n    }\n\n    function cross_scope(def, sym) {\n        do {\n            if (def === sym) return false;\n            if (sym instanceof AST_Scope) return true;\n        } while (sym = sym.parent_scope);\n    }\n\n    function can_drop_symbol(ref, compressor, keep_lambda) {\n        var def = ref.redef || ref.definition();\n        if (ref.in_arg && is_funarg(def)) return false;\n        return all(def.orig, function(sym) {\n            if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {\n                if (sym instanceof AST_SymbolImport) return true;\n                return compressor && safe_from_tdz(compressor, sym);\n            }\n            return !(keep_lambda && sym instanceof AST_SymbolLambda);\n        });\n    }\n\n    function has_escaped(d, scope, node, parent) {\n        if (parent instanceof AST_Assign) return parent.operator == \"=\" && parent.right === node;\n        if (parent instanceof AST_Call) return parent.expression !== node || parent instanceof AST_New;\n        if (parent instanceof AST_ClassField) return parent.value === node && !parent.static;\n        if (parent instanceof AST_Exit) return parent.value === node && scope.resolve() !== d.scope.resolve();\n        if (parent instanceof AST_VarDef) return parent.value === node;\n    }\n\n    function make_ref(ref, fixed) {\n        var node = make_node(AST_SymbolRef, ref);\n        node.fixed = fixed || make_node(AST_Undefined, ref);\n        return node;\n    }\n\n    function replace_ref(resolve, fixed) {\n        return function(node) {\n            var ref = resolve(node);\n            var node = make_ref(ref, fixed);\n            var def = ref.definition();\n            def.references.push(node);\n            def.replaced++;\n            return node;\n        };\n    }\n\n    var RE_POSITIVE_INTEGER = /^(0|[1-9][0-9]*)$/;\n    (function(def) {\n        def(AST_Node, noop);\n\n        function reset_def(tw, compressor, def) {\n            def.assignments = 0;\n            def.bool_return = 0;\n            def.cross_loop = false;\n            def.direct_access = false;\n            def.drop_return = 0;\n            def.escaped = [];\n            def.first_decl = null;\n            def.fixed = !def.const_redefs\n                && !def.scope.pinned()\n                && !compressor.exposed(def)\n                && !(def.init instanceof AST_LambdaExpression && def.init !== def.scope)\n                && def.init;\n            def.reassigned = 0;\n            def.recursive_refs = 0;\n            def.references = [];\n            def.single_use = undefined;\n        }\n\n        function reset_block_variables(tw, compressor, scope) {\n            scope.variables.each(function(def) {\n                reset_def(tw, compressor, def);\n            });\n        }\n\n        function reset_variables(tw, compressor, scope) {\n            scope.fn_defs = [];\n            scope.variables.each(function(def) {\n                reset_def(tw, compressor, def);\n                var init = def.init;\n                if (init instanceof AST_LambdaDefinition) {\n                    scope.fn_defs.push(init);\n                    init.safe_ids = null;\n                }\n                if (def.fixed === null) {\n                    def.safe_ids = tw.safe_ids;\n                    mark(tw, def);\n                } else if (def.fixed) {\n                    tw.loop_ids[def.id] = tw.in_loop;\n                    mark(tw, def);\n                }\n            });\n            scope.may_call_this = function() {\n                scope.may_call_this = scope.contains_this() ? return_true : return_false;\n            };\n            if (scope.uses_arguments) scope.each_argname(function(node) {\n                node.definition().last_ref = false;\n            });\n            if (compressor.option(\"ie\")) scope.variables.each(function(def) {\n                var d = def.orig[0].definition();\n                if (d !== def) d.fixed = false;\n            });\n        }\n\n        function safe_to_visit(tw, fn) {\n            var marker = fn.safe_ids;\n            return marker === undefined || marker === tw.safe_ids;\n        }\n\n        function walk_fn_def(tw, fn) {\n            var was_scanning = tw.fn_scanning;\n            tw.fn_scanning = fn;\n            fn.walk(tw);\n            tw.fn_scanning = was_scanning;\n        }\n\n        function revisit_fn_def(tw, fn) {\n            fn.enclosed.forEach(function(d) {\n                if (fn.variables.get(d.name) === d) return;\n                if (safe_to_read(tw, d)) return;\n                d.single_use = false;\n                var fixed = d.fixed;\n                if (typeof fixed == \"function\") fixed = fixed();\n                if (fixed instanceof AST_Lambda) {\n                    var safe_ids = fixed.safe_ids;\n                    switch (safe_ids) {\n                      case null:\n                      case false:\n                        return;\n                      default:\n                        if (safe_ids && safe_ids.seq !== tw.safe_ids.seq) return;\n                    }\n                }\n                d.fixed = false;\n            });\n        }\n\n        function mark_fn_def(tw, def, fn) {\n            var marker = fn.safe_ids;\n            if (marker === undefined) return;\n            if (marker === false) return;\n            if (fn.parent_scope.resolve().may_call_this === return_true) {\n                if (member(fn, tw.fn_visited)) revisit_fn_def(tw, fn);\n            } else if (marker) {\n                var visited = member(fn, tw.fn_visited);\n                if (marker === tw.safe_ids) {\n                    if (!visited) walk_fn_def(tw, fn);\n                } else if (visited) {\n                    revisit_fn_def(tw, fn);\n                } else {\n                    fn.safe_ids = false;\n                }\n            } else if (tw.fn_scanning && tw.fn_scanning !== def.scope.resolve()) {\n                fn.safe_ids = false;\n            } else {\n                fn.safe_ids = tw.safe_ids;\n                walk_fn_def(tw, fn);\n            }\n        }\n\n        function pop_scope(tw, scope) {\n            pop(tw);\n            var fn_defs = scope.fn_defs;\n            fn_defs.forEach(function(fn) {\n                fn.safe_ids = tw.safe_ids;\n                walk_fn_def(tw, fn);\n            });\n            fn_defs.forEach(function(fn) {\n                fn.safe_ids = undefined;\n            });\n            scope.fn_defs = undefined;\n            scope.may_call_this = undefined;\n        }\n\n        function push(tw, sequential, conditional) {\n            var defined_ids = Object.create(tw.defined_ids);\n            if (!sequential || conditional) defined_ids.seq = Object.create(null);\n            tw.defined_ids = defined_ids;\n            var safe_ids = Object.create(tw.safe_ids);\n            if (!sequential) safe_ids.seq = {};\n            if (conditional) safe_ids.cond = true;\n            tw.safe_ids = safe_ids;\n        }\n\n        function pop(tw) {\n            tw.defined_ids = Object.getPrototypeOf(tw.defined_ids);\n            tw.safe_ids = Object.getPrototypeOf(tw.safe_ids);\n        }\n\n        function access(tw, def) {\n            var seq = tw.defined_ids.seq;\n            tw.defined_ids[def.id] = seq;\n            seq[def.id] = true;\n        }\n\n        function assign(tw, def) {\n            var seq = tw.defined_ids.seq;\n            tw.assigned_ids[def.id] = seq;\n            seq[def.id] = false;\n        }\n\n        function safe_to_access(tw, def) {\n            var seq = tw.defined_ids.seq;\n            var defined = tw.defined_ids[def.id];\n            if (defined !== seq) return false;\n            if (!defined[def.id]) return false;\n            var assigned = tw.assigned_ids[def.id];\n            return !assigned || assigned === seq;\n        }\n\n        function dot(expr, tw) {\n            while (expr instanceof AST_Assign && expr.operator == \"=\") {\n                var lhs = expr.left;\n                if (lhs instanceof AST_SymbolRef) access(tw, lhs.definition());\n                expr = expr.right;\n            }\n            if (expr instanceof AST_SymbolRef) access(tw, expr.definition());\n        }\n\n        function mark(tw, def) {\n            tw.safe_ids[def.id] = {};\n        }\n\n        function push_ref(def, ref) {\n            def.references.push(ref);\n            if (def.last_ref !== false) def.last_ref = ref;\n        }\n\n        function safe_to_read(tw, def) {\n            if (def.single_use == \"m\") return false;\n            var safe = tw.safe_ids[def.id];\n            if (safe) {\n                var in_order = HOP(tw.safe_ids, def.id);\n                if (!in_order) {\n                    var seq = tw.safe_ids.seq;\n                    if (!safe.read) {\n                        safe.read = seq;\n                    } else if (safe.read !== seq) {\n                        safe.read = true;\n                    }\n                }\n                if (def.fixed == null) {\n                    if (is_arguments(def)) return false;\n                    if (def.global && def.name == \"arguments\") return false;\n                    tw.loop_ids[def.id] = null;\n                    def.fixed = make_node(AST_Undefined, def.orig[0]);\n                    if (in_order) def.safe_ids = undefined;\n                    return true;\n                }\n                return !safe.assign || safe.assign === tw.safe_ids;\n            }\n            return def.fixed instanceof AST_LambdaDefinition;\n        }\n\n        function safe_to_assign(tw, def, declare) {\n            if (!declare) {\n                if (is_funarg(def) && def.scope.uses_arguments && !tw.has_directive(\"use strict\")) return false;\n                if (!all(def.orig, function(sym) {\n                    return !(sym instanceof AST_SymbolConst);\n                })) return false;\n            }\n            if (def.fixed === undefined) return declare || all(def.orig, function(sym) {\n                return !(sym instanceof AST_SymbolLet);\n            });\n            if (def.fixed === false || def.fixed === 0) return false;\n            var safe = tw.safe_ids[def.id];\n            if (def.safe_ids) {\n                def.safe_ids[def.id] = false;\n                def.safe_ids = undefined;\n                return def.fixed === null || HOP(tw.safe_ids, def.id) && !safe.read;\n            }\n            if (!HOP(tw.safe_ids, def.id)) {\n                if (!safe) return false;\n                if (safe.read || tw.in_loop) {\n                    var scope = tw.find_parent(AST_BlockScope);\n                    if (scope instanceof AST_Class) return false;\n                    if (def.scope.resolve() !== scope.resolve()) return false;\n                }\n                safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids;\n            }\n            if (def.fixed != null && safe.read) {\n                if (safe.read !== tw.safe_ids.seq) return false;\n                if (tw.loop_ids[def.id] !== tw.in_loop) return false;\n            }\n            return safe_to_read(tw, def) && all(def.orig, function(sym) {\n                return !(sym instanceof AST_SymbolLambda);\n            });\n        }\n\n        function ref_once(compressor, def) {\n            return compressor.option(\"unused\")\n                && !def.scope.pinned()\n                && def.single_use !== false\n                && def.references.length - def.recursive_refs == 1\n                && !(is_funarg(def) && def.scope.uses_arguments);\n        }\n\n        function is_immutable(value) {\n            if (!value) return false;\n            if (value instanceof AST_Assign) {\n                var op = value.operator;\n                return op == \"=\" ? is_immutable(value.right) : !lazy_op[op.slice(0, -1)];\n            }\n            if (value instanceof AST_Sequence) return is_immutable(value.tail_node());\n            return value.is_constant() || is_lambda(value) || value instanceof AST_ObjectIdentity;\n        }\n\n        function value_in_use(node, parent) {\n            if (parent instanceof AST_Array) return true;\n            if (parent instanceof AST_Binary) return lazy_op[parent.operator];\n            if (parent instanceof AST_Conditional) return parent.condition !== node;\n            if (parent instanceof AST_Sequence) return parent.tail_node() === node;\n            if (parent instanceof AST_Spread) return true;\n        }\n\n        function mark_escaped(tw, d, scope, node, value, level, depth) {\n            var parent = tw.parent(level);\n            if (value && value.is_constant()) return;\n            if (has_escaped(d, scope, node, parent)) {\n                d.escaped.push(parent);\n                if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1;\n                if (!d.escaped.depth || d.escaped.depth > depth) d.escaped.depth = depth;\n                if (d.scope.resolve() !== scope.resolve()) d.escaped.cross_scope = true;\n                if (d.fixed) d.fixed.escaped = d.escaped;\n                return;\n            } else if (value_in_use(node, parent)) {\n                mark_escaped(tw, d, scope, parent, parent, level + 1, depth);\n            } else if (parent instanceof AST_ObjectKeyVal && parent.value === node) {\n                var obj = tw.parent(level + 1);\n                mark_escaped(tw, d, scope, obj, obj, level + 2, depth);\n            } else if (parent instanceof AST_PropAccess && parent.expression === node) {\n                value = read_property(value, parent);\n                mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1);\n                if (value) return;\n            }\n            if (level > 0) return;\n            if (parent instanceof AST_Call && parent.expression === node) return;\n            if (parent instanceof AST_Sequence && parent.tail_node() !== node) return;\n            if (parent instanceof AST_SimpleStatement) return;\n            if (parent instanceof AST_Unary && !unary_side_effects[parent.operator]) return;\n            d.direct_access = true;\n            if (d.fixed) d.fixed.direct_access = true;\n        }\n\n        function mark_assignment_to_arguments(node) {\n            if (!(node instanceof AST_Sub)) return;\n            var expr = node.expression;\n            if (!(expr instanceof AST_SymbolRef)) return;\n            var def = expr.definition();\n            if (!is_arguments(def)) return;\n            var key = node.property;\n            if (key.is_constant()) key = key.value;\n            if (!(key instanceof AST_Node) && !RE_POSITIVE_INTEGER.test(key)) return;\n            def.reassigned++;\n            (key instanceof AST_Node ? def.scope.argnames : [ def.scope.argnames[key] ]).forEach(function(argname) {\n                if (argname instanceof AST_SymbolFunarg) argname.definition().fixed = false;\n            });\n        }\n\n        function make_fixed(save, fn) {\n            var prev_save, prev_value;\n            return function() {\n                var current = save();\n                if (prev_save !== current) {\n                    prev_save = current;\n                    prev_value = fn(current);\n                }\n                return prev_value;\n            };\n        }\n\n        function make_fixed_default(compressor, node, save) {\n            var prev_save, prev_seq;\n            return function() {\n                if (prev_seq === node) return node;\n                var current = save();\n                var ev = fuzzy_eval(compressor, current, true);\n                if (ev instanceof AST_Node) {\n                    prev_seq = node;\n                } else if (prev_save !== current) {\n                    prev_save = current;\n                    prev_seq = ev === undefined ? make_sequence(node, [ current, node.value ]) : current;\n                }\n                return prev_seq;\n            };\n        }\n\n        function scan_declaration(tw, compressor, lhs, fixed, visit) {\n            var scanner = new TreeWalker(function(node) {\n                if (node instanceof AST_DefaultValue) {\n                    reset_flags(node);\n                    push(tw, true, true);\n                    node.value.walk(tw);\n                    pop(tw);\n                    var save = fixed;\n                    if (save) fixed = make_fixed_default(compressor, node, save);\n                    node.name.walk(scanner);\n                    fixed = save;\n                    return true;\n                }\n                if (node instanceof AST_DestructuredArray) {\n                    reset_flags(node);\n                    var save = fixed;\n                    node.elements.forEach(function(node, index) {\n                        if (node instanceof AST_Hole) return reset_flags(node);\n                        if (save) fixed = make_fixed(save, function(value) {\n                            return make_node(AST_Sub, node, {\n                                expression: value,\n                                property: make_node(AST_Number, node, { value: index }),\n                            });\n                        });\n                        node.walk(scanner);\n                    });\n                    if (node.rest) {\n                        var fixed_node;\n                        if (save) fixed = compressor.option(\"rests\") && make_fixed(save, function(value) {\n                            if (!(value instanceof AST_Array)) return node;\n                            for (var i = 0, len = node.elements.length; i < len; i++) {\n                                if (value.elements[i] instanceof AST_Spread) return node;\n                            }\n                            if (!fixed_node) fixed_node = make_node(AST_Array, node, {});\n                            fixed_node.elements = value.elements.slice(len);\n                            return fixed_node;\n                        });\n                        node.rest.walk(scanner);\n                    }\n                    fixed = save;\n                    return true;\n                }\n                if (node instanceof AST_DestructuredObject) {\n                    reset_flags(node);\n                    var save = fixed;\n                    node.properties.forEach(function(node) {\n                        reset_flags(node);\n                        if (node.key instanceof AST_Node) {\n                            push(tw);\n                            node.key.walk(tw);\n                            pop(tw);\n                        }\n                        if (save) fixed = make_fixed(save, function(value) {\n                            var key = node.key;\n                            var type = AST_Sub;\n                            if (typeof key == \"string\") {\n                                if (is_identifier_string(key)) {\n                                    type = AST_Dot;\n                                } else {\n                                    key = make_node_from_constant(key, node);\n                                }\n                            }\n                            return make_node(type, node, {\n                                expression: value,\n                                property: key,\n                            });\n                        });\n                        node.value.walk(scanner);\n                    });\n                    if (node.rest) {\n                        fixed = false;\n                        node.rest.walk(scanner);\n                    }\n                    fixed = save;\n                    return true;\n                }\n                visit(node, fixed, function() {\n                    var save_len = tw.stack.length;\n                    for (var i = 0, len = scanner.stack.length - 1; i < len; i++) {\n                        tw.stack.push(scanner.stack[i]);\n                    }\n                    node.walk(tw);\n                    tw.stack.length = save_len;\n                });\n                return true;\n            });\n            lhs.walk(scanner);\n        }\n\n        function reduce_iife(tw, descend, compressor) {\n            var fn = this;\n            fn.inlined = false;\n            var iife = tw.parent();\n            var sequential = !is_async(fn) && !is_generator(fn);\n            var hit = !sequential;\n            var aborts = false;\n            fn.walk(new TreeWalker(function(node) {\n                if (hit) return aborts = true;\n                if (node instanceof AST_Return) return hit = true;\n                if (node instanceof AST_Scope && node !== fn) return true;\n            }));\n            if (aborts) push(tw, sequential);\n            reset_variables(tw, compressor, fn);\n            // Virtually turn IIFE parameters into variable definitions:\n            //   (function(a,b) {...})(c,d) ---> (function() {var a=c,b=d; ...})()\n            // So existing transformation rules can work on them.\n            var safe = !fn.uses_arguments || tw.has_directive(\"use strict\");\n            fn.argnames.forEach(function(argname, i) {\n                var value = iife.args[i];\n                scan_declaration(tw, compressor, argname, function() {\n                    var j = fn.argnames.indexOf(argname);\n                    var arg = j < 0 ? value : iife.args[j];\n                    if (arg instanceof AST_Sequence && arg.expressions.length < 2) arg = arg.expressions[0];\n                    return arg || make_node(AST_Undefined, iife);\n                }, visit);\n            });\n            var rest = fn.rest, fixed_node;\n            if (rest) scan_declaration(tw, compressor, rest, compressor.option(\"rests\") && function() {\n                if (fn.rest !== rest) return rest;\n                if (!fixed_node) fixed_node = make_node(AST_Array, fn, {});\n                fixed_node.elements = iife.args.slice(fn.argnames.length);\n                return fixed_node;\n            }, visit);\n            walk_lambda(fn, tw);\n            var defined_ids = tw.defined_ids;\n            var safe_ids = tw.safe_ids;\n            pop_scope(tw, fn);\n            if (!aborts) {\n                tw.defined_ids = defined_ids;\n                tw.safe_ids = safe_ids;\n            }\n            return true;\n\n            function visit(node, fixed) {\n                var d = node.definition();\n                if (!d.first_decl && d.references.length == 0) d.first_decl = node;\n                if (fixed && safe && d.fixed === undefined) {\n                    mark(tw, d);\n                    tw.loop_ids[d.id] = tw.in_loop;\n                    d.fixed = fixed;\n                    d.fixed.assigns = [ node ];\n                } else {\n                    d.fixed = false;\n                }\n            }\n        }\n\n        def(AST_Assign, function(tw, descend, compressor) {\n            var node = this;\n            var left = node.left;\n            var right = node.right;\n            var ld = left instanceof AST_SymbolRef && left.definition();\n            var scan = ld || left instanceof AST_Destructured;\n            switch (node.operator) {\n              case \"=\":\n                if (left.equals(right) && !left.has_side_effects(compressor)) {\n                    right.walk(tw);\n                    walk_prop(left);\n                    return true;\n                }\n                if (ld && right instanceof AST_LambdaExpression) {\n                    walk_assign();\n                    right.parent_scope.resolve().fn_defs.push(right);\n                    right.safe_ids = null;\n                    if (!ld.fixed || !node.write_only || tw.safe_ids.cond) mark_fn_def(tw, ld, right);\n                    return true;\n                }\n                if (scan) {\n                    right.walk(tw);\n                    walk_assign();\n                    return true;\n                }\n                mark_assignment_to_arguments(left);\n                descend();\n                if (left instanceof AST_PropAccess) dot(left.expression, tw);\n                return true;\n              case \"&&=\":\n              case \"||=\":\n              case \"??=\":\n                var lazy = true;\n              default:\n                if (!scan) {\n                    mark_assignment_to_arguments(left);\n                    return walk_lazy();\n                }\n                assign(tw, ld);\n                ld.assignments++;\n                var fixed = ld.fixed;\n                if (is_modified(compressor, tw, node, node, 0)) {\n                    ld.fixed = false;\n                    return walk_lazy();\n                }\n                var safe = safe_to_read(tw, ld);\n                if (lazy) push(tw, true, true);\n                right.walk(tw);\n                if (lazy) pop(tw);\n                if (safe && !left.in_arg && safe_to_assign(tw, ld)) {\n                    push_ref(ld, left);\n                    mark(tw, ld);\n                    if (ld.single_use) ld.single_use = false;\n                    left.fixed = ld.fixed = function() {\n                        return make_node(AST_Binary, node, {\n                            operator: node.operator.slice(0, -1),\n                            left: make_ref(left, fixed),\n                            right: node.right,\n                        });\n                    };\n                    left.fixed.assigns = !fixed || !fixed.assigns ? [ ld.orig[0] ] : fixed.assigns.slice();\n                    left.fixed.assigns.push(node);\n                    left.fixed.to_binary = replace_ref(function(node) {\n                        return node.left;\n                    }, fixed);\n                } else {\n                    left.walk(tw);\n                    ld.fixed = false;\n                }\n                return true;\n            }\n\n            function walk_prop(lhs) {\n                reset_flags(lhs);\n                if (lhs instanceof AST_Dot) {\n                    walk_prop(lhs.expression);\n                } else if (lhs instanceof AST_Sub) {\n                    walk_prop(lhs.expression);\n                    lhs.property.walk(tw);\n                } else if (lhs instanceof AST_SymbolRef) {\n                    var d = lhs.definition();\n                    push_ref(d, lhs);\n                    if (d.fixed) {\n                        lhs.fixed = d.fixed;\n                        if (lhs.fixed.assigns) {\n                            lhs.fixed.assigns.push(node);\n                        } else {\n                            lhs.fixed.assigns = [ node ];\n                        }\n                    }\n                } else {\n                    lhs.walk(tw);\n                }\n            }\n\n            function walk_assign() {\n                var recursive = ld && recursive_ref(tw, ld);\n                var modified = is_modified(compressor, tw, node, right, 0, is_immutable(right), recursive);\n                scan_declaration(tw, compressor, left, function() {\n                    return node.right;\n                }, function(sym, fixed, walk) {\n                    if (!(sym instanceof AST_SymbolRef)) {\n                        mark_assignment_to_arguments(sym);\n                        walk();\n                        if (sym instanceof AST_PropAccess) dot(sym.expression, tw);\n                        return;\n                    }\n                    var d = sym.definition();\n                    assign(tw, d);\n                    d.assignments++;\n                    if (!fixed || sym.in_arg || !safe_to_assign(tw, d)) {\n                        walk();\n                        d.fixed = false;\n                    } else {\n                        push_ref(d, sym);\n                        mark(tw, d);\n                        if (left instanceof AST_Destructured\n                            || d.orig.length == 1 && d.orig[0] instanceof AST_SymbolDefun) {\n                            d.single_use = false;\n                        }\n                        tw.loop_ids[d.id] = tw.in_loop;\n                        d.fixed = modified ? 0 : fixed;\n                        sym.fixed = fixed;\n                        sym.fixed.assigns = [ node ];\n                        mark_escaped(tw, d, sym.scope, node, right, 0, 1);\n                    }\n                });\n            }\n\n            function walk_lazy() {\n                if (!lazy) return;\n                left.walk(tw);\n                push(tw, true, true);\n                right.walk(tw);\n                pop(tw);\n                return true;\n            }\n        });\n        def(AST_Binary, function(tw) {\n            if (!lazy_op[this.operator]) return;\n            this.left.walk(tw);\n            push(tw, true, true);\n            this.right.walk(tw);\n            pop(tw);\n            return true;\n        });\n        def(AST_BlockScope, function(tw, descend, compressor) {\n            reset_block_variables(tw, compressor, this);\n        });\n        def(AST_Call, function(tw) {\n            var node = this;\n            var exp = node.expression;\n            if (exp instanceof AST_LambdaExpression) {\n                var iife = is_iife_single(node);\n                node.args.forEach(function(arg) {\n                    arg.walk(tw);\n                    if (arg instanceof AST_Spread) iife = false;\n                });\n                if (iife) exp.reduce_vars = reduce_iife;\n                exp.walk(tw);\n                if (iife) delete exp.reduce_vars;\n                return true;\n            }\n            if (node.TYPE == \"Call\") switch (tw.in_boolean_context()) {\n              case \"d\":\n                var drop = true;\n              case true:\n                mark_refs(exp, drop);\n            }\n            exp.walk(tw);\n            var optional = node.optional;\n            if (optional) push(tw, true, true);\n            node.args.forEach(function(arg) {\n                arg.walk(tw);\n            });\n            if (optional) pop(tw);\n            var fixed = exp instanceof AST_SymbolRef && exp.fixed_value();\n            if (fixed instanceof AST_Lambda) {\n                mark_fn_def(tw, exp.definition(), fixed);\n            } else {\n                tw.defined_ids.seq = {};\n                tw.find_parent(AST_Scope).may_call_this();\n            }\n            return true;\n\n            function mark_refs(node, drop) {\n                if (node instanceof AST_Assign) {\n                    if (node.operator != \"=\") return;\n                    mark_refs(node.left, drop);\n                    mark_refs(node.right, drop);\n                } else if (node instanceof AST_Binary) {\n                    if (!lazy_op[node.operator]) return;\n                    mark_refs(node.left, drop);\n                    mark_refs(node.right, drop);\n                } else if (node instanceof AST_Conditional) {\n                    mark_refs(node.consequent, drop);\n                    mark_refs(node.alternative, drop);\n                } else if (node instanceof AST_SymbolRef) {\n                    var def = node.definition();\n                    def.bool_return++;\n                    if (drop) def.drop_return++;\n                }\n            }\n        });\n        def(AST_Class, function(tw, descend, compressor) {\n            var node = this;\n            reset_block_variables(tw, compressor, node);\n            if (node.extends) node.extends.walk(tw);\n            var props = node.properties.filter(function(prop) {\n                reset_flags(prop);\n                if (prop.key instanceof AST_Node) {\n                    tw.push(prop);\n                    prop.key.walk(tw);\n                    tw.pop();\n                }\n                return prop.value;\n            });\n            if (node.name) {\n                var d = node.name.definition();\n                var parent = tw.parent();\n                if (parent instanceof AST_ExportDeclaration || parent instanceof AST_ExportDefault) d.single_use = false;\n                if (safe_to_assign(tw, d, true)) {\n                    mark(tw, d);\n                    tw.loop_ids[d.id] = tw.in_loop;\n                    d.fixed = function() {\n                        return node;\n                    };\n                    d.fixed.assigns = [ node ];\n                    if (!is_safe_lexical(d)) d.single_use = false;\n                } else {\n                    d.fixed = false;\n                }\n            }\n            props.forEach(function(prop) {\n                tw.push(prop);\n                if (!prop.static || is_static_field_or_init(prop) && prop.value.contains_this()) {\n                    push(tw);\n                    prop.value.walk(tw);\n                    pop(tw);\n                } else {\n                    prop.value.walk(tw);\n                }\n                tw.pop();\n            });\n            return true;\n        });\n        def(AST_ClassInitBlock, function(tw, descend, compressor) {\n            var node = this;\n            push(tw, true);\n            reset_variables(tw, compressor, node);\n            descend();\n            pop_scope(tw, node);\n            return true;\n        });\n        def(AST_Conditional, function(tw) {\n            this.condition.walk(tw);\n            push(tw, true, true);\n            this.consequent.walk(tw);\n            pop(tw);\n            push(tw, true, true);\n            this.alternative.walk(tw);\n            pop(tw);\n            return true;\n        });\n        def(AST_DefaultValue, function(tw) {\n            push(tw, true, true);\n            this.value.walk(tw);\n            pop(tw);\n            this.name.walk(tw);\n            return true;\n        });\n        def(AST_Do, function(tw) {\n            var save_loop = tw.in_loop;\n            tw.in_loop = this;\n            push(tw);\n            this.body.walk(tw);\n            if (has_loop_control(this, tw.parent())) {\n                pop(tw);\n                push(tw);\n            }\n            this.condition.walk(tw);\n            pop(tw);\n            tw.in_loop = save_loop;\n            return true;\n        });\n        def(AST_Dot, function(tw, descend) {\n            descend();\n            var node = this;\n            if (!node.optional && !is_direct_assignment(node, tw.parent())) dot(node.expression, tw);\n            return true;\n        });\n        def(AST_For, function(tw, descend, compressor) {\n            var node = this;\n            reset_block_variables(tw, compressor, node);\n            if (node.init) node.init.walk(tw);\n            var save_loop = tw.in_loop;\n            tw.in_loop = node;\n            push(tw);\n            if (node.condition) node.condition.walk(tw);\n            node.body.walk(tw);\n            if (node.step) {\n                if (has_loop_control(node, tw.parent())) {\n                    pop(tw);\n                    push(tw);\n                }\n                node.step.walk(tw);\n            }\n            pop(tw);\n            tw.in_loop = save_loop;\n            return true;\n        });\n        def(AST_ForEnumeration, function(tw, descend, compressor) {\n            var node = this;\n            reset_block_variables(tw, compressor, node);\n            node.object.walk(tw);\n            var save_loop = tw.in_loop;\n            tw.in_loop = node;\n            push(tw);\n            var init = node.init;\n            if (init instanceof AST_Definitions) {\n                init.definitions[0].name.mark_symbol(function(node) {\n                    if (node instanceof AST_SymbolDeclaration) {\n                        var def = node.definition();\n                        def.assignments++;\n                        def.fixed = false;\n                    }\n                }, tw);\n            } else if (init instanceof AST_Destructured || init instanceof AST_SymbolRef) {\n                init.mark_symbol(function(node) {\n                    if (node instanceof AST_SymbolRef) {\n                        var def = node.definition();\n                        push_ref(def, node);\n                        def.assignments++;\n                        if (!node.is_immutable()) def.fixed = false;\n                    }\n                }, tw);\n            } else {\n                init.walk(tw);\n            }\n            node.body.walk(tw);\n            pop(tw);\n            tw.in_loop = save_loop;\n            return true;\n        });\n        def(AST_If, function(tw) {\n            this.condition.walk(tw);\n            push(tw, true, true);\n            this.body.walk(tw);\n            pop(tw);\n            if (this.alternative) {\n                push(tw, true, true);\n                this.alternative.walk(tw);\n                pop(tw);\n            }\n            return true;\n        });\n        def(AST_LabeledStatement, function(tw) {\n            push(tw, true);\n            this.body.walk(tw);\n            pop(tw);\n            return true;\n        });\n        def(AST_Lambda, function(tw, descend, compressor) {\n            var fn = this;\n            if (!safe_to_visit(tw, fn)) return true;\n            if (!push_uniq(tw.fn_visited, fn)) return true;\n            fn.inlined = false;\n            push(tw);\n            reset_variables(tw, compressor, fn);\n            descend();\n            pop_scope(tw, fn);\n            if (fn.name) mark_escaped(tw, fn.name.definition(), fn, fn.name, fn, 0, 1);\n            return true;\n        });\n        def(AST_LambdaDefinition, function(tw, descend, compressor) {\n            var fn = this;\n            var def = fn.name.definition();\n            if (!safe_to_trim(fn)) def.fixed = false;\n            var parent = tw.parent();\n            if (parent instanceof AST_ExportDeclaration || parent instanceof AST_ExportDefault) def.single_use = false;\n            if (!safe_to_visit(tw, fn)) return true;\n            if (!push_uniq(tw.fn_visited, fn)) return true;\n            fn.inlined = false;\n            push(tw);\n            reset_variables(tw, compressor, fn);\n            descend();\n            pop_scope(tw, fn);\n            return true;\n        });\n        def(AST_Sub, function(tw) {\n            var node = this;\n            var expr = node.expression;\n            var prop = node.property;\n            expr.walk(tw);\n            if (node.optional) {\n                push(tw, true, true);\n                prop.walk(tw);\n                pop(tw);\n            } else {\n                if (!is_direct_assignment(node, tw.parent())) dot(expr, tw);\n                prop.walk(tw);\n            }\n            return true;\n        });\n        def(AST_Switch, function(tw, descend, compressor) {\n            var node = this;\n            reset_block_variables(tw, compressor, node);\n            node.expression.walk(tw);\n            var first = true;\n            node.body.forEach(function(branch) {\n                if (branch instanceof AST_Default) return;\n                branch.expression.walk(tw);\n                if (first) {\n                    first = false;\n                    push(tw, true, true);\n                }\n            });\n            if (!first) pop(tw);\n            walk_body(node, tw);\n            return true;\n        });\n        def(AST_SwitchBranch, function(tw) {\n            push(tw, true, true);\n            walk_body(this, tw);\n            pop(tw);\n            return true;\n        });\n        def(AST_SymbolCatch, function() {\n            var d = this.definition();\n            if (!d.first_decl && d.references.length == 0) d.first_decl = this;\n            d.fixed = false;\n        });\n        def(AST_SymbolDeclaration, function() {\n            var d = this.definition();\n            if (!d.first_decl && d.references.length == 0) d.first_decl = this;\n        });\n        def(AST_SymbolDefun, function() {\n            var d = this.definition();\n            if (!d.first_decl && d.references.length == 0) d.first_decl = this;\n            if (d.orig.length > 1 && d.scope.resolve() !== this.scope) d.fixed = false;\n        });\n        def(AST_SymbolImport, function() {\n            var d = this.definition();\n            d.first_decl = this;\n            d.fixed = false;\n        });\n        def(AST_SymbolRef, function(tw, descend, compressor) {\n            var ref = this;\n            var d = ref.definition();\n            var fixed = d.fixed || d.last_ref && d.last_ref.fixed;\n            push_ref(d, ref);\n            if (safe_to_access(tw, d)) ref.defined = true;\n            if (d.references.length == 1 && !d.fixed && d.orig[0] instanceof AST_SymbolDefun) {\n                tw.loop_ids[d.id] = tw.in_loop;\n            }\n            var recursive = recursive_ref(tw, d);\n            if (recursive) recursive.enclosed.forEach(function(def) {\n                if (d === def) return;\n                if (def.scope.resolve() === recursive) return;\n                var assigns = def.fixed && def.fixed.assigns;\n                if (!assigns) return;\n                if (assigns[assigns.length - 1] instanceof AST_VarDef) return;\n                var safe = tw.safe_ids[def.id];\n                if (!safe) return;\n                safe.assign = true;\n            });\n            if (d.single_use == \"m\" && d.fixed) {\n                d.fixed = 0;\n                d.single_use = false;\n            }\n            switch (d.fixed) {\n              case 0:\n                if (!safe_to_read(tw, d)) d.fixed = false;\n              case false:\n                var redef = d.redefined();\n                if (redef && cross_scope(d.scope, ref.scope)) redef.single_use = false;\n                break;\n              case undefined:\n                d.fixed = false;\n                break;\n              default:\n                if (!safe_to_read(tw, d)) {\n                    d.fixed = false;\n                    break;\n                }\n                if (ref.in_arg && d.orig[0] instanceof AST_SymbolLambda) ref.fixed = d.scope;\n                var value = ref.fixed_value();\n                if (recursive) {\n                    d.recursive_refs++;\n                } else if (value && ref_once(compressor, d)) {\n                    d.in_loop = tw.loop_ids[d.id] !== tw.in_loop;\n                    d.single_use = is_lambda(value)\n                            && !value.pinned()\n                            && (!d.in_loop || tw.parent() instanceof AST_Call)\n                        || !d.in_loop\n                            && d.scope === ref.scope.resolve()\n                            && value.is_constant_expression();\n                } else {\n                    d.single_use = false;\n                }\n                if (is_modified(compressor, tw, ref, value, 0, is_immutable(value), recursive)) {\n                    if (d.single_use) {\n                        d.single_use = \"m\";\n                    } else {\n                        d.fixed = 0;\n                    }\n                }\n                if (d.fixed && tw.loop_ids[d.id] !== tw.in_loop) d.cross_loop = true;\n                mark_escaped(tw, d, ref.scope, ref, value, 0, 1);\n                break;\n            }\n            if (!ref.fixed) ref.fixed = d.fixed === 0 ? fixed : d.fixed;\n            if (!value && fixed) value = fixed instanceof AST_Node ? fixed : fixed();\n            if (!(value instanceof AST_Lambda)) return;\n            if (d.fixed) {\n                var parent = tw.parent();\n                if (parent instanceof AST_Call && parent.expression === ref) return;\n            }\n            mark_fn_def(tw, d, value);\n        });\n        def(AST_Template, function(tw) {\n            var node = this;\n            var tag = node.tag;\n            if (!tag) return;\n            if (tag instanceof AST_LambdaExpression) {\n                node.expressions.forEach(function(exp) {\n                    exp.walk(tw);\n                });\n                tag.walk(tw);\n                return true;\n            }\n            tag.walk(tw);\n            node.expressions.forEach(function(exp) {\n                exp.walk(tw);\n            });\n            var fixed = tag instanceof AST_SymbolRef && tag.fixed_value();\n            if (fixed instanceof AST_Lambda) {\n                mark_fn_def(tw, tag.definition(), fixed);\n            } else {\n                tw.find_parent(AST_Scope).may_call_this();\n            }\n            return true;\n        });\n        def(AST_Toplevel, function(tw, descend, compressor) {\n            var node = this;\n            node.globals.each(function(def) {\n                reset_def(tw, compressor, def);\n            });\n            push(tw, true);\n            reset_variables(tw, compressor, node);\n            descend();\n            pop_scope(tw, node);\n            return true;\n        });\n        def(AST_Try, function(tw, descend, compressor) {\n            var node = this;\n            reset_block_variables(tw, compressor, node);\n            push(tw, true);\n            walk_body(node, tw);\n            pop(tw);\n            if (node.bcatch) {\n                push(tw, true, true);\n                node.bcatch.walk(tw);\n                pop(tw);\n            }\n            if (node.bfinally) node.bfinally.walk(tw);\n            return true;\n        });\n        def(AST_Unary, function(tw) {\n            var node = this;\n            if (!UNARY_POSTFIX[node.operator]) return;\n            var exp = node.expression;\n            if (!(exp instanceof AST_SymbolRef)) {\n                mark_assignment_to_arguments(exp);\n                return;\n            }\n            var d = exp.definition();\n            d.assignments++;\n            var fixed = d.fixed;\n            if (safe_to_read(tw, d) && !exp.in_arg && safe_to_assign(tw, d)) {\n                push_ref(d, exp);\n                mark(tw, d);\n                if (d.single_use) d.single_use = false;\n                d.fixed = function() {\n                    return make_node(AST_Binary, node, {\n                        operator: node.operator.slice(0, -1),\n                        left: make_node(AST_UnaryPrefix, node, {\n                            operator: \"+\",\n                            expression: make_ref(exp, fixed),\n                        }),\n                        right: make_node(AST_Number, node, { value: 1 }),\n                    });\n                };\n                d.fixed.assigns = fixed && fixed.assigns ? fixed.assigns.slice() : [];\n                d.fixed.assigns.push(node);\n                if (node instanceof AST_UnaryPrefix) {\n                    exp.fixed = d.fixed;\n                } else {\n                    exp.fixed = function() {\n                        return make_node(AST_UnaryPrefix, node, {\n                            operator: \"+\",\n                            expression: make_ref(exp, fixed),\n                        });\n                    };\n                    exp.fixed.assigns = fixed && fixed.assigns;\n                    exp.fixed.to_prefix = replace_ref(function(node) {\n                        return node.expression;\n                    }, d.fixed);\n                }\n            } else {\n                exp.walk(tw);\n                d.fixed = false;\n            }\n            return true;\n        });\n        def(AST_VarDef, function(tw, descend, compressor) {\n            var node = this;\n            var value = node.value;\n            if (value instanceof AST_LambdaExpression && node.name instanceof AST_SymbolDeclaration) {\n                walk_defn();\n                value.parent_scope.resolve().fn_defs.push(value);\n                value.safe_ids = null;\n                var ld = node.name.definition();\n                if (!ld.fixed) mark_fn_def(tw, ld, value);\n            } else if (value) {\n                value.walk(tw);\n                walk_defn();\n            } else if (tw.parent() instanceof AST_Let) {\n                walk_defn();\n            } else {\n                node.name.walk(tw);\n            }\n            return true;\n\n            function walk_defn() {\n                scan_declaration(tw, compressor, node.name, function() {\n                    return node.value || make_node(AST_Undefined, node);\n                }, function(name, fixed) {\n                    var d = name.definition();\n                    assign(tw, d);\n                    if (!d.first_decl && d.references.length == 0) d.first_decl = name;\n                    if (fixed && safe_to_assign(tw, d, true)) {\n                        mark(tw, d);\n                        tw.loop_ids[d.id] = tw.in_loop;\n                        d.fixed = fixed;\n                        d.fixed.assigns = [ node ];\n                        if (name instanceof AST_SymbolConst && d.redefined()\n                            || !(can_drop_symbol(name) || is_safe_lexical(d))) {\n                            d.single_use = false;\n                        }\n                    } else {\n                        d.fixed = false;\n                    }\n                });\n            }\n        });\n        def(AST_While, function(tw, descend) {\n            var save_loop = tw.in_loop;\n            tw.in_loop = this;\n            push(tw);\n            descend();\n            pop(tw);\n            tw.in_loop = save_loop;\n            return true;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"reduce_vars\", func);\n    });\n\n    function reset_flags(node) {\n        node._squeezed = false;\n        node._optimized = false;\n        node.single_use = false;\n        if (node instanceof AST_BlockScope) node._var_names = undefined;\n        if (node instanceof AST_SymbolRef) node.fixed = undefined;\n    }\n\n    AST_Toplevel.DEFMETHOD(\"reset_opt_flags\", function(compressor) {\n        var tw = new TreeWalker(compressor.option(\"reduce_vars\") ? function(node, descend) {\n            reset_flags(node);\n            return node.reduce_vars(tw, descend, compressor);\n        } : reset_flags);\n        // Side-effect tracking on sequential property access\n        tw.assigned_ids = Object.create(null);\n        tw.defined_ids = Object.create(null);\n        tw.defined_ids.seq = {};\n        // Flow control for visiting lambda definitions\n        tw.fn_scanning = null;\n        tw.fn_visited = [];\n        // Record the loop body in which `AST_SymbolDeclaration` is first encountered\n        tw.in_loop = null;\n        tw.loop_ids = Object.create(null);\n        // Stack of look-up tables to keep track of whether a `SymbolDef` has been\n        // properly assigned before use:\n        // - `push()` & `pop()` when visiting conditional branches\n        // - backup & restore via `save_ids` when visiting out-of-order sections\n        tw.safe_ids = Object.create(null);\n        tw.safe_ids.seq = {};\n        this.walk(tw);\n    });\n\n    AST_Symbol.DEFMETHOD(\"fixed_value\", function(ref_only) {\n        var def = this.definition();\n        var fixed = def.fixed;\n        if (fixed) {\n            if (this.fixed) fixed = this.fixed;\n            return (fixed instanceof AST_Node ? fixed : fixed()).tail_node();\n        }\n        fixed = fixed === 0 && this.fixed;\n        if (!fixed) return fixed;\n        var value = (fixed instanceof AST_Node ? fixed : fixed()).tail_node();\n        if (ref_only && def.escaped.depth != 1 && is_object(value, true)) return value;\n        if (value.is_constant()) return value;\n    });\n\n    AST_SymbolRef.DEFMETHOD(\"is_immutable\", function() {\n        var def = this.redef || this.definition();\n        if (!(def.orig[0] instanceof AST_SymbolLambda)) return false;\n        if (def.orig.length == 1) return true;\n        if (!this.in_arg) return false;\n        return !(def.orig[1] instanceof AST_SymbolFunarg);\n    });\n\n    AST_Node.DEFMETHOD(\"convert_symbol\", noop);\n    function convert_destructured(type, process) {\n        return this.transform(new TreeTransformer(function(node, descend) {\n            if (node instanceof AST_DefaultValue) {\n                node = node.clone();\n                node.name = node.name.transform(this);\n                return node;\n            }\n            if (node instanceof AST_Destructured) {\n                node = node.clone();\n                descend(node, this);\n                return node;\n            }\n            if (node instanceof AST_DestructuredKeyVal) {\n                node = node.clone();\n                node.value = node.value.transform(this);\n                return node;\n            }\n            return node.convert_symbol(type, process);\n        }));\n    }\n    AST_DefaultValue.DEFMETHOD(\"convert_symbol\", convert_destructured);\n    AST_Destructured.DEFMETHOD(\"convert_symbol\", convert_destructured);\n    function convert_symbol(type, process) {\n        var node = make_node(type, this);\n        return process(node, this) || node;\n    }\n    AST_SymbolDeclaration.DEFMETHOD(\"convert_symbol\", convert_symbol);\n    AST_SymbolRef.DEFMETHOD(\"convert_symbol\", convert_symbol);\n\n    function process_to_assign(ref) {\n        var def = ref.definition();\n        def.assignments++;\n        def.references.push(ref);\n    }\n\n    function mark_destructured(process, tw) {\n        var marker = new TreeWalker(function(node) {\n            if (node instanceof AST_DefaultValue) {\n                node.value.walk(tw);\n                node.name.walk(marker);\n                return true;\n            }\n            if (node instanceof AST_DestructuredKeyVal) {\n                if (node.key instanceof AST_Node) node.key.walk(tw);\n                node.value.walk(marker);\n                return true;\n            }\n            return process(node);\n        });\n        this.walk(marker);\n    }\n    AST_DefaultValue.DEFMETHOD(\"mark_symbol\", mark_destructured);\n    AST_Destructured.DEFMETHOD(\"mark_symbol\", mark_destructured);\n    function mark_symbol(process) {\n        return process(this);\n    }\n    AST_SymbolDeclaration.DEFMETHOD(\"mark_symbol\", mark_symbol);\n    AST_SymbolRef.DEFMETHOD(\"mark_symbol\", mark_symbol);\n\n    AST_Node.DEFMETHOD(\"match_symbol\", function(predicate) {\n        return predicate(this);\n    });\n    function match_destructured(predicate, ignore_side_effects) {\n        var found = false;\n        var tw = new TreeWalker(function(node) {\n            if (found) return true;\n            if (node instanceof AST_DefaultValue) {\n                if (!ignore_side_effects) return found = true;\n                node.name.walk(tw);\n                return true;\n            }\n            if (node instanceof AST_DestructuredKeyVal) {\n                if (!ignore_side_effects && node.key instanceof AST_Node) return found = true;\n                node.value.walk(tw);\n                return true;\n            }\n            if (predicate(node)) return found = true;\n        });\n        this.walk(tw);\n        return found;\n    }\n    AST_DefaultValue.DEFMETHOD(\"match_symbol\", match_destructured);\n    AST_Destructured.DEFMETHOD(\"match_symbol\", match_destructured);\n\n    function in_async_generator(scope) {\n        return scope instanceof AST_AsyncGeneratorDefun || scope instanceof AST_AsyncGeneratorFunction;\n    }\n\n    function find_scope(compressor) {\n        var level = 0, node = compressor.self();\n        do {\n            if (node.variables) return node;\n        } while (node = compressor.parent(level++));\n    }\n\n    function find_try(compressor, level, node, scope, may_throw, sync) {\n        for (var parent; parent = compressor.parent(level++); node = parent) {\n            if (parent === scope) return false;\n            if (sync && parent instanceof AST_Lambda) {\n                if (parent.name || is_async(parent) || is_generator(parent)) return true;\n            } else if (parent instanceof AST_Try) {\n                if (parent.bfinally && parent.bfinally !== node) return true;\n                if (may_throw && parent.bcatch && parent.bcatch !== node) return true;\n            }\n        }\n        return false;\n    }\n\n    var identifier_atom = makePredicate(\"Infinity NaN undefined\");\n    function is_lhs_read_only(lhs, compressor) {\n        if (lhs instanceof AST_Assign) {\n            if (lhs.operator != \"=\") return true;\n            if (lhs.right.tail_node().is_constant()) return true;\n            return is_lhs_read_only(lhs.left, compressor);\n        }\n        if (lhs instanceof AST_Atom) return true;\n        if (lhs instanceof AST_ObjectIdentity) return true;\n        if (lhs instanceof AST_PropAccess) {\n            if (lhs.property === \"__proto__\") return true;\n            lhs = lhs.expression;\n            if (lhs instanceof AST_SymbolRef) {\n                if (lhs.is_immutable()) return false;\n                lhs = lhs.fixed_value();\n            }\n            if (!lhs) return true;\n            if (lhs.tail_node().is_constant()) return true;\n            return is_lhs_read_only(lhs, compressor);\n        }\n        if (lhs instanceof AST_SymbolRef) {\n            if (lhs.is_immutable()) return true;\n            var def = lhs.definition();\n            return compressor.exposed(def) && identifier_atom[def.name];\n        }\n        return false;\n    }\n\n    function make_node(ctor, orig, props) {\n        if (props) {\n            props.start = orig.start;\n            props.end = orig.end;\n        } else {\n            props = orig;\n        }\n        return new ctor(props);\n    }\n\n    function make_sequence(orig, expressions) {\n        if (expressions.length == 1) return expressions[0];\n        return make_node(AST_Sequence, orig, { expressions: expressions.reduce(merge_sequence, []) });\n    }\n\n    function make_node_from_constant(val, orig) {\n        switch (typeof val) {\n          case \"string\":\n            return make_node(AST_String, orig, { value: val });\n          case \"number\":\n            if (isNaN(val)) return make_node(AST_NaN, orig);\n            if (isFinite(val)) {\n                return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, {\n                    operator: \"-\",\n                    expression: make_node(AST_Number, orig, { value: -val }),\n                }) : make_node(AST_Number, orig, { value: val });\n            }\n            return val < 0 ? make_node(AST_UnaryPrefix, orig, {\n                operator: \"-\",\n                expression: make_node(AST_Infinity, orig),\n            }) : make_node(AST_Infinity, orig);\n          case \"boolean\":\n            return make_node(val ? AST_True : AST_False, orig);\n          case \"undefined\":\n            return make_node(AST_Undefined, orig);\n          default:\n            if (val === null) {\n                return make_node(AST_Null, orig);\n            }\n            if (val instanceof RegExp) {\n                return make_node(AST_RegExp, orig, { value: val });\n            }\n            throw new Error(string_template(\"Can't handle constant of type: {type}\", { type: typeof val }));\n        }\n    }\n\n    function needs_unbinding(val) {\n        return val instanceof AST_PropAccess\n            || is_undeclared_ref(val) && val.name == \"eval\";\n    }\n\n    // we shouldn't compress (1,func)(something) to\n    // func(something) because that changes the meaning of\n    // the func (becomes lexical instead of global).\n    function maintain_this_binding(parent, orig, val) {\n        var wrap = false;\n        if (parent.TYPE == \"Call\") {\n            wrap = parent.expression === orig && needs_unbinding(val);\n        } else if (parent instanceof AST_Template) {\n            wrap = parent.tag === orig && needs_unbinding(val);\n        } else if (parent instanceof AST_UnaryPrefix) {\n            wrap = parent.operator == \"delete\"\n                || parent.operator == \"typeof\" && is_undeclared_ref(val);\n        }\n        return wrap ? make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]) : val;\n    }\n\n    function merge_expression(base, target) {\n        var fixed_by_id = new Dictionary();\n        base.walk(new TreeWalker(function(node) {\n            if (!(node instanceof AST_SymbolRef)) return;\n            var def = node.definition();\n            var fixed = node.fixed;\n            if (!fixed || !fixed_by_id.has(def.id)) {\n                fixed_by_id.set(def.id, fixed);\n            } else if (fixed_by_id.get(def.id) !== fixed) {\n                fixed_by_id.set(def.id, false);\n            }\n        }));\n        if (fixed_by_id.size() > 0) target.walk(new TreeWalker(function(node) {\n            if (!(node instanceof AST_SymbolRef)) return;\n            var def = node.definition();\n            var fixed = node.fixed;\n            if (!fixed || !fixed_by_id.has(def.id)) return;\n            if (fixed_by_id.get(def.id) !== fixed) node.fixed = false;\n        }));\n        return target;\n    }\n\n    function merge_sequence(array, node) {\n        if (node instanceof AST_Sequence) {\n            [].push.apply(array, node.expressions);\n        } else {\n            array.push(node);\n        }\n        return array;\n    }\n\n    function is_direct_assignment(node, parent) {\n        if (parent instanceof AST_Assign) return parent.operator == \"=\" && parent.left === node;\n        if (parent instanceof AST_DefaultValue) return parent.name === node;\n        if (parent instanceof AST_DestructuredArray) return true;\n        if (parent instanceof AST_DestructuredKeyVal) return parent.value === node;\n    }\n\n    function is_lexical_definition(stat) {\n        return stat instanceof AST_Const || stat instanceof AST_DefClass || stat instanceof AST_Let;\n    }\n\n    function safe_to_trim(stat) {\n        if (stat instanceof AST_LambdaDefinition) {\n            var def = stat.name.definition();\n            var scope = stat.name.scope;\n            if (def.orig.length > 1 && def.scope.resolve() !== scope) return false;\n            return def.scope === scope || all(def.references, function(ref) {\n                var s = ref.scope;\n                do {\n                    if (s === scope) return true;\n                } while (s = s.parent_scope);\n            });\n        }\n        return !is_lexical_definition(stat);\n    }\n\n    function as_statement_array(thing) {\n        if (thing === null) return [];\n        if (thing instanceof AST_BlockStatement) return all(thing.body, safe_to_trim) ? thing.body : [ thing ];\n        if (thing instanceof AST_EmptyStatement) return [];\n        if (is_statement(thing)) return [ thing ];\n        throw new Error(\"Can't convert thing to statement array\");\n    }\n\n    function is_empty(thing) {\n        if (thing === null) return true;\n        if (thing instanceof AST_EmptyStatement) return true;\n        if (thing instanceof AST_BlockStatement) return thing.body.length == 0;\n        return false;\n    }\n\n    function has_declarations_only(block) {\n        return all(block.body, function(stat) {\n            return is_empty(stat)\n                || stat instanceof AST_Defun\n                || stat instanceof AST_Var && declarations_only(stat);\n        });\n    }\n\n    function loop_body(x) {\n        if (x instanceof AST_IterationStatement) {\n            return x.body instanceof AST_BlockStatement ? x.body : x;\n        }\n        return x;\n    }\n\n    function is_iife_call(node) {\n        if (node.TYPE != \"Call\") return false;\n        do {\n            node = node.expression;\n        } while (node instanceof AST_PropAccess);\n        return node instanceof AST_LambdaExpression ? !is_arrow(node) : is_iife_call(node);\n    }\n\n    function is_iife_single(call) {\n        var exp = call.expression;\n        if (exp.name) return false;\n        if (!(call instanceof AST_New)) return true;\n        var found = false;\n        exp.walk(new TreeWalker(function(node) {\n            if (found) return true;\n            if (node instanceof AST_NewTarget) return found = true;\n            if (node instanceof AST_Scope && node !== exp) return true;\n        }));\n        return !found;\n    }\n\n    function is_undeclared_ref(node) {\n        return node instanceof AST_SymbolRef && node.definition().undeclared;\n    }\n\n    var global_names = makePredicate(\"Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Map Math Number parseFloat parseInt RangeError ReferenceError RegExp Object Set setInterval setTimeout String SyntaxError TypeError unescape URIError WeakMap WeakSet\");\n    AST_SymbolRef.DEFMETHOD(\"is_declared\", function(compressor) {\n        return this.defined\n            || !this.definition().undeclared\n            || compressor.option(\"unsafe\") && global_names[this.name];\n    });\n\n    function is_static_field_or_init(prop) {\n        return prop.static && prop.value && (prop instanceof AST_ClassField || prop instanceof AST_ClassInit);\n    }\n\n    function declarations_only(node) {\n        return all(node.definitions, function(var_def) {\n            return !var_def.value;\n        });\n    }\n\n    function is_declaration(stat, lexical) {\n        if (stat instanceof AST_DefClass) return lexical && !stat.extends && all(stat.properties, function(prop) {\n            if (prop.key instanceof AST_Node) return false;\n            return !is_static_field_or_init(prop);\n        });\n        if (stat instanceof AST_Definitions) return (lexical || stat instanceof AST_Var) && declarations_only(stat);\n        if (stat instanceof AST_ExportDeclaration) return is_declaration(stat.body, lexical);\n        if (stat instanceof AST_ExportDefault) return is_declaration(stat.body, lexical);\n        return stat instanceof AST_LambdaDefinition;\n    }\n\n    function is_last_statement(body, stat) {\n        var index = body.lastIndexOf(stat);\n        if (index < 0) return false;\n        while (++index < body.length) {\n            if (!is_declaration(body[index], true)) return false;\n        }\n        return true;\n    }\n\n    // Certain combination of unused name + side effect leads to invalid AST:\n    //    https://github.com/mishoo/UglifyJS/issues/44\n    //    https://github.com/mishoo/UglifyJS/issues/1838\n    //    https://github.com/mishoo/UglifyJS/issues/3371\n    // We fix it at this stage by moving the `var` outside the `for`.\n    function patch_for_init(node, in_list) {\n        var block;\n        if (node.init instanceof AST_BlockStatement) {\n            block = node.init;\n            node.init = block.body.pop();\n            block.body.push(node);\n        }\n        if (node.init instanceof AST_Defun) {\n            if (!block) block = make_node(AST_BlockStatement, node, { body: [ node ] });\n            block.body.splice(-1, 0, node.init);\n            node.init = null;\n        } else if (node.init instanceof AST_SimpleStatement) {\n            node.init = node.init.body;\n        } else if (is_empty(node.init)) {\n            node.init = null;\n        }\n        if (!block) return;\n        return in_list ? List.splice(block.body) : block;\n    }\n\n    function tighten_body(statements, compressor) {\n        var in_lambda = last_of(compressor, function(node) {\n            return node instanceof AST_Lambda;\n        });\n        var block_scope, iife_in_try, in_iife_single, in_loop, in_try, scope;\n        find_loop_scope_try();\n        var changed, last_changed, max_iter = 10;\n        do {\n            last_changed = changed;\n            changed = 0;\n            if (eliminate_spurious_blocks(statements)) changed = 1;\n            if (!changed && last_changed == 1) break;\n            if (compressor.option(\"dead_code\")) {\n                if (eliminate_dead_code(statements, compressor)) changed = 2;\n                if (!changed && last_changed == 2) break;\n            }\n            if (compressor.option(\"if_return\")) {\n                if (handle_if_return(statements, compressor)) changed = 3;\n                if (!changed && last_changed == 3) break;\n            }\n            if (compressor.option(\"awaits\") && compressor.option(\"side_effects\")) {\n                if (trim_awaits(statements, compressor)) changed = 4;\n                if (!changed && last_changed == 4) break;\n            }\n            if (compressor.option(\"inline\") >= 4) {\n                if (inline_iife(statements, compressor)) changed = 5;\n                if (!changed && last_changed == 5) break;\n            }\n            if (compressor.sequences_limit > 0) {\n                if (sequencesize(statements, compressor)) changed = 6;\n                if (!changed && last_changed == 6) break;\n                if (sequencesize_2(statements, compressor)) changed = 7;\n                if (!changed && last_changed == 7) break;\n            }\n            if (compressor.option(\"join_vars\")) {\n                if (join_consecutive_vars(statements)) changed = 8;\n                if (!changed && last_changed == 8) break;\n            }\n            if (compressor.option(\"collapse_vars\")) {\n                if (collapse(statements, compressor)) changed = 9;\n            }\n        } while (changed && max_iter-- > 0);\n        return statements;\n\n        function last_of(compressor, predicate) {\n            var block = compressor.self(), level = 0, stat;\n            do {\n                if (block instanceof AST_Catch) {\n                    block = compressor.parent(level++);\n                } else if (block instanceof AST_LabeledStatement) {\n                    block = block.body;\n                } else if (block instanceof AST_SwitchBranch) {\n                    var branches = compressor.parent(level);\n                    if (branches.body[branches.body.length - 1] === block || has_break(block.body)) {\n                        level++;\n                        block = branches;\n                    }\n                }\n                do {\n                    stat = block;\n                    if (predicate(stat)) return stat;\n                    block = compressor.parent(level++);\n                } while (block instanceof AST_If);\n            } while (stat\n                && (block instanceof AST_BlockStatement\n                    || block instanceof AST_Catch\n                    || block instanceof AST_Scope\n                    || block instanceof AST_SwitchBranch\n                    || block instanceof AST_Try)\n                && is_last_statement(block.body, stat));\n\n            function has_break(stats) {\n                for (var i = stats.length; --i >= 0;) {\n                    if (stats[i] instanceof AST_Break) return true;\n                }\n                return false;\n            }\n        }\n\n        function find_loop_scope_try() {\n            var node = compressor.self(), level = 0;\n            do {\n                if (!block_scope && node.variables) block_scope = node;\n                if (node instanceof AST_Catch) {\n                    if (compressor.parent(level).bfinally) {\n                        if (!in_try) in_try = {};\n                        in_try.bfinally = true;\n                    }\n                    level++;\n                } else if (node instanceof AST_Finally) {\n                    level++;\n                } else if (node instanceof AST_IterationStatement) {\n                    in_loop = true;\n                } else if (node instanceof AST_Scope) {\n                    scope = node;\n                    break;\n                } else if (node instanceof AST_Try) {\n                    if (!in_try) in_try = {};\n                    if (node.bcatch) in_try.bcatch = true;\n                    if (node.bfinally) in_try.bfinally = true;\n                }\n            } while (node = compressor.parent(level++));\n        }\n\n        // Search from right to left for assignment-like expressions:\n        // - `var a = x;`\n        // - `a = x;`\n        // - `++a`\n        // For each candidate, scan from left to right for first usage, then try\n        // to fold assignment into the site for compression.\n        // Will not attempt to collapse assignments into or past code blocks\n        // which are not sequentially executed, e.g. loops and conditionals.\n        function collapse(statements, compressor) {\n            if (scope.pinned()) return;\n            var args;\n            var assignments = new Dictionary();\n            var candidates = [];\n            var changed = false;\n            var declare_only = new Dictionary();\n            var force_single;\n            var stat_index = statements.length;\n            var scanner = new TreeTransformer(function(node, descend) {\n                if (abort) return node;\n                // Skip nodes before `candidate` as quickly as possible\n                if (!hit) {\n                    if (node !== hit_stack[hit_index]) return node;\n                    hit_index++;\n                    if (hit_index < hit_stack.length) return handle_custom_scan_order(node, scanner);\n                    hit = true;\n                    stop_after = (value_def ? find_stop_value : find_stop)(node, 0);\n                    if (stop_after === node) abort = true;\n                    return node;\n                }\n                var parent = scanner.parent();\n                // Stop only if candidate is found within conditional branches\n                if (!stop_if_hit && in_conditional(node, parent)) {\n                    stop_if_hit = parent;\n                }\n                // Cascade compound assignments\n                if (compound && scan_lhs && can_replace && !stop_if_hit\n                    && node instanceof AST_Assign && node.operator != \"=\" && node.left.equals(lhs)) {\n                    replaced++;\n                    changed = true;\n                    AST_Node.info(\"Cascading {this} [{start}]\", node);\n                    can_replace = false;\n                    lvalues = get_lvalues(lhs);\n                    node.right.transform(scanner);\n                    clear_write_only(candidate);\n                    var folded;\n                    if (abort) {\n                        folded = candidate;\n                    } else {\n                        abort = true;\n                        folded = make_node(AST_Binary, candidate, {\n                            operator: compound,\n                            left: lhs.fixed && lhs.definition().fixed ? lhs.fixed.to_binary(candidate) : lhs,\n                            right: rvalue,\n                        });\n                    }\n                    return make_node(AST_Assign, node, {\n                        operator: \"=\",\n                        left: node.left,\n                        right: make_node(AST_Binary, node, {\n                            operator: node.operator.slice(0, -1),\n                            left: folded,\n                            right: node.right,\n                        }),\n                    });\n                }\n                // Stop immediately if these node types are encountered\n                if (should_stop(node, parent)) {\n                    abort = true;\n                    return node;\n                }\n                // Skip transient nodes caused by single-use variable replacement\n                if (node.single_use) return node;\n                // Replace variable with assignment when found\n                var hit_rhs;\n                if (!(node instanceof AST_SymbolDeclaration)\n                    && (scan_lhs && lhs.equals(node)\n                        || scan_rhs && (hit_rhs = scan_rhs(node, this)))) {\n                    if (!can_replace || stop_if_hit && (hit_rhs || !lhs_local || !replace_all)) {\n                        if (!hit_rhs && !value_def) abort = true;\n                        return node;\n                    }\n                    if (is_lhs(node, parent)) {\n                        if (value_def && !hit_rhs) assign_used = true;\n                        return node;\n                    }\n                    if (!hit_rhs && verify_ref && node.fixed !== lhs.fixed) {\n                        abort = true;\n                        return node;\n                    }\n                    if (value_def) {\n                        if (stop_if_hit && assign_pos == 0) assign_pos = remaining - replaced;\n                        if (!hit_rhs) replaced++;\n                        return node;\n                    }\n                    replaced++;\n                    changed = abort = true;\n                    AST_Node.info(\"Collapsing {this} [{start}]\", node);\n                    if (candidate.TYPE == \"Binary\") {\n                        update_symbols(candidate, node);\n                        return make_node(AST_Assign, candidate, {\n                            operator: \"=\",\n                            left: candidate.right.left,\n                            right: candidate.operator == \"&&\" ? make_node(AST_Conditional, candidate, {\n                                condition: candidate.left,\n                                consequent: candidate.right.right,\n                                alternative: node,\n                            }) : make_node(AST_Conditional, candidate, {\n                                condition: candidate.left,\n                                consequent: node,\n                                alternative: candidate.right.right,\n                            }),\n                        });\n                    }\n                    if (candidate instanceof AST_UnaryPostfix) return make_node(AST_UnaryPrefix, candidate, {\n                        operator: candidate.operator,\n                        expression: lhs.fixed && lhs.definition().fixed ? lhs.fixed.to_prefix(candidate) : lhs,\n                    });\n                    if (candidate instanceof AST_UnaryPrefix) {\n                        clear_write_only(candidate);\n                        return candidate;\n                    }\n                    update_symbols(rvalue, node);\n                    if (candidate instanceof AST_VarDef) {\n                        var def = candidate.name.definition();\n                        if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) {\n                            def.replaced++;\n                            return maintain_this_binding(parent, node, rvalue);\n                        }\n                        return make_node(AST_Assign, candidate, {\n                            operator: \"=\",\n                            left: node,\n                            right: rvalue,\n                        });\n                    }\n                    clear_write_only(rvalue);\n                    var assign = candidate.clone();\n                    assign.right = rvalue;\n                    return assign;\n                }\n                // Stop signals related to AST_SymbolRef\n                if (should_stop_ref(node, parent)) {\n                    abort = true;\n                    return node;\n                }\n                // These node types have child nodes that execute sequentially,\n                // but are otherwise not safe to scan into or beyond them.\n                if (is_last_node(node, parent) || may_throw(node)) {\n                    stop_after = node;\n                    if (node instanceof AST_Scope) abort = true;\n                }\n                // Scan but don't replace inside getter/setter\n                if (node instanceof AST_Accessor) {\n                    var replace = can_replace;\n                    can_replace = false;\n                    descend(node, scanner);\n                    can_replace = replace;\n                    return signal_abort(node);\n                }\n                // Scan but don't replace inside destructuring expression\n                if (node instanceof AST_Destructured) {\n                    var replace = can_replace;\n                    can_replace = false;\n                    descend(node, scanner);\n                    can_replace = replace;\n                    return signal_abort(node);\n                }\n                // Scan but don't replace inside default value\n                if (node instanceof AST_DefaultValue) {\n                    node.name = node.name.transform(scanner);\n                    var replace = can_replace;\n                    can_replace = false;\n                    node.value = node.value.transform(scanner);\n                    can_replace = replace;\n                    return signal_abort(node);\n                }\n                // Scan but don't replace inside block scope with colliding variable\n                if (node instanceof AST_BlockScope\n                    && !(node instanceof AST_Scope)\n                    && !(node.variables && node.variables.all(function(def) {\n                        return !enclosed.has(def.name) && !lvalues.has(def.name);\n                    }))) {\n                    var replace = can_replace;\n                    can_replace = false;\n                    if (!handle_custom_scan_order(node, scanner)) descend(node, scanner);\n                    can_replace = replace;\n                    return signal_abort(node);\n                }\n                if (handle_custom_scan_order(node, scanner)) return signal_abort(node);\n            }, signal_abort);\n            var multi_replacer = new TreeTransformer(function(node) {\n                if (abort) return node;\n                // Skip nodes before `candidate` as quickly as possible\n                if (!hit) {\n                    if (node !== hit_stack[hit_index]) return node;\n                    hit_index++;\n                    switch (hit_stack.length - hit_index) {\n                      case 0:\n                        hit = true;\n                        if (assign_used) return node;\n                        if (node !== candidate) return node;\n                        if (node instanceof AST_VarDef) return node;\n                        def.replaced++;\n                        var parent = multi_replacer.parent();\n                        if (parent instanceof AST_Sequence && parent.tail_node() !== node) {\n                            value_def.replaced++;\n                            if (rvalue === rhs_value) return List.skip;\n                            return make_sequence(rhs_value, rhs_value.expressions.slice(0, -1));\n                        }\n                        return rvalue;\n                      case 1:\n                        if (!assign_used && node.body === candidate) {\n                            hit = true;\n                            def.replaced++;\n                            value_def.replaced++;\n                            return null;\n                        }\n                      default:\n                        return handle_custom_scan_order(node, multi_replacer);\n                    }\n                }\n                // Replace variable when found\n                if (node instanceof AST_SymbolRef && node.definition() === def) {\n                    if (is_lhs(node, multi_replacer.parent())) return node;\n                    if (!--replaced) abort = true;\n                    AST_Node.info(\"Replacing {this} [{start}]\", node);\n                    var ref = rvalue.clone();\n                    ref.scope = node.scope;\n                    ref.reference();\n                    if (replaced == assign_pos) {\n                        abort = true;\n                        return make_node(AST_Assign, candidate, {\n                            operator: \"=\",\n                            left: node,\n                            right: ref,\n                        });\n                    }\n                    def.replaced++;\n                    return ref;\n                }\n                // Skip (non-executed) functions and (leading) default case in switch statements\n                if (node instanceof AST_Default || node instanceof AST_Scope) return node;\n            }, function(node) {\n                return patch_sequence(node, multi_replacer);\n            });\n            while (--stat_index >= 0) {\n                // Treat parameters as collapsible in IIFE, i.e.\n                //   function(a, b){ ... }(x());\n                // would be translated into equivalent assignments:\n                //   var a = x(), b = undefined;\n                if (stat_index == 0 && compressor.option(\"unused\")) extract_args();\n                // Find collapsible assignments\n                var hit_stack = [];\n                extract_candidates(statements[stat_index]);\n                while (candidates.length > 0) {\n                    hit_stack = candidates.pop();\n                    var hit_index = 0;\n                    var candidate = hit_stack[hit_stack.length - 1];\n                    var assign_pos = -1;\n                    var assign_used = false;\n                    var verify_ref = false;\n                    var remaining;\n                    var value_def = null;\n                    var stop_after = null;\n                    var stop_if_hit = null;\n                    var lhs = get_lhs(candidate);\n                    var side_effects = lhs && lhs.has_side_effects(compressor);\n                    var scan_lhs = lhs && (!side_effects || lhs instanceof AST_SymbolRef)\n                            && !is_lhs_read_only(lhs, compressor);\n                    var scan_rhs = foldable(candidate);\n                    if (!scan_lhs && !scan_rhs) continue;\n                    var compound = candidate instanceof AST_Assign && candidate.operator.slice(0, -1);\n                    var funarg = candidate.name instanceof AST_SymbolFunarg;\n                    var may_throw = return_false;\n                    if (candidate.may_throw(compressor)) {\n                        if (funarg && is_async(scope)) continue;\n                        may_throw = in_try ? function(node) {\n                            return node.has_side_effects(compressor);\n                        } : side_effects_external;\n                    }\n                    var read_toplevel = false;\n                    var modify_toplevel = false;\n                    var defun_scopes = get_defun_scopes(lhs);\n                    // Locate symbols which may execute code outside of scanning range\n                    var enclosed = new Dictionary();\n                    var well_defined = true;\n                    var lvalues = get_lvalues(candidate);\n                    var lhs_local = is_lhs_local(lhs);\n                    var rhs_value = get_rvalue(candidate);\n                    var rvalue = rhs_value;\n                    if (!side_effects) {\n                        if (!compound && rvalue instanceof AST_Sequence) rvalue = rvalue.tail_node();\n                        side_effects = value_has_side_effects();\n                    }\n                    var check_destructured = in_try || !lhs_local ? function(node) {\n                        return node instanceof AST_Destructured;\n                    } : return_false;\n                    var replace_all = replace_all_symbols(candidate);\n                    var hit = funarg;\n                    var abort = false;\n                    var replaced = 0;\n                    var can_replace = !args || !hit;\n                    if (!can_replace) {\n                        for (var j = candidate.arg_index + 1; !abort && j < args.length; j++) {\n                            if (args[j]) args[j].transform(scanner);\n                        }\n                        can_replace = true;\n                    }\n                    for (var i = stat_index; !abort && i < statements.length; i++) {\n                        statements[i].transform(scanner);\n                    }\n                    if (value_def) {\n                        if (!replaced || remaining > replaced + assign_used) {\n                            candidates.push(hit_stack);\n                            force_single = true;\n                            continue;\n                        }\n                        if (replaced == assign_pos) assign_used = true;\n                        var def = lhs.definition();\n                        abort = false;\n                        hit_index = 0;\n                        hit = funarg;\n                        for (var i = stat_index; !abort && i < statements.length; i++) {\n                            if (!statements[i].transform(multi_replacer)) statements.splice(i--, 1);\n                        }\n                        replaced = candidate instanceof AST_VarDef\n                            && candidate === hit_stack[hit_stack.length - 1]\n                            && def.references.length == def.replaced\n                            && !compressor.exposed(def);\n                        value_def.last_ref = false;\n                        value_def.single_use = false;\n                        changed = true;\n                    }\n                    if (replaced) remove_candidate(candidate);\n                }\n            }\n            return changed;\n\n            function signal_abort(node) {\n                if (abort) return node;\n                if (stop_after === node) abort = true;\n                if (stop_if_hit === node) stop_if_hit = null;\n                return node;\n            }\n\n            function handle_custom_scan_order(node, tt) {\n                if (!(node instanceof AST_BlockScope)) return;\n                // Skip (non-executed) functions\n                if (node instanceof AST_Scope) return node;\n                // Scan computed keys, static fields & initializers in class\n                if (node instanceof AST_Class) {\n                    var replace = can_replace;\n                    can_replace = false;\n                    if (node.name) node.name.transform(tt);\n                    if (!abort && node.extends) node.extends.transform(tt);\n                    var fields = [], stats = [];\n                    for (var i = 0; !abort && i < node.properties.length; i++) {\n                        var prop = node.properties[i];\n                        if (prop.key instanceof AST_Node) prop.key = prop.key.transform(tt);\n                        if (!prop.static) continue;\n                        if (prop instanceof AST_ClassField) {\n                            if (prop.value) fields.push(prop);\n                        } else if (prop instanceof AST_ClassInit) {\n                            [].push.apply(stats, prop.value.body);\n                        }\n                    }\n                    for (var i = 0; !abort && i < stats.length; i++) {\n                        stats[i].transform(tt);\n                    }\n                    for (var i = 0; !abort && i < fields.length; i++) {\n                        fields[i].value.transform(tt);\n                    }\n                    can_replace = replace;\n                    return node;\n                }\n                // Scan object only in a for-in/of statement\n                if (node instanceof AST_ForEnumeration) {\n                    node.object = node.object.transform(tt);\n                    abort = true;\n                    return node;\n                }\n                // Scan first case expression only in a switch statement\n                if (node instanceof AST_Switch) {\n                    node.expression = node.expression.transform(tt);\n                    for (var i = 0; !abort && i < node.body.length; i++) {\n                        var branch = node.body[i];\n                        if (branch instanceof AST_Case) {\n                            if (!hit) {\n                                if (branch !== hit_stack[hit_index]) continue;\n                                hit_index++;\n                            }\n                            branch.expression = branch.expression.transform(tt);\n                            if (!replace_all || verify_ref) break;\n                            scan_rhs = false;\n                        }\n                    }\n                    abort = true;\n                    return node;\n                }\n            }\n\n            function should_stop(node, parent) {\n                if (node === rvalue) return true;\n                if (parent instanceof AST_For) {\n                    if (node !== parent.init) return true;\n                }\n                if (node instanceof AST_Assign) return node.operator != \"=\" && lhs.equals(node.left);\n                if (node instanceof AST_BlockStatement) {\n                    return defun_scopes && !all(defun_scopes, function(scope) {\n                        return node !== scope;\n                    });\n                }\n                if (node instanceof AST_Call) {\n                    if (!(lhs instanceof AST_PropAccess)) return false;\n                    if (!lhs.equals(node.expression)) return false;\n                    return !(rvalue instanceof AST_LambdaExpression && !rvalue.contains_this());\n                }\n                if (node instanceof AST_Class) return !compressor.has_directive(\"use strict\");\n                if (node instanceof AST_Debugger) return true;\n                if (node instanceof AST_Defun) return funarg && lhs.name === node.name.name;\n                if (node instanceof AST_DestructuredKeyVal) return node.key instanceof AST_Node;\n                if (node instanceof AST_DWLoop) return true;\n                if (node instanceof AST_LoopControl) return true;\n                if (node instanceof AST_Try) return true;\n                if (node instanceof AST_With) return true;\n                return false;\n            }\n\n            function should_stop_ref(node, parent) {\n                if (!(node instanceof AST_SymbolRef)) return false;\n                if (node.is_declared(compressor)) {\n                    if (node.fixed_value()) return false;\n                    if (can_drop_symbol(node)) {\n                        return !(parent instanceof AST_PropAccess && parent.expression === node)\n                            && is_arguments(node.definition());\n                    }\n                } else if (is_direct_assignment(node, parent)) {\n                    return false;\n                }\n                if (!replace_all) return true;\n                scan_rhs = false;\n                return false;\n            }\n\n            function in_conditional(node, parent) {\n                if (parent instanceof AST_Assign) return parent.left !== node && lazy_op[parent.operator.slice(0, -1)];\n                if (parent instanceof AST_Binary) return parent.left !== node && lazy_op[parent.operator];\n                if (parent instanceof AST_Call) return parent.optional && parent.expression !== node;\n                if (parent instanceof AST_Case) return parent.expression !== node;\n                if (parent instanceof AST_Conditional) return parent.condition !== node;\n                if (parent instanceof AST_If) return parent.condition !== node;\n                if (parent instanceof AST_Sub) return parent.optional && parent.expression !== node;\n            }\n\n            function is_last_node(node, parent) {\n                if (node instanceof AST_Await) return true;\n                if (node.TYPE == \"Binary\") return !can_drop_op(node, compressor);\n                if (node instanceof AST_Call) {\n                    var def, fn = node.expression;\n                    if (fn instanceof AST_SymbolRef) {\n                        def = fn.definition();\n                        fn = fn.fixed_value();\n                    }\n                    if (!(fn instanceof AST_Lambda)) return !node.is_expr_pure(compressor);\n                    if (def && recursive_ref(compressor, def, fn)) return true;\n                    if (fn.collapse_scanning) return false;\n                    fn.collapse_scanning = true;\n                    var replace = can_replace;\n                    can_replace = false;\n                    var after = stop_after;\n                    var if_hit = stop_if_hit;\n                    for (var i = 0; !abort && i < fn.argnames.length; i++) {\n                        if (arg_may_throw(reject, fn.argnames[i], node.args[i])) abort = true;\n                    }\n                    if (!abort) {\n                        if (fn.rest && arg_may_throw(reject, fn.rest, make_node(AST_Array, node, {\n                            elements: node.args.slice(i),\n                        }))) {\n                            abort = true;\n                        } else if (is_arrow(fn) && fn.value) {\n                            fn.value.transform(scanner);\n                        } else for (var i = 0; !abort && i < fn.body.length; i++) {\n                            var stat = fn.body[i];\n                            if (stat instanceof AST_Return) {\n                                if (stat.value) stat.value.transform(scanner);\n                                break;\n                            }\n                            stat.transform(scanner);\n                        }\n                    }\n                    stop_if_hit = if_hit;\n                    stop_after = after;\n                    can_replace = replace;\n                    fn.collapse_scanning = false;\n                    if (!abort) return false;\n                    abort = false;\n                    return true;\n                }\n                if (node instanceof AST_Class) {\n                    if (!in_try) return false;\n                    var base = node.extends;\n                    if (!base) return false;\n                    if (base instanceof AST_SymbolRef) base = base.fixed_value();\n                    return !safe_for_extends(base);\n                }\n                if (node instanceof AST_Exit) {\n                    if (in_try) {\n                        if (in_try.bfinally) return true;\n                        if (in_try.bcatch && node instanceof AST_Throw) return true;\n                    }\n                    return side_effects || lhs instanceof AST_PropAccess || may_modify(lhs);\n                }\n                if (node instanceof AST_Function) {\n                    return compressor.option(\"ie\") && node.name && lvalues.has(node.name.name);\n                }\n                if (node instanceof AST_ObjectIdentity) return symbol_in_lvalues(node);\n                if (node instanceof AST_PropAccess) {\n                    var exp = node.expression;\n                    if (compressor.option(\"unsafe\")) {\n                        if (is_undeclared_ref(exp) && global_names[exp.name]) return false;\n                        if (is_static_fn(exp)) return false;\n                    }\n                    if (exp instanceof AST_SymbolRef && is_arguments(exp.definition())) return true;\n                    if (side_effects) return true;\n                    if (!well_defined) return true;\n                    if (value_def) return false;\n                    if (!in_try && lhs_local) return false;\n                    if (node.optional) return false;\n                    return exp.may_throw_on_access(compressor);\n                }\n                if (node instanceof AST_Spread) return true;\n                if (node instanceof AST_SymbolRef) {\n                    var assign_direct = symbol_in_lvalues(node);\n                    if (is_undeclared_ref(node) && node.is_declared(compressor)) return false;\n                    if (assign_direct) return !is_direct_assignment(node, parent);\n                    if (side_effects && may_modify(node)) return true;\n                    var def = node.definition();\n                    return (in_try || def.scope.resolve() !== scope) && !can_drop_symbol(node);\n                }\n                if (node instanceof AST_Template) return !node.is_expr_pure(compressor);\n                if (node instanceof AST_VarDef) {\n                    if (check_destructured(node.name)) return true;\n                    return (node.value || parent instanceof AST_Let) && node.name.match_symbol(function(node) {\n                        return node instanceof AST_SymbolDeclaration\n                            && (lvalues.has(node.name) || side_effects && may_modify(node));\n                    }, true);\n                }\n                if (node instanceof AST_Yield) return true;\n                var sym = is_lhs(node.left, node);\n                if (!sym) return false;\n                if (sym instanceof AST_PropAccess) return true;\n                if (check_destructured(sym)) return true;\n                return sym.match_symbol(function(node) {\n                    if (node instanceof AST_PropAccess) return true;\n                    if (node instanceof AST_SymbolRef) {\n                        return lvalues.has(node.name) || read_toplevel && compressor.exposed(node.definition());\n                    }\n                }, true);\n\n                function reject(node) {\n                    node.transform(scanner);\n                    return abort;\n                }\n            }\n\n            function arg_may_throw(reject, node, value) {\n                if (node instanceof AST_DefaultValue) {\n                    return reject(node.value)\n                        || arg_may_throw(reject, node.name, node.value)\n                        || !is_undefined(value) && arg_may_throw(reject, node.name, value);\n                }\n                if (!value) return !(node instanceof AST_Symbol);\n                if (node instanceof AST_Destructured) {\n                    if (node.rest && arg_may_throw(reject, node.rest)) return true;\n                    if (node instanceof AST_DestructuredArray) {\n                        if (value instanceof AST_Array) return !all(node.elements, function(element, index) {\n                            return !arg_may_throw(reject, element, value[index]);\n                        });\n                        if (!value.is_string(compressor)) return true;\n                        return !all(node.elements, function(element) {\n                            return !arg_may_throw(reject, element);\n                        });\n                    }\n                    if (node instanceof AST_DestructuredObject) {\n                        if (value.may_throw_on_access(compressor)) return true;\n                        return !all(node.properties, function(prop) {\n                            if (prop.key instanceof AST_Node && reject(prop.key)) return false;\n                            return !arg_may_throw(reject, prop.value);\n                        });\n                    }\n                }\n            }\n\n            function extract_args() {\n                if (in_iife_single === false) return;\n                var iife = compressor.parent(), fn = compressor.self();\n                if (in_iife_single === undefined) {\n                    if (!(fn instanceof AST_LambdaExpression)\n                        || is_generator(fn)\n                        || fn.uses_arguments\n                        || fn.pinned()\n                        || !(iife instanceof AST_Call)\n                        || iife.expression !== fn\n                        || !all(iife.args, function(arg) {\n                            return !(arg instanceof AST_Spread);\n                        })) {\n                        in_iife_single = false;\n                        return;\n                    }\n                    if (!is_iife_single(iife)) return;\n                    in_iife_single = true;\n                }\n                var fn_strict = fn.in_strict_mode(compressor)\n                    && !fn.parent_scope.resolve(true).in_strict_mode(compressor);\n                var has_await;\n                if (is_async(fn)) {\n                    has_await = function(node) {\n                        return node instanceof AST_Symbol && node.name == \"await\";\n                    };\n                    iife_in_try = true;\n                } else {\n                    has_await = function(node) {\n                        return node instanceof AST_Await && !tw.find_parent(AST_Scope);\n                    };\n                    if (iife_in_try === undefined) iife_in_try = find_try(compressor, 1, iife, null, true, true);\n                }\n                var arg_scope = null;\n                var tw = new TreeWalker(function(node, descend) {\n                    if (!arg) return true;\n                    if (has_await(node) || node instanceof AST_Yield) {\n                        arg = null;\n                        return true;\n                    }\n                    if (node instanceof AST_ObjectIdentity) {\n                        if (fn_strict || !arg_scope) arg = null;\n                        return true;\n                    }\n                    if (node instanceof AST_SymbolRef) {\n                        var def;\n                        if (node.in_arg && !is_safe_lexical(node.definition())\n                            || (def = fn.variables.get(node.name)) && def !== node.definition()) {\n                            arg = null;\n                        }\n                        return true;\n                    }\n                    if (node instanceof AST_Scope && !is_arrow(node)) {\n                        var save_scope = arg_scope;\n                        arg_scope = node;\n                        descend();\n                        arg_scope = save_scope;\n                        return true;\n                    }\n                });\n                args = iife.args.slice();\n                var len = args.length;\n                var names = new Dictionary();\n                for (var i = fn.argnames.length; --i >= 0;) {\n                    var sym = fn.argnames[i];\n                    var arg = args[i];\n                    var value = null;\n                    if (sym instanceof AST_DefaultValue) {\n                        value = sym.value;\n                        sym = sym.name;\n                        args[len + i] = value;\n                    }\n                    if (sym instanceof AST_Destructured) {\n                        if (iife_in_try && arg_may_throw(function(node) {\n                            return node.has_side_effects(compressor);\n                        }, sym, arg)) {\n                            candidates.length = 0;\n                            break;\n                        }\n                        args[len + i] = fn.argnames[i];\n                        continue;\n                    }\n                    if (names.has(sym.name)) continue;\n                    names.set(sym.name, true);\n                    if (value) arg = is_undefined(arg) ? value : null;\n                    if (!arg && !value) {\n                        arg = make_node(AST_Undefined, sym).transform(compressor);\n                    } else if (arg instanceof AST_Lambda && arg.pinned()) {\n                        arg = null;\n                    } else if (arg) {\n                        arg.walk(tw);\n                    }\n                    if (!arg) continue;\n                    var candidate = make_node(AST_VarDef, sym, {\n                        name: sym,\n                        value: arg,\n                    });\n                    candidate.name_index = i;\n                    candidate.arg_index = value ? len + i : i;\n                    candidates.unshift([ candidate ]);\n                }\n                if (fn.rest) args.push(fn.rest);\n            }\n\n            function extract_candidates(expr, unused) {\n                hit_stack.push(expr);\n                if (expr instanceof AST_Array) {\n                    expr.elements.forEach(function(node) {\n                        extract_candidates(node, unused);\n                    });\n                } else if (expr instanceof AST_Assign) {\n                    var lhs = expr.left;\n                    if (!(lhs instanceof AST_Destructured)) candidates.push(hit_stack.slice());\n                    extract_candidates(lhs);\n                    extract_candidates(expr.right);\n                    if (lhs instanceof AST_SymbolRef && expr.operator == \"=\") {\n                        assignments.set(lhs.name, (assignments.get(lhs.name) || 0) + 1);\n                    }\n                } else if (expr instanceof AST_Await) {\n                    extract_candidates(expr.expression, unused);\n                } else if (expr instanceof AST_Binary) {\n                    var lazy = lazy_op[expr.operator];\n                    if (unused\n                        && lazy\n                        && expr.operator != \"??\"\n                        && expr.right instanceof AST_Assign\n                        && expr.right.operator == \"=\"\n                        && !(expr.right.left instanceof AST_Destructured)) {\n                        candidates.push(hit_stack.slice());\n                    }\n                    extract_candidates(expr.left, !lazy && unused);\n                    extract_candidates(expr.right, unused);\n                } else if (expr instanceof AST_Call) {\n                    extract_candidates(expr.expression);\n                    expr.args.forEach(extract_candidates);\n                } else if (expr instanceof AST_Case) {\n                    extract_candidates(expr.expression);\n                } else if (expr instanceof AST_Conditional) {\n                    extract_candidates(expr.condition);\n                    extract_candidates(expr.consequent, unused);\n                    extract_candidates(expr.alternative, unused);\n                } else if (expr instanceof AST_Definitions) {\n                    expr.definitions.forEach(extract_candidates);\n                } else if (expr instanceof AST_Dot) {\n                    extract_candidates(expr.expression);\n                } else if (expr instanceof AST_DWLoop) {\n                    extract_candidates(expr.condition);\n                    if (!(expr.body instanceof AST_Block)) {\n                        extract_candidates(expr.body);\n                    }\n                } else if (expr instanceof AST_Exit) {\n                    if (expr.value) extract_candidates(expr.value);\n                } else if (expr instanceof AST_For) {\n                    if (expr.init) extract_candidates(expr.init, true);\n                    if (expr.condition) extract_candidates(expr.condition);\n                    if (expr.step) extract_candidates(expr.step, true);\n                    if (!(expr.body instanceof AST_Block)) {\n                        extract_candidates(expr.body);\n                    }\n                } else if (expr instanceof AST_ForEnumeration) {\n                    extract_candidates(expr.object);\n                    if (!(expr.body instanceof AST_Block)) {\n                        extract_candidates(expr.body);\n                    }\n                } else if (expr instanceof AST_If) {\n                    extract_candidates(expr.condition);\n                    if (!(expr.body instanceof AST_Block)) {\n                        extract_candidates(expr.body);\n                    }\n                    if (expr.alternative && !(expr.alternative instanceof AST_Block)) {\n                        extract_candidates(expr.alternative);\n                    }\n                } else if (expr instanceof AST_Object) {\n                    expr.properties.forEach(function(prop) {\n                        hit_stack.push(prop);\n                        if (prop.key instanceof AST_Node) extract_candidates(prop.key);\n                        if (prop instanceof AST_ObjectKeyVal) extract_candidates(prop.value, unused);\n                        hit_stack.pop();\n                    });\n                } else if (expr instanceof AST_Sequence) {\n                    var end = expr.expressions.length - (unused ? 0 : 1);\n                    expr.expressions.forEach(function(node, index) {\n                        extract_candidates(node, index < end);\n                    });\n                } else if (expr instanceof AST_SimpleStatement) {\n                    extract_candidates(expr.body, true);\n                } else if (expr instanceof AST_Spread) {\n                    extract_candidates(expr.expression);\n                } else if (expr instanceof AST_Sub) {\n                    extract_candidates(expr.expression);\n                    extract_candidates(expr.property);\n                } else if (expr instanceof AST_Switch) {\n                    extract_candidates(expr.expression);\n                    expr.body.forEach(extract_candidates);\n                } else if (expr instanceof AST_Unary) {\n                    if (UNARY_POSTFIX[expr.operator]) {\n                        candidates.push(hit_stack.slice());\n                    } else {\n                        extract_candidates(expr.expression);\n                    }\n                } else if (expr instanceof AST_VarDef) {\n                    if (expr.name instanceof AST_SymbolVar) {\n                        if (expr.value) {\n                            var def = expr.name.definition();\n                            if (def.references.length > def.replaced) {\n                                candidates.push(hit_stack.slice());\n                            }\n                        } else {\n                            declare_only.set(expr.name.name, (declare_only.get(expr.name.name) || 0) + 1);\n                        }\n                    }\n                    if (expr.value) extract_candidates(expr.value);\n                } else if (expr instanceof AST_Yield) {\n                    if (expr.expression) extract_candidates(expr.expression);\n                }\n                hit_stack.pop();\n            }\n\n            function find_stop(node, level) {\n                var parent = scanner.parent(level);\n                if (parent instanceof AST_Array) return node;\n                if (parent instanceof AST_Assign) return node;\n                if (parent instanceof AST_Await) return node;\n                if (parent instanceof AST_Binary) return node;\n                if (parent instanceof AST_Call) return node;\n                if (parent instanceof AST_Case) return node;\n                if (parent instanceof AST_Conditional) return node;\n                if (parent instanceof AST_Definitions) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Exit) return node;\n                if (parent instanceof AST_If) return node;\n                if (parent instanceof AST_IterationStatement) return node;\n                if (parent instanceof AST_ObjectProperty) return node;\n                if (parent instanceof AST_PropAccess) return node;\n                if (parent instanceof AST_Sequence) {\n                    return (parent.tail_node() === node ? find_stop : find_stop_unused)(parent, level + 1);\n                }\n                if (parent instanceof AST_SimpleStatement) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Spread) return node;\n                if (parent instanceof AST_Switch) return node;\n                if (parent instanceof AST_Unary) return node;\n                if (parent instanceof AST_VarDef) return node;\n                if (parent instanceof AST_Yield) return node;\n                return null;\n            }\n\n            function find_stop_logical(parent, op, level) {\n                var node;\n                do {\n                    node = parent;\n                    parent = scanner.parent(++level);\n                } while (parent instanceof AST_Assign && parent.operator.slice(0, -1) == op\n                    || parent instanceof AST_Binary && parent.operator == op);\n                return node;\n            }\n\n            function find_stop_expr(expr, cont, node, parent, level) {\n                var replace = can_replace;\n                can_replace = false;\n                var after = stop_after;\n                var if_hit = stop_if_hit;\n                var stack = scanner.stack;\n                scanner.stack = [ parent ];\n                expr.transform(scanner);\n                scanner.stack = stack;\n                stop_if_hit = if_hit;\n                stop_after = after;\n                can_replace = replace;\n                if (abort) {\n                    abort = false;\n                    return node;\n                }\n                return cont(parent, level + 1);\n            }\n\n            function find_stop_value(node, level) {\n                var parent = scanner.parent(level);\n                if (parent instanceof AST_Array) return find_stop_value(parent, level + 1);\n                if (parent instanceof AST_Assign) {\n                    if (may_throw(parent)) return node;\n                    if (parent.left.match_symbol(function(ref) {\n                        return ref instanceof AST_SymbolRef && (lhs.name == ref.name || value_def.name == ref.name);\n                    })) return node;\n                    var op;\n                    if (parent.left === node || !lazy_op[op = parent.operator.slice(0, -1)]) {\n                        return find_stop_value(parent, level + 1);\n                    }\n                    return find_stop_logical(parent, op, level);\n                }\n                if (parent instanceof AST_Await) return find_stop_value(parent, level + 1);\n                if (parent instanceof AST_Binary) {\n                    var op;\n                    if (parent.left === node || !lazy_op[op = parent.operator]) {\n                        return find_stop_value(parent, level + 1);\n                    }\n                    return find_stop_logical(parent, op, level);\n                }\n                if (parent instanceof AST_Call) return parent;\n                if (parent instanceof AST_Case) {\n                    if (parent.expression !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_Conditional) {\n                    if (parent.condition !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_Definitions) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Do) return node;\n                if (parent instanceof AST_Exit) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_For) {\n                    if (parent.init !== node && parent.condition !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_ForEnumeration) {\n                    if (parent.init !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_If) {\n                    if (parent.condition !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_ObjectProperty) {\n                    var obj = scanner.parent(level + 1);\n                    return all(obj.properties, function(prop) {\n                        return prop instanceof AST_ObjectKeyVal;\n                    }) ? find_stop_value(obj, level + 2) : obj;\n                }\n                if (parent instanceof AST_PropAccess) {\n                    var exp = parent.expression;\n                    return exp === node ? find_stop_value(parent, level + 1) : node;\n                }\n                if (parent instanceof AST_Sequence) {\n                    return (parent.tail_node() === node ? find_stop_value : find_stop_unused)(parent, level + 1);\n                }\n                if (parent instanceof AST_SimpleStatement) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Spread) return find_stop_value(parent, level + 1);\n                if (parent instanceof AST_Switch) {\n                    if (parent.expression !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_Unary) {\n                    if (parent.operator == \"delete\") return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_VarDef) return parent.name.match_symbol(function(sym) {\n                    return sym instanceof AST_SymbolDeclaration && (lhs.name == sym.name || value_def.name == sym.name);\n                }) ? node : find_stop_value(parent, level + 1);\n                if (parent instanceof AST_While) {\n                    if (parent.condition !== node) return node;\n                    return find_stop_value(parent, level + 1);\n                }\n                if (parent instanceof AST_Yield) return find_stop_value(parent, level + 1);\n                return null;\n            }\n\n            function find_stop_unused(node, level) {\n                var parent = scanner.parent(level);\n                if (is_last_node(node, parent)) return node;\n                if (in_conditional(node, parent)) return node;\n                if (parent instanceof AST_Array) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Assign) return check_assignment(parent.left);\n                if (parent instanceof AST_Await) return node;\n                if (parent instanceof AST_Binary) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Call) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Case) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Conditional) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Definitions) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Exit) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_If) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_IterationStatement) return node;\n                if (parent instanceof AST_ObjectProperty) {\n                    var obj = scanner.parent(level + 1);\n                    return all(obj.properties, function(prop) {\n                        return prop instanceof AST_ObjectKeyVal;\n                    }) ? find_stop_unused(obj, level + 2) : obj;\n                }\n                if (parent instanceof AST_PropAccess) {\n                    var exp = parent.expression;\n                    if (exp === node) return find_stop_unused(parent, level + 1);\n                    return find_stop_expr(exp, find_stop_unused, node, parent, level);\n                }\n                if (parent instanceof AST_Sequence) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_SimpleStatement) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Spread) return node;\n                if (parent instanceof AST_Switch) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_Unary) return find_stop_unused(parent, level + 1);\n                if (parent instanceof AST_VarDef) return check_assignment(parent.name);\n                if (parent instanceof AST_Yield) return node;\n                return null;\n\n                function check_assignment(lhs) {\n                    if (may_throw(parent)) return node;\n                    if (lhs !== node && lhs instanceof AST_Destructured) {\n                        return find_stop_expr(lhs, find_stop_unused, node, parent, level);\n                    }\n                    return find_stop_unused(parent, level + 1);\n                }\n            }\n\n            function mangleable_var(rhs) {\n                if (force_single) {\n                    force_single = false;\n                    return;\n                }\n                if (remaining < 1) return;\n                rhs = rhs.tail_node();\n                var value = rhs instanceof AST_Assign && rhs.operator == \"=\" ? rhs.left : rhs;\n                if (!(value instanceof AST_SymbolRef)) return;\n                var def = value.definition();\n                if (def.undeclared) return;\n                if (is_arguments(def)) return;\n                if (value !== rhs) {\n                    if (is_lhs_read_only(value, compressor)) return;\n                    var referenced = def.references.length - def.replaced;\n                    if (referenced < 2) return;\n                    var expr = candidate.clone();\n                    expr[expr instanceof AST_Assign ? \"right\" : \"value\"] = value;\n                    if (candidate.name_index >= 0) {\n                        expr.name_index = candidate.name_index;\n                        expr.arg_index = candidate.arg_index;\n                    }\n                    candidate = expr;\n                }\n                return value_def = def;\n            }\n\n            function remaining_refs(def) {\n                return def.references.length - def.replaced - (assignments.get(def.name) || 0);\n            }\n\n            function get_lhs(expr) {\n                if (expr instanceof AST_Assign) {\n                    var lhs = expr.left;\n                    if (!(lhs instanceof AST_SymbolRef)) return lhs;\n                    var def = lhs.definition();\n                    if (scope.uses_arguments && is_funarg(def)) return lhs;\n                    if (compressor.exposed(def)) return lhs;\n                    remaining = remaining_refs(def);\n                    if (def.fixed && lhs.fixed) {\n                        var matches = def.references.filter(function(ref) {\n                            return ref.fixed === lhs.fixed;\n                        }).length - 1;\n                        if (matches < remaining) {\n                            remaining = matches;\n                            assign_pos = 0;\n                            verify_ref = true;\n                        }\n                    }\n                    if (expr.operator == \"=\") mangleable_var(expr.right);\n                    return lhs;\n                }\n                if (expr instanceof AST_Binary) return expr.right.left;\n                if (expr instanceof AST_Unary) return expr.expression;\n                if (expr instanceof AST_VarDef) {\n                    var lhs = expr.name;\n                    var def = lhs.definition();\n                    if (def.const_redefs) return;\n                    if (!member(lhs, def.orig)) return;\n                    if (scope.uses_arguments && is_funarg(def)) return;\n                    var declared = def.orig.length - def.eliminated - (declare_only.get(def.name) || 0);\n                    remaining = remaining_refs(def);\n                    if (def.fixed) remaining = Math.min(remaining, def.references.filter(function(ref) {\n                        if (!ref.fixed) return true;\n                        if (!ref.fixed.assigns) return true;\n                        var assign = ref.fixed.assigns[0];\n                        return assign === lhs || get_rvalue(assign) === expr.value;\n                    }).length);\n                    if (declared > 1 && !(lhs instanceof AST_SymbolFunarg)) {\n                        mangleable_var(expr.value);\n                        return make_node(AST_SymbolRef, lhs);\n                    }\n                    if (mangleable_var(expr.value) || remaining == 1 && !compressor.exposed(def)) {\n                        return make_node(AST_SymbolRef, lhs);\n                    }\n                    return;\n                }\n            }\n\n            function get_rvalue(expr) {\n                if (expr instanceof AST_Assign) return expr.right;\n                if (expr instanceof AST_Binary) {\n                    var node = expr.clone();\n                    node.right = expr.right.right;\n                    return node;\n                }\n                if (expr instanceof AST_VarDef) return expr.value;\n            }\n\n            function invariant(expr) {\n                if (expr instanceof AST_Array) return false;\n                if (expr instanceof AST_Binary && lazy_op[expr.operator]) {\n                    return invariant(expr.left) && invariant(expr.right);\n                }\n                if (expr instanceof AST_Call) return false;\n                if (expr instanceof AST_Conditional) {\n                    return invariant(expr.consequent) && invariant(expr.alternative);\n                }\n                if (expr instanceof AST_Object) return false;\n                return !expr.has_side_effects(compressor);\n            }\n\n            function foldable(expr) {\n                if (expr instanceof AST_Assign && expr.right.single_use) return;\n                var lhs_ids = Object.create(null);\n                var marker = new TreeWalker(function(node) {\n                    if (!(node instanceof AST_SymbolRef)) return;\n                    for (var level = 0, parent, child = node; parent = marker.parent(level++); child = parent) {\n                        if (is_direct_assignment(child, parent)) {\n                            if (parent instanceof AST_DestructuredKeyVal) parent = marker.parent(level++);\n                            continue;\n                        }\n                        lhs_ids[node.definition().id] = true;\n                        return;\n                    }\n                    lhs_ids[node.definition().id] = \"a\";\n                });\n                while (expr instanceof AST_Assign && expr.operator == \"=\") {\n                    expr.left.walk(marker);\n                    expr = expr.right;\n                }\n                if (expr instanceof AST_ObjectIdentity) return rhs_exact_match;\n                if (expr instanceof AST_SymbolRef) {\n                    if (lhs_ids[expr.definition().id] === \"a\") return;\n                    var value = expr.evaluate(compressor);\n                    if (value === expr) return rhs_exact_match;\n                    return rhs_fuzzy_match(value, rhs_exact_match);\n                }\n                if (expr.is_truthy()) return rhs_fuzzy_match(true, return_false);\n                if (expr.is_constant()) {\n                    var ev = expr.evaluate(compressor);\n                    if (!(ev instanceof AST_Node)) return rhs_fuzzy_match(ev, rhs_exact_match);\n                }\n                if (!(lhs instanceof AST_SymbolRef)) return false;\n                if (!invariant(expr)) return false;\n                var circular;\n                expr.walk(new TreeWalker(function(node) {\n                    if (circular) return true;\n                    if (node instanceof AST_SymbolRef && lhs_ids[node.definition().id]) circular = true;\n                }));\n                return !circular && rhs_exact_match;\n\n                function rhs_exact_match(node) {\n                    return expr.equals(node);\n                }\n            }\n\n            function rhs_fuzzy_match(value, fallback) {\n                return function(node, tw) {\n                    if (tw.in_boolean_context()) {\n                        if (value && node.is_truthy() && !node.has_side_effects(compressor)) {\n                            return true;\n                        }\n                        if (node.is_constant()) {\n                            var ev = node.evaluate(compressor);\n                            if (!(ev instanceof AST_Node)) return !ev == !value;\n                        }\n                    }\n                    return fallback(node);\n                };\n            }\n\n            function clear_write_only(assign) {\n                while (assign.write_only) {\n                    assign.write_only = false;\n                    if (!(assign instanceof AST_Assign)) break;\n                    assign = assign.right;\n                }\n            }\n\n            function update_symbols(value, node) {\n                var clear_defined = node instanceof AST_SymbolRef && !node.defined;\n                var scope = node.scope || find_scope(scanner) || block_scope;\n                value.walk(new TreeWalker(function(node) {\n                    if (node instanceof AST_BlockScope) return true;\n                    if (node instanceof AST_Symbol) {\n                        if (clear_defined && node instanceof AST_SymbolRef) node.defined = false;\n                        node.scope = scope;\n                    }\n                }));\n            }\n\n            function may_be_global(node) {\n                if (node instanceof AST_SymbolRef) {\n                    node = node.fixed_value();\n                    if (!node) return true;\n                }\n                if (node instanceof AST_Assign) return node.operator == \"=\" && may_be_global(node.right);\n                return node instanceof AST_PropAccess || node instanceof AST_ObjectIdentity;\n            }\n\n            function get_lvalues(expr) {\n                var lvalues = new Dictionary();\n                if (expr instanceof AST_VarDef) {\n                    if (!expr.name.definition().fixed) well_defined = false;\n                    lvalues.add(expr.name.name, lhs);\n                }\n                var find_arguments = scope.uses_arguments && !compressor.has_directive(\"use strict\");\n                var scan_toplevel = scope instanceof AST_Toplevel;\n                var tw = new TreeWalker(function(node) {\n                    if (node.inlined_node) node.inlined_node.walk(tw);\n                    var value;\n                    if (node instanceof AST_SymbolRef) {\n                        value = node.fixed_value();\n                        if (!value) {\n                            value = node;\n                            var def = node.definition();\n                            var escaped = node.fixed && node.fixed.escaped || def.escaped;\n                            if (!def.undeclared\n                                && (def.assignments || !escaped || escaped.cross_scope)\n                                && (has_escaped(def, node.scope, node, tw.parent()) || !same_scope(def))) {\n                                well_defined = false;\n                            }\n                        }\n                    } else if (node instanceof AST_ObjectIdentity) {\n                        value = node;\n                    }\n                    if (value) {\n                        lvalues.add(node.name, is_modified(compressor, tw, node, value, 0));\n                    } else if (node instanceof AST_Lambda) {\n                        for (var level = 0, parent, child = node; parent = tw.parent(level++); child = parent) {\n                            if (parent instanceof AST_Assign) {\n                                if (parent.left === child) break;\n                                if (parent.operator == \"=\") continue;\n                                if (lazy_op[parent.operator.slice(0, -1)]) continue;\n                                break;\n                            }\n                            if (parent instanceof AST_Binary) {\n                                if (lazy_op[parent.operator]) continue;\n                                break;\n                            }\n                            if (parent instanceof AST_Call) return;\n                            if (parent instanceof AST_Scope) return;\n                            if (parent instanceof AST_Sequence) {\n                                if (parent.tail_node() === child) continue;\n                                break;\n                            }\n                            if (parent instanceof AST_Template) {\n                                if (parent.tag) return;\n                                break;\n                            }\n                        }\n                        node.enclosed.forEach(function(def) {\n                            if (def.scope !== node) enclosed.set(def.name, true);\n                        });\n                        return true;\n                    } else if (find_arguments && node instanceof AST_Sub) {\n                        scope.each_argname(function(argname) {\n                            if (!compressor.option(\"reduce_vars\") || argname.definition().assignments) {\n                                if (!argname.definition().fixed) well_defined = false;\n                                lvalues.add(argname.name, true);\n                            }\n                        });\n                        find_arguments = false;\n                    }\n                    if (!scan_toplevel) return;\n                    if (node.TYPE == \"Call\") {\n                        if (modify_toplevel) return;\n                        var exp = node.expression;\n                        if (exp instanceof AST_PropAccess) return;\n                        if (exp instanceof AST_LambdaExpression && !exp.contains_this()) return;\n                        modify_toplevel = true;\n                    } else if (node instanceof AST_PropAccess && may_be_global(node.expression)) {\n                        if (node === lhs && !(expr instanceof AST_Unary)) {\n                            modify_toplevel = true;\n                        } else {\n                            read_toplevel = true;\n                        }\n                    }\n                });\n                expr.walk(tw);\n                return lvalues;\n            }\n\n            function remove_candidate(expr) {\n                var value = rvalue === rhs_value ? null : make_sequence(rhs_value, rhs_value.expressions.slice(0, -1));\n                var index = expr.name_index;\n                if (index >= 0) {\n                    var args, argname = scope.argnames[index];\n                    if (argname instanceof AST_DefaultValue) {\n                        scope.argnames[index] = argname = argname.clone();\n                        argname.value = value || make_node(AST_Number, argname, { value: 0 });\n                    } else if ((args = compressor.parent().args)[index]) {\n                        scope.argnames[index] = argname.clone();\n                        args[index] = value || make_node(AST_Number, args[index], { value: 0 });\n                    }\n                    return;\n                }\n                var end = hit_stack.length - 1;\n                var last = hit_stack[end];\n                if (last instanceof AST_VarDef || hit_stack[end - 1].body === last) end--;\n                var tt = new TreeTransformer(function(node, descend, in_list) {\n                    if (hit) return node;\n                    if (node !== hit_stack[hit_index]) return node;\n                    hit_index++;\n                    if (hit_index <= end) return handle_custom_scan_order(node, tt);\n                    hit = true;\n                    if (node instanceof AST_Definitions) {\n                        declare_only.set(last.name.name, (declare_only.get(last.name.name) || 0) + 1);\n                        if (value_def) value_def.replaced++;\n                        var defns = node.definitions;\n                        var index = defns.indexOf(last);\n                        var defn = last.clone();\n                        defn.value = null;\n                        if (!value) {\n                            node.definitions[index] = defn;\n                            return node;\n                        }\n                        var body = [ make_node(AST_SimpleStatement, value, { body: value }) ];\n                        if (index > 0) {\n                            var head = node.clone();\n                            head.definitions = defns.slice(0, index);\n                            body.unshift(head);\n                            node = node.clone();\n                            node.definitions = defns.slice(index);\n                        }\n                        body.push(node);\n                        node.definitions[0] = defn;\n                        return in_list ? List.splice(body) : make_node(AST_BlockStatement, node, { body: body });\n                    }\n                    if (!value) return in_list ? List.skip : null;\n                    return is_statement(node) ? make_node(AST_SimpleStatement, value, { body: value }) : value;\n                }, function(node, in_list) {\n                    if (node instanceof AST_For) return patch_for_init(node, in_list);\n                    return patch_sequence(node, tt);\n                });\n                abort = false;\n                hit = false;\n                hit_index = 0;\n                if (!(statements[stat_index] = statements[stat_index].transform(tt))) statements.splice(stat_index, 1);\n            }\n\n            function patch_sequence(node, tt) {\n                if (node instanceof AST_Sequence) switch (node.expressions.length) {\n                  case 0: return null;\n                  case 1: return maintain_this_binding(tt.parent(), node, node.expressions[0]);\n                }\n            }\n\n            function get_defun_scopes(lhs) {\n                if (!(lhs instanceof AST_SymbolDeclaration\n                    || lhs instanceof AST_SymbolRef\n                    || lhs instanceof AST_Destructured)) return;\n                var scopes = [];\n                lhs.mark_symbol(function(node) {\n                    if (node instanceof AST_Symbol) {\n                        var def = node.definition();\n                        var scope = def.scope.resolve();\n                        def.orig.forEach(function(sym) {\n                            if (sym instanceof AST_SymbolDefun) {\n                                if (sym.scope !== scope) push_uniq(scopes, sym.scope);\n                            }\n                        });\n                    }\n                });\n                if (scopes.length == 0) return;\n                return scopes;\n            }\n\n            function is_lhs_local(lhs) {\n                var sym = root_expr(lhs);\n                if (!(sym instanceof AST_SymbolRef)) return false;\n                if (sym.definition().scope.resolve() !== scope) return false;\n                if (!in_loop) return true;\n                if (compound) return false;\n                if (candidate instanceof AST_Unary) return false;\n                var lvalue = lvalues.get(sym.name);\n                return !lvalue || lvalue[0] === lhs;\n            }\n\n            function value_has_side_effects() {\n                if (candidate instanceof AST_Unary) return false;\n                return rvalue.has_side_effects(compressor);\n            }\n\n            function replace_all_symbols(expr) {\n                if (expr instanceof AST_Unary) return false;\n                if (side_effects) return false;\n                if (value_def) return true;\n                if (!(lhs instanceof AST_SymbolRef)) return false;\n                var referenced;\n                if (expr instanceof AST_VarDef) {\n                    referenced = 1;\n                } else if (expr.operator == \"=\") {\n                    referenced = 2;\n                } else {\n                    return false;\n                }\n                var def = lhs.definition();\n                if (def.references.length - def.replaced == referenced) return true;\n                if (!def.fixed) return false;\n                if (!lhs.fixed) return false;\n                var assigns = lhs.fixed.assigns;\n                var matched = 0;\n                if (!all(def.references, function(ref, index) {\n                    var fixed = ref.fixed;\n                    if (!fixed) return false;\n                    if (fixed.to_binary || fixed.to_prefix) return false;\n                    if (fixed === lhs.fixed) {\n                        matched++;\n                        return true;\n                    }\n                    return assigns && fixed.assigns && assigns[0] !== fixed.assigns[0];\n                })) return false;\n                if (matched != referenced) return false;\n                verify_ref = true;\n                return true;\n            }\n\n            function symbol_in_lvalues(sym) {\n                var lvalue = lvalues.get(sym.name);\n                if (!lvalue || all(lvalue, function(lhs) {\n                    return !lhs;\n                })) return;\n                if (lvalue[0] !== lhs) return true;\n                scan_rhs = false;\n            }\n\n            function may_modify(sym) {\n                var def = sym.definition();\n                if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false;\n                if (def.scope.resolve() !== scope) return true;\n                if (modify_toplevel && compressor.exposed(def)) return true;\n                return !all(def.references, function(ref) {\n                    return ref.scope.resolve(true) === scope;\n                });\n            }\n\n            function side_effects_external(node, lhs) {\n                if (node instanceof AST_Assign) return side_effects_external(node.left, true);\n                if (node instanceof AST_Unary) return side_effects_external(node.expression, true);\n                if (node instanceof AST_VarDef) return node.value && side_effects_external(node.value);\n                if (lhs) {\n                    if (node instanceof AST_Dot) return side_effects_external(node.expression, true);\n                    if (node instanceof AST_Sub) return side_effects_external(node.expression, true);\n                    if (node instanceof AST_SymbolRef) return node.definition().scope.resolve() !== scope;\n                }\n                return false;\n            }\n        }\n\n        function eliminate_spurious_blocks(statements) {\n            var changed = false, seen_dirs = [];\n            for (var i = 0; i < statements.length;) {\n                var stat = statements[i];\n                if (stat instanceof AST_BlockStatement) {\n                    if (all(stat.body, safe_to_trim)) {\n                        changed = true;\n                        eliminate_spurious_blocks(stat.body);\n                        [].splice.apply(statements, [i, 1].concat(stat.body));\n                        i += stat.body.length;\n                        continue;\n                    }\n                }\n                if (stat instanceof AST_Directive) {\n                    if (member(stat.value, seen_dirs)) {\n                        changed = true;\n                        statements.splice(i, 1);\n                        continue;\n                    }\n                    seen_dirs.push(stat.value);\n                }\n                if (stat instanceof AST_EmptyStatement) {\n                    changed = true;\n                    statements.splice(i, 1);\n                    continue;\n                }\n                i++;\n            }\n            return changed;\n        }\n\n        function handle_if_return(statements, compressor) {\n            var changed = false;\n            var parent = compressor.parent();\n            var self = compressor.self();\n            var declare_only, jump, merge_jump;\n            var in_iife = in_lambda && parent && parent.TYPE == \"Call\" && parent.expression === self;\n            var chain_if_returns = in_lambda && compressor.option(\"conditionals\") && compressor.option(\"sequences\");\n            var drop_return_void = !(in_try && in_try.bfinally && in_async_generator(scope));\n            var multiple_if_returns = has_multiple_if_returns(statements);\n            for (var i = statements.length; --i >= 0;) {\n                var stat = statements[i];\n                var j = next_index(i);\n                var next = statements[j];\n\n                if (in_lambda && declare_only && !next && stat instanceof AST_Return\n                    && drop_return_void && !(self instanceof AST_SwitchBranch)) {\n                    var body = stat.value;\n                    if (!body) {\n                        changed = true;\n                        statements.splice(i, 1);\n                        continue;\n                    }\n                    var tail = body.tail_node();\n                    if (is_undefined(tail)) {\n                        changed = true;\n                        if (body instanceof AST_UnaryPrefix) {\n                            body = body.expression;\n                        } else if (tail instanceof AST_UnaryPrefix) {\n                            body = body.clone();\n                            body.expressions[body.expressions.length - 1] = tail.expression;\n                        }\n                        statements[i] = make_node(AST_SimpleStatement, stat, { body: body });\n                        continue;\n                    }\n                }\n\n                if (stat instanceof AST_If) {\n                    var ab = aborts(stat.body);\n                    // if (foo()) { bar(); return; } else baz(); moo(); ---> if (foo()) bar(); else { baz(); moo(); }\n                    if (can_merge_flow(ab)) {\n                        if (ab.label) remove(ab.label.thedef.references, ab);\n                        changed = true;\n                        stat = stat.clone();\n                        stat.body = make_node(AST_BlockStatement, stat, {\n                            body: as_statement_array_with_return(stat.body, ab),\n                        });\n                        stat.alternative = make_node(AST_BlockStatement, stat, {\n                            body: as_statement_array(stat.alternative).concat(extract_functions(merge_jump, jump)),\n                        });\n                        adjust_refs(ab.value, merge_jump);\n                        statements[i] = stat;\n                        statements[i] = stat.transform(compressor);\n                        continue;\n                    }\n                    // if (foo()) { bar(); return x; } return y; ---> if (!foo()) return y; bar(); return x;\n                    if (ab && !stat.alternative && next instanceof AST_Jump) {\n                        var cond = stat.condition;\n                        var preference = i + 1 == j && stat.body instanceof AST_BlockStatement;\n                        cond = best_of_expression(cond, cond.negate(compressor), preference);\n                        if (cond !== stat.condition) {\n                            changed = true;\n                            stat = stat.clone();\n                            stat.condition = cond;\n                            var body = stat.body;\n                            stat.body = make_node(AST_BlockStatement, next, {\n                                body: extract_functions(true, null, j + 1),\n                            });\n                            statements.splice(i, 1, stat, body);\n                            // proceed further only if `TreeWalker.stack` is in a consistent state\n                            //    https://github.com/mishoo/UglifyJS/issues/5595\n                            //    https://github.com/mishoo/UglifyJS/issues/5597\n                            if (!in_lambda || self instanceof AST_Block && self.body === statements) {\n                                statements[i] = stat.transform(compressor);\n                            }\n                            continue;\n                        }\n                    }\n                    var alt = aborts(stat.alternative);\n                    // if (foo()) bar(); else { baz(); return; } moo(); ---> if (foo()) { bar(); moo(); } else baz();\n                    if (can_merge_flow(alt)) {\n                        if (alt.label) remove(alt.label.thedef.references, alt);\n                        changed = true;\n                        stat = stat.clone();\n                        stat.body = make_node(AST_BlockStatement, stat.body, {\n                            body: as_statement_array(stat.body).concat(extract_functions(merge_jump, jump)),\n                        });\n                        stat.alternative = make_node(AST_BlockStatement, stat.alternative, {\n                            body: as_statement_array_with_return(stat.alternative, alt),\n                        });\n                        adjust_refs(alt.value, merge_jump);\n                        statements[i] = stat;\n                        statements[i] = stat.transform(compressor);\n                        continue;\n                    }\n                    if (compressor.option(\"typeofs\")) {\n                        if (ab && !alt) {\n                            var stats = make_node(AST_BlockStatement, self, { body: statements.slice(i + 1) });\n                            mark_locally_defined(stat.condition, null, stats);\n                        }\n                        if (!ab && alt) {\n                            var stats = make_node(AST_BlockStatement, self, { body: statements.slice(i + 1) });\n                            mark_locally_defined(stat.condition, stats);\n                        }\n                    }\n                }\n\n                if (stat instanceof AST_If && stat.body instanceof AST_Return) {\n                    var value = stat.body.value;\n                    var in_bool = stat.body.in_bool || next instanceof AST_Return && next.in_bool;\n                    // if (foo()) return x; return y; ---> return foo() ? x : y;\n                    if (!stat.alternative && next instanceof AST_Return\n                        && (drop_return_void || !value == !next.value)) {\n                        changed = true;\n                        stat = stat.clone();\n                        stat.alternative = make_node(AST_BlockStatement, next, {\n                            body: extract_functions(true, null, j + 1),\n                        });\n                        statements[i] = stat;\n                        statements[i] = stat.transform(compressor);\n                        continue;\n                    }\n                    // if (foo()) return x; [ return ; ] ---> return foo() ? x : undefined;\n                    // if (foo()) return bar() ? x : void 0; ---> return foo() && bar() ? x : void 0;\n                    // if (foo()) return bar() ? void 0 : x; ---> return !foo() || bar() ? void 0 : x;\n                    if (in_lambda && declare_only && !next && !stat.alternative && (in_bool\n                        || value && multiple_if_returns\n                        || value instanceof AST_Conditional && (is_undefined(value.consequent, compressor)\n                            || is_undefined(value.alternative, compressor)))) {\n                        changed = true;\n                        stat = stat.clone();\n                        stat.alternative = make_node(AST_Return, stat, { value: null });\n                        statements[i] = stat;\n                        statements[i] = stat.transform(compressor);\n                        continue;\n                    }\n                    // if (a) return b; if (c) return d; e; ---> return a ? b : c ? d : void e;\n                    //\n                    // if sequences is not enabled, this can lead to an endless loop (issue #866).\n                    // however, with sequences on this helps producing slightly better output for\n                    // the example code.\n                    var prev, prev_stat;\n                    if (chain_if_returns && !stat.alternative\n                        && (!(prev_stat = statements[prev = prev_index(i)]) && in_iife\n                            || prev_stat instanceof AST_If && prev_stat.body instanceof AST_Return)\n                        && (!next ? !declare_only\n                            : next instanceof AST_SimpleStatement && next_index(j) == statements.length)) {\n                        changed = true;\n                        var exprs = [];\n                        stat = stat.clone();\n                        exprs.push(stat.condition);\n                        stat.condition = make_sequence(stat, exprs);\n                        stat.alternative = make_node(AST_BlockStatement, self, {\n                            body: extract_functions().concat(make_node(AST_Return, self, { value: null })),\n                        });\n                        statements[i] = stat.transform(compressor);\n                        i = prev + 1;\n                        continue;\n                    }\n                }\n\n                if (stat instanceof AST_Break || stat instanceof AST_Exit) {\n                    jump = stat;\n                    continue;\n                }\n\n                if (declare_only && jump && jump === next) eliminate_returns(stat);\n            }\n            return changed;\n\n            function has_multiple_if_returns(statements) {\n                var n = 0;\n                for (var i = statements.length; --i >= 0;) {\n                    var stat = statements[i];\n                    if (stat instanceof AST_If && stat.body instanceof AST_Return) {\n                        if (++n > 1) return true;\n                    }\n                }\n                return false;\n            }\n\n            function match_target(target) {\n                return last_of(compressor, function(node) {\n                    return node === target;\n                });\n            }\n\n            function match_return(ab, exact) {\n                if (!jump) return false;\n                if (jump.TYPE != ab.TYPE) return false;\n                var value = ab.value;\n                if (!value) return false;\n                var equals = jump.equals(ab);\n                if (!equals && value instanceof AST_Sequence) {\n                    value = value.tail_node();\n                    if (jump.value && jump.value.equals(value)) equals = 2;\n                }\n                if (!equals && !exact && jump.value instanceof AST_Sequence) {\n                    if (jump.value.tail_node().equals(value)) equals = 3;\n                }\n                return equals;\n            }\n\n            function can_drop_abort(ab) {\n                if (ab instanceof AST_Exit) {\n                    if (merge_jump = match_return(ab)) return true;\n                    if (!in_lambda) return false;\n                    if (!(ab instanceof AST_Return)) return false;\n                    var value = ab.value;\n                    if (value) {\n                        if (!drop_return_void) return false;\n                        if (!is_undefined(value.tail_node())) return false;\n                    }\n                    if (!(self instanceof AST_SwitchBranch)) return true;\n                    if (!jump) return false;\n                    if (jump instanceof AST_Exit && jump.value) return false;\n                    merge_jump = 4;\n                    return true;\n                }\n                if (!(ab instanceof AST_LoopControl)) return false;\n                if (self instanceof AST_SwitchBranch) {\n                    if (jump instanceof AST_Exit) {\n                        if (!in_lambda) return false;\n                        if (jump.value) return false;\n                        merge_jump = true;\n                    } else if (jump) {\n                        if (compressor.loopcontrol_target(jump) !== parent) return false;\n                        merge_jump = true;\n                    } else if (jump === false) {\n                        return false;\n                    }\n                }\n                var lct = compressor.loopcontrol_target(ab);\n                if (ab instanceof AST_Continue) return match_target(loop_body(lct));\n                if (lct instanceof AST_IterationStatement) return false;\n                return match_target(lct);\n            }\n\n            function can_merge_flow(ab) {\n                merge_jump = false;\n                if (!can_drop_abort(ab)) return false;\n                for (var j = statements.length; --j > i;) {\n                    var stat = statements[j];\n                    if (stat instanceof AST_DefClass) {\n                        if (stat.name.definition().preinit) return false;\n                    } else if (stat instanceof AST_Const || stat instanceof AST_Let) {\n                        if (!all(stat.definitions, function(defn) {\n                            return !defn.name.match_symbol(function(node) {\n                                return node instanceof AST_SymbolDeclaration && node.definition().preinit;\n                            });\n                        })) return false;\n                    }\n                }\n                return true;\n            }\n\n            function extract_functions(mode, stop, end) {\n                var defuns = [];\n                var lexical = false;\n                var start = i + 1;\n                if (!mode) {\n                    end = statements.length;\n                    jump = null;\n                } else if (stop) {\n                    end = statements.lastIndexOf(stop);\n                } else {\n                    stop = statements[end];\n                    if (stop !== jump) jump = false;\n                }\n                var tail = statements.splice(start, end - start).filter(function(stat) {\n                    if (stat instanceof AST_LambdaDefinition) {\n                        defuns.push(stat);\n                        return false;\n                    }\n                    if (is_lexical_definition(stat)) lexical = true;\n                    return true;\n                });\n                if (mode === 3) {\n                    tail.push(make_node(AST_SimpleStatement, stop.value, {\n                        body: make_sequence(stop.value, stop.value.expressions.slice(0, -1)),\n                    }));\n                    stop.value = stop.value.tail_node();\n                }\n                [].push.apply(lexical ? tail : statements, defuns);\n                return tail;\n            }\n\n            function trim_return(value, mode) {\n                if (value) switch (mode) {\n                  case 4:\n                    return value;\n                  case 3:\n                    if (!(value instanceof AST_Sequence)) break;\n                  case 2:\n                    return make_sequence(value, value.expressions.slice(0, -1));\n                }\n            }\n\n            function as_statement_array_with_return(node, ab) {\n                var body = as_statement_array(node);\n                var block = body, last;\n                while ((last = block[block.length - 1]) !== ab) {\n                    block = last.body;\n                }\n                block.pop();\n                var value = ab.value;\n                if (merge_jump) value = trim_return(value, merge_jump);\n                if (value) block.push(make_node(AST_SimpleStatement, value, { body: value }));\n                return body;\n            }\n\n            function adjust_refs(value, mode) {\n                if (!mode) return;\n                if (!value) return;\n                switch (mode) {\n                  case 4:\n                    return;\n                  case 3:\n                  case 2:\n                    value = value.tail_node();\n                }\n                merge_expression(value, jump.value);\n            }\n\n            function next_index(i) {\n                declare_only = true;\n                for (var j = i; ++j < statements.length;) {\n                    var stat = statements[j];\n                    if (is_declaration(stat)) continue;\n                    if (stat instanceof AST_Var) {\n                        declare_only = false;\n                        continue;\n                    }\n                    break;\n                }\n                return j;\n            }\n\n            function prev_index(i) {\n                for (var j = i; --j >= 0;) {\n                    var stat = statements[j];\n                    if (stat instanceof AST_Var) continue;\n                    if (is_declaration(stat)) continue;\n                    break;\n                }\n                return j;\n            }\n\n            function eliminate_returns(stat, keep_throws, in_block) {\n                if (stat instanceof AST_Exit) {\n                    var mode = !(keep_throws && stat instanceof AST_Throw) && match_return(stat, true);\n                    if (mode) {\n                        changed = true;\n                        var value = trim_return(stat.value, mode);\n                        if (value) return make_node(AST_SimpleStatement, value, { body: value });\n                        return in_block ? null : make_node(AST_EmptyStatement, stat);\n                    }\n                } else if (stat instanceof AST_If) {\n                    stat.body = eliminate_returns(stat.body, keep_throws);\n                    if (stat.alternative) stat.alternative = eliminate_returns(stat.alternative, keep_throws);\n                } else if (stat instanceof AST_LabeledStatement) {\n                    stat.body = eliminate_returns(stat.body, keep_throws);\n                } else if (stat instanceof AST_Try) {\n                    if (!stat.bfinally || !jump.value || jump.value.is_constant()) {\n                        if (stat.bcatch) eliminate_returns(stat.bcatch, keep_throws);\n                        var trimmed = eliminate_returns(stat.body.pop(), true, true);\n                        if (trimmed) stat.body.push(trimmed);\n                    }\n                } else if (stat instanceof AST_Block && !(stat instanceof AST_Scope || stat instanceof AST_Switch)) {\n                    var trimmed = eliminate_returns(stat.body.pop(), keep_throws, true);\n                    if (trimmed) stat.body.push(trimmed);\n                }\n                return stat;\n            }\n        }\n\n        function eliminate_dead_code(statements, compressor) {\n            var has_quit;\n            var self = compressor.self();\n            if (self instanceof AST_Catch) {\n                self = compressor.parent();\n            } else if (self instanceof AST_LabeledStatement) {\n                self = self.body;\n            }\n            for (var i = 0, n = 0, len = statements.length; i < len; i++) {\n                var stat = statements[i];\n                if (stat instanceof AST_LoopControl) {\n                    var lct = compressor.loopcontrol_target(stat);\n                    if (loop_body(lct) !== self\n                        || stat instanceof AST_Break && lct instanceof AST_IterationStatement) {\n                        statements[n++] = stat;\n                    } else if (stat.label) {\n                        remove(stat.label.thedef.references, stat);\n                    }\n                } else {\n                    statements[n++] = stat;\n                }\n                if (aborts(stat)) {\n                    has_quit = statements.slice(i + 1);\n                    break;\n                }\n            }\n            statements.length = n;\n            if (has_quit) has_quit.forEach(function(stat) {\n                extract_declarations_from_unreachable_code(compressor, stat, statements);\n            });\n            return statements.length != len;\n        }\n\n        function trim_awaits(statements, compressor) {\n            if (!in_lambda || in_try && in_try.bfinally) return;\n            var changed = false;\n            for (var index = statements.length; --index >= 0;) {\n                var stat = statements[index];\n                if (!(stat instanceof AST_SimpleStatement)) break;\n                var node = stat.body.tail_node();\n                if (!(node instanceof AST_Await)) break;\n                var exp = node.expression;\n                if (!needs_enqueuing(compressor, exp)) break;\n                changed = true;\n                exp = exp.drop_side_effect_free(compressor, true);\n                if (stat.body instanceof AST_Sequence) {\n                    var expressions = stat.body.expressions.slice();\n                    expressions.pop();\n                    if (exp) expressions.push(exp);\n                    stat.body = make_sequence(stat.body, expressions);\n                    break;\n                }\n                if (exp) {\n                    stat.body = exp;\n                    break;\n                }\n            }\n            statements.length = index + 1;\n            return changed;\n        }\n\n        function inline_iife(statements, compressor) {\n            var changed = false;\n            var index = statements.length - 1;\n            if (in_lambda && index >= 0) {\n                var no_return = in_try && in_try.bfinally && in_async_generator(scope);\n                var inlined = statements[index].try_inline(compressor, block_scope, no_return);\n                if (inlined) {\n                    statements[index--] = inlined;\n                    changed = true;\n                }\n            }\n            var loop = in_loop && in_try ? \"try\" : in_loop;\n            for (; index >= 0; index--) {\n                var inlined = statements[index].try_inline(compressor, block_scope, true, loop);\n                if (!inlined) continue;\n                statements[index] = inlined;\n                changed = true;\n            }\n            return changed;\n        }\n\n        function sequencesize(statements, compressor) {\n            if (statements.length < 2) return;\n            var seq = [], n = 0;\n            function push_seq() {\n                if (!seq.length) return;\n                var body = make_sequence(seq[0], seq);\n                statements[n++] = make_node(AST_SimpleStatement, body, { body: body });\n                seq = [];\n            }\n            for (var i = 0, len = statements.length; i < len; i++) {\n                var stat = statements[i];\n                if (stat instanceof AST_SimpleStatement) {\n                    if (seq.length >= compressor.sequences_limit) push_seq();\n                    merge_sequence(seq, stat.body);\n                } else if (is_declaration(stat)) {\n                    statements[n++] = stat;\n                } else {\n                    push_seq();\n                    statements[n++] = stat;\n                }\n            }\n            push_seq();\n            statements.length = n;\n            return n != len;\n        }\n\n        function to_simple_statement(block, decls) {\n            if (!(block instanceof AST_BlockStatement)) return block;\n            var stat = null;\n            for (var i = 0; i < block.body.length; i++) {\n                var line = block.body[i];\n                if (line instanceof AST_Var && declarations_only(line)) {\n                    decls.push(line);\n                } else if (stat || is_lexical_definition(line)) {\n                    return false;\n                } else {\n                    stat = line;\n                }\n            }\n            return stat;\n        }\n\n        function sequencesize_2(statements, compressor) {\n            var changed = false, n = 0, prev;\n            for (var i = 0; i < statements.length; i++) {\n                var stat = statements[i];\n                if (prev) {\n                    if (stat instanceof AST_Exit) {\n                        if (stat.value || !in_async_generator(scope)) {\n                            stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat)).optimize(compressor);\n                        }\n                    } else if (stat instanceof AST_For) {\n                        if (!(stat.init instanceof AST_Definitions)) {\n                            var abort = false;\n                            prev.body.walk(new TreeWalker(function(node) {\n                                if (abort || node instanceof AST_Scope) return true;\n                                if (node instanceof AST_Binary && node.operator == \"in\") {\n                                    abort = true;\n                                    return true;\n                                }\n                            }));\n                            if (!abort) {\n                                if (stat.init) stat.init = cons_seq(stat.init);\n                                else {\n                                    stat.init = prev.body;\n                                    n--;\n                                    changed = true;\n                                }\n                            }\n                        }\n                    } else if (stat instanceof AST_ForIn) {\n                        if (!is_lexical_definition(stat.init)) stat.object = cons_seq(stat.object);\n                    } else if (stat instanceof AST_If) {\n                        stat.condition = cons_seq(stat.condition);\n                    } else if (stat instanceof AST_Switch) {\n                        stat.expression = cons_seq(stat.expression);\n                    } else if (stat instanceof AST_With) {\n                        stat.expression = cons_seq(stat.expression);\n                    }\n                }\n                if (compressor.option(\"conditionals\") && stat instanceof AST_If) {\n                    var decls = [];\n                    var body = to_simple_statement(stat.body, decls);\n                    var alt = to_simple_statement(stat.alternative, decls);\n                    if (body !== false && alt !== false && decls.length > 0) {\n                        var len = decls.length;\n                        decls.push(make_node(AST_If, stat, {\n                            condition: stat.condition,\n                            body: body || make_node(AST_EmptyStatement, stat.body),\n                            alternative: alt,\n                        }));\n                        decls.unshift(n, 1);\n                        [].splice.apply(statements, decls);\n                        i += len;\n                        n += len + 1;\n                        prev = null;\n                        changed = true;\n                        continue;\n                    }\n                }\n                statements[n++] = stat;\n                prev = stat instanceof AST_SimpleStatement ? stat : null;\n            }\n            statements.length = n;\n            return changed;\n\n            function cons_seq(right) {\n                n--;\n                changed = true;\n                var left = prev.body;\n                return make_sequence(left, [ left, right ]);\n            }\n        }\n\n        function extract_exprs(body) {\n            if (body instanceof AST_Assign) return [ body ];\n            if (body instanceof AST_Sequence) return body.expressions.slice();\n        }\n\n        function join_assigns(defn, body, keep) {\n            var exprs = extract_exprs(body);\n            if (!exprs) return;\n            keep = keep || 0;\n            var trimmed = false;\n            for (var i = exprs.length - keep; --i >= 0;) {\n                var expr = exprs[i];\n                if (!can_trim(expr)) continue;\n                var tail;\n                if (expr.left instanceof AST_SymbolRef) {\n                    tail = exprs.slice(i + 1);\n                } else if (expr.left instanceof AST_PropAccess && can_trim(expr.left.expression)) {\n                    tail = exprs.slice(i + 1);\n                    var flattened = expr.clone();\n                    expr = expr.left.expression;\n                    flattened.left = flattened.left.clone();\n                    flattened.left.expression = expr.left.clone();\n                    tail.unshift(flattened);\n                } else {\n                    continue;\n                }\n                if (tail.length == 0) continue;\n                if (!trim_assigns(expr.left, expr.right, tail)) continue;\n                trimmed = true;\n                exprs = exprs.slice(0, i).concat(expr, tail);\n            }\n            if (defn instanceof AST_Definitions) {\n                for (var i = defn.definitions.length; --i >= 0;) {\n                    var def = defn.definitions[i];\n                    if (!def.value) continue;\n                    if (trim_assigns(def.name, def.value, exprs)) trimmed = true;\n                    if (merge_conditional_assignments(def, exprs, keep)) trimmed = true;\n                    break;\n                }\n                if (defn instanceof AST_Var && join_var_assign(defn.definitions, exprs, keep)) trimmed = true;\n            }\n            return trimmed && exprs;\n\n            function can_trim(node) {\n                return node instanceof AST_Assign && node.operator == \"=\";\n            }\n        }\n\n        function merge_assigns(prev, defn) {\n            if (!(prev instanceof AST_SimpleStatement)) return;\n            if (declarations_only(defn)) return;\n            var exprs = extract_exprs(prev.body);\n            if (!exprs) return;\n            var definitions = [];\n            if (!join_var_assign(definitions, exprs.reverse(), 0)) return;\n            defn.definitions = definitions.reverse().concat(defn.definitions);\n            return exprs.reverse();\n        }\n\n        function merge_conditional_assignments(var_def, exprs, keep) {\n            if (!compressor.option(\"conditionals\")) return;\n            if (var_def.name instanceof AST_Destructured) return;\n            var trimmed = false;\n            var def = var_def.name.definition();\n            while (exprs.length > keep) {\n                var cond = to_conditional_assignment(compressor, def, var_def.value, exprs[0]);\n                if (!cond) break;\n                var_def.value = cond;\n                exprs.shift();\n                trimmed = true;\n            }\n            return trimmed;\n        }\n\n        function join_var_assign(definitions, exprs, keep) {\n            var trimmed = false;\n            while (exprs.length > keep) {\n                var expr = exprs[0];\n                if (!(expr instanceof AST_Assign)) break;\n                if (expr.operator != \"=\") break;\n                var lhs = expr.left;\n                if (!(lhs instanceof AST_SymbolRef)) break;\n                if (is_undeclared_ref(lhs)) break;\n                if (lhs.scope.resolve() !== scope) break;\n                var def = lhs.definition();\n                if (def.scope !== scope) break;\n                if (def.orig.length > def.eliminated + 1) break;\n                if (def.orig[0].TYPE != \"SymbolVar\") break;\n                var name = make_node(AST_SymbolVar, lhs);\n                definitions.push(make_node(AST_VarDef, expr, {\n                    name: name,\n                    value: expr.right,\n                }));\n                def.orig.push(name);\n                def.replaced++;\n                exprs.shift();\n                trimmed = true;\n            }\n            return trimmed;\n        }\n\n        function trim_assigns(name, value, exprs) {\n            var names = new Dictionary();\n            names.set(name.name, true);\n            while (value instanceof AST_Assign && value.operator == \"=\") {\n                if (value.left instanceof AST_SymbolRef) names.set(value.left.name, true);\n                value = value.right;\n            }\n            if (value instanceof AST_Array) {\n                var trimmed = false;\n                do {\n                    if (!try_join_array(exprs[0])) break;\n                    exprs.shift();\n                    trimmed = true;\n                } while (exprs.length);\n                return trimmed;\n            } else if (value instanceof AST_Object) {\n                var trimmed = false;\n                do {\n                    if (!try_join_object(exprs[0])) break;\n                    exprs.shift();\n                    trimmed = true;\n                } while (exprs.length);\n                return trimmed;\n            }\n\n            function try_join_array(node) {\n                if (!(node instanceof AST_Assign)) return;\n                if (node.operator != \"=\") return;\n                if (!(node.left instanceof AST_PropAccess)) return;\n                var sym = node.left.expression;\n                if (!(sym instanceof AST_SymbolRef)) return;\n                if (!names.has(sym.name)) return;\n                if (!node.right.is_constant_expression(scope)) return;\n                var prop = node.left.property;\n                if (prop instanceof AST_Node) {\n                    if (try_join_array(prop)) prop = node.left.property = prop.right.clone();\n                    prop = prop.evaluate(compressor);\n                }\n                if (prop instanceof AST_Node) return;\n                if (!RE_POSITIVE_INTEGER.test(\"\" + prop)) return;\n                prop = +prop;\n                var elements = value.elements;\n                var len = elements.length;\n                if (prop > len + 4) return;\n                for (var i = Math.min(len, prop + 1); --i >= 0;) {\n                    if (elements[i] instanceof AST_Spread) return;\n                }\n                if (prop < len) {\n                    var element = elements[prop].drop_side_effect_free(compressor);\n                    elements[prop] = element ? make_sequence(node, [ element, node.right ]) : node.right;\n                } else {\n                    while (prop > len) elements[len++] = make_node(AST_Hole, value);\n                    elements[prop] = node.right;\n                }\n                return true;\n            }\n\n            function try_join_object(node) {\n                if (!(node instanceof AST_Assign)) return;\n                if (node.operator != \"=\") return;\n                if (!(node.left instanceof AST_PropAccess)) return;\n                var sym = node.left.expression;\n                if (!(sym instanceof AST_SymbolRef)) return;\n                if (!names.has(sym.name)) return;\n                if (!node.right.is_constant_expression(scope)) return;\n                var prop = node.left.property;\n                if (prop instanceof AST_Node) {\n                    if (try_join_object(prop)) prop = node.left.property = prop.right.clone();\n                    prop = prop.evaluate(compressor);\n                }\n                if (prop instanceof AST_Node) return;\n                prop = \"\" + prop;\n                var diff = prop == \"__proto__\" || compressor.has_directive(\"use strict\") ? function(node) {\n                    var key = node.key;\n                    return typeof key == \"string\" && key != prop && key != \"__proto__\";\n                } : function(node) {\n                    var key = node.key;\n                    if (node instanceof AST_ObjectGetter || node instanceof AST_ObjectSetter) {\n                        return typeof key == \"string\" && key != prop;\n                    }\n                    return key !== \"__proto__\";\n                };\n                if (!all(value.properties, diff)) return;\n                value.properties.push(make_node(AST_ObjectKeyVal, node, {\n                    key: prop,\n                    value: node.right,\n                }));\n                return true;\n            }\n        }\n\n        function join_consecutive_vars(statements) {\n            var changed = false, defs, prev_defs;\n            for (var i = 0, j = -1; i < statements.length; i++) {\n                var stat = statements[i];\n                var prev = statements[j];\n                if (stat instanceof AST_Definitions) {\n                    if (prev && prev.TYPE == stat.TYPE) {\n                        prev.definitions = prev.definitions.concat(stat.definitions);\n                        changed = true;\n                    } else if (stat && prev instanceof AST_Let && stat.can_letify(compressor)) {\n                        prev.definitions = prev.definitions.concat(to_let(stat, block_scope).definitions);\n                        changed = true;\n                    } else if (prev && stat instanceof AST_Let && prev.can_letify(compressor)) {\n                        defs = prev_defs;\n                        statements[j] = prev = to_let(prev, block_scope);\n                        prev.definitions = prev.definitions.concat(stat.definitions);\n                        changed = true;\n                    } else if (defs && defs.TYPE == stat.TYPE && declarations_only(stat)) {\n                        defs.definitions = defs.definitions.concat(stat.definitions);\n                        changed = true;\n                    } else if (stat instanceof AST_Var) {\n                        var exprs = merge_assigns(prev, stat);\n                        if (exprs) {\n                            if (exprs.length) {\n                                prev.body = make_sequence(prev, exprs);\n                                j++;\n                            }\n                            changed = true;\n                        } else {\n                            j++;\n                        }\n                        prev_defs = defs;\n                        statements[j] = defs = stat;\n                    } else {\n                        statements[++j] = stat;\n                    }\n                    continue;\n                } else if (stat instanceof AST_Exit) {\n                    stat.value = join_assigns_expr(stat.value);\n                } else if (stat instanceof AST_For) {\n                    var exprs = join_assigns(prev, stat.init);\n                    if (exprs) {\n                        changed = true;\n                        stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;\n                    } else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {\n                        if (stat.init) {\n                            prev.definitions = prev.definitions.concat(stat.init.definitions);\n                        }\n                        stat = stat.clone();\n                        prev_defs = defs;\n                        defs = stat.init = prev;\n                        statements[j] = merge_defns(stat);\n                        changed = true;\n                        continue;\n                    } else if (defs && stat.init && defs.TYPE == stat.init.TYPE && declarations_only(stat.init)) {\n                        defs.definitions = defs.definitions.concat(stat.init.definitions);\n                        stat.init = null;\n                        changed = true;\n                    } else if (stat.init instanceof AST_Var) {\n                        prev_defs = defs;\n                        defs = stat.init;\n                        exprs = merge_assigns(prev, stat.init);\n                        if (exprs) {\n                            changed = true;\n                            if (exprs.length == 0) {\n                                statements[j] = merge_defns(stat);\n                                continue;\n                            }\n                            prev.body = make_sequence(prev, exprs);\n                        }\n                    }\n                } else if (stat instanceof AST_ForEnumeration) {\n                    if (defs && defs.TYPE == stat.init.TYPE) {\n                        var defns = defs.definitions.slice();\n                        stat.init = stat.init.definitions[0].name.convert_symbol(AST_SymbolRef, function(ref, name) {\n                            defns.push(make_node(AST_VarDef, name, {\n                                name: name,\n                                value: null,\n                            }));\n                            name.definition().references.push(ref);\n                        });\n                        defs.definitions = defns;\n                        changed = true;\n                    }\n                    stat.object = join_assigns_expr(stat.object);\n                } else if (stat instanceof AST_If) {\n                    stat.condition = join_assigns_expr(stat.condition);\n                } else if (stat instanceof AST_SimpleStatement) {\n                    var exprs = join_assigns(prev, stat.body), next;\n                    if (exprs) {\n                        changed = true;\n                        if (!exprs.length) continue;\n                        stat.body = make_sequence(stat.body, exprs);\n                    } else if (prev instanceof AST_Definitions\n                        && (next = statements[i + 1])\n                        && prev.TYPE == next.TYPE\n                        && (next = next.definitions[0]).value) {\n                        changed = true;\n                        next.value = make_sequence(stat, [ stat.body, next.value ]);\n                        continue;\n                    }\n                } else if (stat instanceof AST_Switch) {\n                    stat.expression = join_assigns_expr(stat.expression);\n                } else if (stat instanceof AST_With) {\n                    stat.expression = join_assigns_expr(stat.expression);\n                }\n                statements[++j] = defs ? merge_defns(stat) : stat;\n            }\n            statements.length = j + 1;\n            return changed;\n\n            function join_assigns_expr(value) {\n                var exprs = join_assigns(prev, value, 1);\n                if (!exprs) return value;\n                changed = true;\n                var tail = value.tail_node();\n                if (exprs[exprs.length - 1] !== tail) exprs.push(tail.left);\n                return make_sequence(value, exprs);\n            }\n\n            function merge_defns(stat) {\n                return stat.transform(new TreeTransformer(function(node, descend, in_list) {\n                    if (node instanceof AST_Definitions) {\n                        if (defs === node) return node;\n                        if (defs.TYPE != node.TYPE) return node;\n                        var parent = this.parent();\n                        if (parent instanceof AST_ForEnumeration && parent.init === node) return node;\n                        if (!declarations_only(node)) return node;\n                        defs.definitions = defs.definitions.concat(node.definitions);\n                        changed = true;\n                        if (parent instanceof AST_For && parent.init === node) return null;\n                        return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n                    }\n                    if (node instanceof AST_ExportDeclaration) return node;\n                    if (node instanceof AST_Scope) return node;\n                    if (!is_statement(node)) return node;\n                }));\n            }\n        }\n    }\n\n    function extract_declarations_from_unreachable_code(compressor, stat, target) {\n        var block;\n        var dropped = false;\n        stat.walk(new TreeWalker(function(node, descend) {\n            if (node instanceof AST_DefClass) {\n                node.extends = null;\n                node.properties = [];\n                push(node);\n                return true;\n            }\n            if (node instanceof AST_Definitions) {\n                var defns = [];\n                if (node.remove_initializers(compressor, defns)) {\n                    AST_Node.warn(\"Dropping initialization in unreachable code [{start}]\", node);\n                }\n                if (defns.length > 0) {\n                    node.definitions = defns;\n                    push(node);\n                }\n                return true;\n            }\n            if (node instanceof AST_LambdaDefinition) {\n                push(node);\n                return true;\n            }\n            if (node instanceof AST_Scope) return true;\n            if (node instanceof AST_BlockScope) {\n                var save = block;\n                block = [];\n                descend();\n                if (block.required) {\n                    target.push(make_node(AST_BlockStatement, stat, { body: block }));\n                } else if (block.length) {\n                    [].push.apply(target, block);\n                }\n                block = save;\n                return true;\n            }\n            if (!(node instanceof AST_LoopControl)) dropped = true;\n        }));\n        if (dropped) AST_Node.warn(\"Dropping unreachable code [{start}]\", stat);\n\n        function push(node) {\n            if (block) {\n                block.push(node);\n                if (!safe_to_trim(node)) block.required = true;\n            } else {\n                target.push(node);\n            }\n        }\n    }\n\n    function is_undefined(node, compressor) {\n        return node == null\n            || node.is_undefined\n            || node instanceof AST_Undefined\n            || node instanceof AST_UnaryPrefix\n                && node.operator == \"void\"\n                && !(compressor && node.expression.has_side_effects(compressor));\n    }\n\n    // in_strict_mode()\n    // return true if scope executes in Strict Mode\n    (function(def) {\n        def(AST_Class, return_true);\n        def(AST_Scope, function(compressor) {\n            var body = this.body;\n            for (var i = 0; i < body.length; i++) {\n                var stat = body[i];\n                if (!(stat instanceof AST_Directive)) break;\n                if (stat.value == \"use strict\") return true;\n            }\n            var parent = this.parent_scope;\n            if (!parent) return compressor.option(\"module\");\n            return parent.resolve(true).in_strict_mode(compressor);\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"in_strict_mode\", func);\n    });\n\n    // is_truthy()\n    // return true if `!!node === true`\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Array, return_true);\n        def(AST_Assign, function() {\n            return this.operator == \"=\" && this.right.is_truthy();\n        });\n        def(AST_Lambda, return_true);\n        def(AST_Object, return_true);\n        def(AST_RegExp, return_true);\n        def(AST_Sequence, function() {\n            return this.tail_node().is_truthy();\n        });\n        def(AST_SymbolRef, function() {\n            var fixed = this.fixed_value();\n            if (!fixed) return false;\n            this.is_truthy = return_false;\n            var result = fixed.is_truthy();\n            delete this.is_truthy;\n            return result;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_truthy\", func);\n    });\n\n    // is_negative_zero()\n    // return true if the node may represent -0\n    (function(def) {\n        def(AST_Node, return_true);\n        def(AST_Array, return_false);\n        function binary(op, left, right) {\n            switch (op) {\n              case \"-\":\n                return left.is_negative_zero()\n                    && (!(right instanceof AST_Constant) || right.value == 0);\n              case \"&&\":\n              case \"||\":\n                return left.is_negative_zero() || right.is_negative_zero();\n              case \"*\":\n              case \"/\":\n              case \"%\":\n              case \"**\":\n                return true;\n              default:\n                return false;\n            }\n        }\n        def(AST_Assign, function() {\n            var op = this.operator;\n            if (op == \"=\") return this.right.is_negative_zero();\n            return binary(op.slice(0, -1), this.left, this.right);\n        });\n        def(AST_Binary, function() {\n            return binary(this.operator, this.left, this.right);\n        });\n        def(AST_Constant, function() {\n            return this.value == 0 && 1 / this.value < 0;\n        });\n        def(AST_Lambda, return_false);\n        def(AST_Object, return_false);\n        def(AST_RegExp, return_false);\n        def(AST_Sequence, function() {\n            return this.tail_node().is_negative_zero();\n        });\n        def(AST_SymbolRef, function() {\n            var fixed = this.fixed_value();\n            if (!fixed) return true;\n            this.is_negative_zero = return_true;\n            var result = fixed.is_negative_zero();\n            delete this.is_negative_zero;\n            return result;\n        });\n        def(AST_UnaryPrefix, function() {\n            return this.operator == \"+\" && this.expression.is_negative_zero()\n                || this.operator == \"-\";\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_negative_zero\", func);\n    });\n\n    // may_throw_on_access()\n    // returns true if this node may be null, undefined or contain `AST_Accessor`\n    (function(def) {\n        AST_Node.DEFMETHOD(\"may_throw_on_access\", function(compressor, force) {\n            return !compressor.option(\"pure_getters\") || this._dot_throw(compressor, force);\n        });\n        function is_strict(compressor, force) {\n            return force || /strict/.test(compressor.option(\"pure_getters\"));\n        }\n        def(AST_Node, is_strict);\n        def(AST_Array, return_false);\n        def(AST_Assign, function(compressor) {\n            var op = this.operator;\n            var sym = this.left;\n            var rhs = this.right;\n            if (op != \"=\") {\n                return lazy_op[op.slice(0, -1)] && (sym._dot_throw(compressor) || rhs._dot_throw(compressor));\n            }\n            if (!rhs._dot_throw(compressor)) return false;\n            if (!(sym instanceof AST_SymbolRef)) return true;\n            if (rhs instanceof AST_Binary && rhs.operator == \"||\" && sym.name == rhs.left.name) {\n                return rhs.right._dot_throw(compressor);\n            }\n            return true;\n        });\n        def(AST_Binary, function(compressor) {\n            return lazy_op[this.operator] && (this.left._dot_throw(compressor) || this.right._dot_throw(compressor));\n        });\n        def(AST_Class, function(compressor, force) {\n            return is_strict(compressor, force) && !all(this.properties, function(prop) {\n                if (prop.private) return true;\n                if (!prop.static) return true;\n                return !(prop instanceof AST_ClassGetter || prop instanceof AST_ClassSetter);\n            });\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.consequent._dot_throw(compressor) || this.alternative._dot_throw(compressor);\n        });\n        def(AST_Constant, return_false);\n        def(AST_Dot, function(compressor, force) {\n            if (!is_strict(compressor, force)) return false;\n            var exp = this.expression;\n            if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();\n            return !(this.property == \"prototype\" && is_lambda(exp));\n        });\n        def(AST_Lambda, return_false);\n        def(AST_Null, return_true);\n        def(AST_Object, function(compressor, force) {\n            return is_strict(compressor, force) && !all(this.properties, function(prop) {\n                if (prop instanceof AST_ObjectGetter || prop instanceof AST_ObjectSetter) return false;\n                return !(prop.key === \"__proto__\" && prop.value._dot_throw(compressor, force));\n            });\n        });\n        def(AST_ObjectIdentity, function(compressor, force) {\n            return is_strict(compressor, force) && !this.scope.resolve().new;\n        });\n        def(AST_Sequence, function(compressor) {\n            return this.tail_node()._dot_throw(compressor);\n        });\n        def(AST_SymbolRef, function(compressor, force) {\n            if (this.defined) return false;\n            if (this.is_undefined) return true;\n            if (!is_strict(compressor, force)) return false;\n            if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;\n            if (this.is_immutable()) return false;\n            var def = this.definition();\n            if (is_arguments(def) && !def.scope.rest && all(def.scope.argnames, function(argname) {\n                return argname instanceof AST_SymbolFunarg;\n            })) return def.scope.uses_arguments > 2;\n            var fixed = this.fixed_value(true);\n            if (!fixed) return true;\n            this._dot_throw = return_true;\n            if (fixed._dot_throw(compressor)) {\n                delete this._dot_throw;\n                return true;\n            }\n            this._dot_throw = return_false;\n            return false;\n        });\n        def(AST_UnaryPrefix, function() {\n            return this.operator == \"void\";\n        });\n        def(AST_UnaryPostfix, return_false);\n        def(AST_Undefined, return_true);\n    })(function(node, func) {\n        node.DEFMETHOD(\"_dot_throw\", func);\n    });\n\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Array, return_true);\n        function is_binary_defined(compressor, op, node) {\n            switch (op) {\n              case \"&&\":\n                return node.left.is_defined(compressor) && node.right.is_defined(compressor);\n              case \"||\":\n                return node.left.is_truthy() || node.right.is_defined(compressor);\n              case \"??\":\n                return node.left.is_defined(compressor) || node.right.is_defined(compressor);\n              default:\n                return true;\n            }\n        }\n        def(AST_Assign, function(compressor) {\n            var op = this.operator;\n            if (op == \"=\") return this.right.is_defined(compressor);\n            return is_binary_defined(compressor, op.slice(0, -1), this);\n        });\n        def(AST_Binary, function(compressor) {\n            return is_binary_defined(compressor, this.operator, this);\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.consequent.is_defined(compressor) && this.alternative.is_defined(compressor);\n        });\n        def(AST_Constant, return_true);\n        def(AST_Hole, return_false);\n        def(AST_Lambda, return_true);\n        def(AST_Object, return_true);\n        def(AST_Sequence, function(compressor) {\n            return this.tail_node().is_defined(compressor);\n        });\n        def(AST_SymbolRef, function(compressor) {\n            if (this.is_undefined) return false;\n            if (is_undeclared_ref(this) && this.is_declared(compressor)) return true;\n            if (this.is_immutable()) return true;\n            var fixed = this.fixed_value();\n            if (!fixed) return false;\n            this.is_defined = return_false;\n            var result = fixed.is_defined(compressor);\n            delete this.is_defined;\n            return result;\n        });\n        def(AST_UnaryPrefix, function() {\n            return this.operator != \"void\";\n        });\n        def(AST_UnaryPostfix, return_true);\n        def(AST_Undefined, return_false);\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_defined\", func);\n    });\n\n    /* -----[ boolean/negation helpers ]----- */\n\n    // methods to determine whether an expression has a boolean result type\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Assign, function(compressor) {\n            return this.operator == \"=\" && this.right.is_boolean(compressor);\n        });\n        var binary = makePredicate(\"in instanceof == != === !== < <= >= >\");\n        def(AST_Binary, function(compressor) {\n            return binary[this.operator] || lazy_op[this.operator]\n                && this.left.is_boolean(compressor)\n                && this.right.is_boolean(compressor);\n        });\n        def(AST_Boolean, return_true);\n        var fn = makePredicate(\"every hasOwnProperty isPrototypeOf propertyIsEnumerable some\");\n        def(AST_Call, function(compressor) {\n            if (!compressor.option(\"unsafe\")) return false;\n            var exp = this.expression;\n            return exp instanceof AST_Dot && (fn[exp.property]\n                || exp.property == \"test\" && exp.expression instanceof AST_RegExp);\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.consequent.is_boolean(compressor) && this.alternative.is_boolean(compressor);\n        });\n        def(AST_New, return_false);\n        def(AST_Sequence, function(compressor) {\n            return this.tail_node().is_boolean(compressor);\n        });\n        def(AST_SymbolRef, function(compressor) {\n            var fixed = this.fixed_value();\n            if (!fixed) return false;\n            this.is_boolean = return_false;\n            var result = fixed.is_boolean(compressor);\n            delete this.is_boolean;\n            return result;\n        });\n        var unary = makePredicate(\"! delete\");\n        def(AST_UnaryPrefix, function() {\n            return unary[this.operator];\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_boolean\", func);\n    });\n\n    // methods to determine if an expression has a numeric result type\n    (function(def) {\n        def(AST_Node, return_false);\n        var binary = makePredicate(\"- * / % ** & | ^ << >> >>>\");\n        def(AST_Assign, function(compressor) {\n            return binary[this.operator.slice(0, -1)]\n                || this.operator == \"=\" && this.right.is_number(compressor);\n        });\n        def(AST_Binary, function(compressor) {\n            if (binary[this.operator]) return true;\n            if (this.operator != \"+\") return false;\n            return (this.left.is_boolean(compressor) || this.left.is_number(compressor))\n                && (this.right.is_boolean(compressor) || this.right.is_number(compressor));\n        });\n        var fn = makePredicate([\n            \"charCodeAt\",\n            \"getDate\",\n            \"getDay\",\n            \"getFullYear\",\n            \"getHours\",\n            \"getMilliseconds\",\n            \"getMinutes\",\n            \"getMonth\",\n            \"getSeconds\",\n            \"getTime\",\n            \"getTimezoneOffset\",\n            \"getUTCDate\",\n            \"getUTCDay\",\n            \"getUTCFullYear\",\n            \"getUTCHours\",\n            \"getUTCMilliseconds\",\n            \"getUTCMinutes\",\n            \"getUTCMonth\",\n            \"getUTCSeconds\",\n            \"getYear\",\n            \"indexOf\",\n            \"lastIndexOf\",\n            \"localeCompare\",\n            \"push\",\n            \"search\",\n            \"setDate\",\n            \"setFullYear\",\n            \"setHours\",\n            \"setMilliseconds\",\n            \"setMinutes\",\n            \"setMonth\",\n            \"setSeconds\",\n            \"setTime\",\n            \"setUTCDate\",\n            \"setUTCFullYear\",\n            \"setUTCHours\",\n            \"setUTCMilliseconds\",\n            \"setUTCMinutes\",\n            \"setUTCMonth\",\n            \"setUTCSeconds\",\n            \"setYear\",\n        ]);\n        def(AST_Call, function(compressor) {\n            if (!compressor.option(\"unsafe\")) return false;\n            var exp = this.expression;\n            return exp instanceof AST_Dot && (fn[exp.property]\n                || is_undeclared_ref(exp.expression) && exp.expression.name == \"Math\");\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);\n        });\n        def(AST_New, return_false);\n        def(AST_Number, return_true);\n        def(AST_Sequence, function(compressor) {\n            return this.tail_node().is_number(compressor);\n        });\n        def(AST_SymbolRef, function(compressor, keep_unary) {\n            var fixed = this.fixed_value();\n            if (!fixed) return false;\n            if (keep_unary\n                && fixed instanceof AST_UnaryPrefix\n                && fixed.operator == \"+\"\n                && fixed.expression.equals(this)) {\n                return false;\n            }\n            this.is_number = return_false;\n            var result = fixed.is_number(compressor);\n            delete this.is_number;\n            return result;\n        });\n        var unary = makePredicate(\"+ - ~ ++ --\");\n        def(AST_Unary, function() {\n            return unary[this.operator];\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_number\", func);\n    });\n\n    // methods to determine if an expression has a string result type\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Assign, function(compressor) {\n            switch (this.operator) {\n              case \"+=\":\n                if (this.left.is_string(compressor)) return true;\n              case \"=\":\n                return this.right.is_string(compressor);\n            }\n        });\n        def(AST_Binary, function(compressor) {\n            return this.operator == \"+\" &&\n                (this.left.is_string(compressor) || this.right.is_string(compressor));\n        });\n        var fn = makePredicate([\n            \"charAt\",\n            \"substr\",\n            \"substring\",\n            \"toExponential\",\n            \"toFixed\",\n            \"toLowerCase\",\n            \"toPrecision\",\n            \"toString\",\n            \"toUpperCase\",\n            \"trim\",\n        ]);\n        def(AST_Call, function(compressor) {\n            if (!compressor.option(\"unsafe\")) return false;\n            var exp = this.expression;\n            return exp instanceof AST_Dot && fn[exp.property];\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);\n        });\n        def(AST_Sequence, function(compressor) {\n            return this.tail_node().is_string(compressor);\n        });\n        def(AST_String, return_true);\n        def(AST_SymbolRef, function(compressor) {\n            var fixed = this.fixed_value();\n            if (!fixed) return false;\n            this.is_string = return_false;\n            var result = fixed.is_string(compressor);\n            delete this.is_string;\n            return result;\n        });\n        def(AST_Template, function(compressor) {\n            return !this.tag || is_raw_tag(compressor, this.tag);\n        });\n        def(AST_UnaryPrefix, function() {\n            return this.operator == \"typeof\";\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_string\", func);\n    });\n\n    var lazy_op = makePredicate(\"&& || ??\");\n\n    (function(def) {\n        function to_node(value, orig) {\n            if (value instanceof AST_Node) return value.clone(true);\n            if (Array.isArray(value)) return make_node(AST_Array, orig, {\n                elements: value.map(function(value) {\n                    return to_node(value, orig);\n                })\n            });\n            if (value && typeof value == \"object\") {\n                var props = [];\n                for (var key in value) if (HOP(value, key)) {\n                    props.push(make_node(AST_ObjectKeyVal, orig, {\n                        key: key,\n                        value: to_node(value[key], orig),\n                    }));\n                }\n                return make_node(AST_Object, orig, { properties: props });\n            }\n            return make_node_from_constant(value, orig);\n        }\n\n        function warn(node) {\n            AST_Node.warn(\"global_defs {this} redefined [{start}]\", node);\n        }\n\n        AST_Toplevel.DEFMETHOD(\"resolve_defines\", function(compressor) {\n            if (!compressor.option(\"global_defs\")) return this;\n            this.figure_out_scope({ ie: compressor.option(\"ie\") });\n            return this.transform(new TreeTransformer(function(node) {\n                var def = node._find_defs(compressor, \"\");\n                if (!def) return;\n                var level = 0, child = node, parent;\n                while (parent = this.parent(level++)) {\n                    if (!(parent instanceof AST_PropAccess)) break;\n                    if (parent.expression !== child) break;\n                    child = parent;\n                }\n                if (is_lhs(child, parent)) {\n                    warn(node);\n                    return;\n                }\n                return def;\n            }));\n        });\n        def(AST_Node, noop);\n        def(AST_Dot, function(compressor, suffix) {\n            return this.expression._find_defs(compressor, \".\" + this.property + suffix);\n        });\n        def(AST_SymbolDeclaration, function(compressor) {\n            if (!this.definition().global) return;\n            if (HOP(compressor.option(\"global_defs\"), this.name)) warn(this);\n        });\n        def(AST_SymbolRef, function(compressor, suffix) {\n            if (!this.definition().global) return;\n            var defines = compressor.option(\"global_defs\");\n            var name = this.name + suffix;\n            if (HOP(defines, name)) return to_node(defines[name], this);\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"_find_defs\", func);\n    });\n\n    function best_of_expression(ast1, ast2, threshold) {\n        var delta = ast2.print_to_string().length - ast1.print_to_string().length;\n        return delta < (threshold || 0) ? ast2 : ast1;\n    }\n\n    function best_of_statement(ast1, ast2, threshold) {\n        return best_of_expression(make_node(AST_SimpleStatement, ast1, {\n            body: ast1,\n        }), make_node(AST_SimpleStatement, ast2, {\n            body: ast2,\n        }), threshold).body;\n    }\n\n    function best_of(compressor, ast1, ast2, threshold) {\n        return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2, threshold);\n    }\n\n    function convert_to_predicate(obj) {\n        var map = Object.create(null);\n        Object.keys(obj).forEach(function(key) {\n            map[key] = makePredicate(obj[key]);\n        });\n        return map;\n    }\n\n    function skip_directives(body) {\n        for (var i = 0; i < body.length; i++) {\n            var stat = body[i];\n            if (!(stat instanceof AST_Directive)) return stat;\n        }\n    }\n\n    function arrow_first_statement() {\n        if (this.value) return make_node(AST_Return, this.value, { value: this.value });\n        return skip_directives(this.body);\n    }\n    AST_Arrow.DEFMETHOD(\"first_statement\", arrow_first_statement);\n    AST_AsyncArrow.DEFMETHOD(\"first_statement\", arrow_first_statement);\n    AST_Lambda.DEFMETHOD(\"first_statement\", function() {\n        return skip_directives(this.body);\n    });\n\n    AST_Lambda.DEFMETHOD(\"length\", function() {\n        var argnames = this.argnames;\n        for (var i = 0; i < argnames.length; i++) {\n            if (argnames[i] instanceof AST_DefaultValue) break;\n        }\n        return i;\n    });\n\n    function try_evaluate(compressor, node) {\n        var ev = node.evaluate(compressor);\n        if (ev === node) return node;\n        ev = make_node_from_constant(ev, node).optimize(compressor);\n        return best_of(compressor, node, ev, compressor.eval_threshold);\n    }\n\n    var object_fns = [\n        \"constructor\",\n        \"toString\",\n        \"valueOf\",\n    ];\n    var native_fns = convert_to_predicate({\n        Array: [\n            \"indexOf\",\n            \"join\",\n            \"lastIndexOf\",\n            \"slice\",\n        ].concat(object_fns),\n        Boolean: object_fns,\n        Function: object_fns,\n        Number: [\n            \"toExponential\",\n            \"toFixed\",\n            \"toPrecision\",\n        ].concat(object_fns),\n        Object: object_fns,\n        RegExp: [\n            \"exec\",\n            \"test\",\n        ].concat(object_fns),\n        String: [\n            \"charAt\",\n            \"charCodeAt\",\n            \"concat\",\n            \"indexOf\",\n            \"italics\",\n            \"lastIndexOf\",\n            \"match\",\n            \"replace\",\n            \"search\",\n            \"slice\",\n            \"split\",\n            \"substr\",\n            \"substring\",\n            \"toLowerCase\",\n            \"toUpperCase\",\n            \"trim\",\n        ].concat(object_fns),\n    });\n    var static_fns = convert_to_predicate({\n        Array: [\n            \"isArray\",\n        ],\n        Math: [\n            \"abs\",\n            \"acos\",\n            \"asin\",\n            \"atan\",\n            \"ceil\",\n            \"cos\",\n            \"exp\",\n            \"floor\",\n            \"log\",\n            \"round\",\n            \"sin\",\n            \"sqrt\",\n            \"tan\",\n            \"atan2\",\n            \"pow\",\n            \"max\",\n            \"min\",\n        ],\n        Number: [\n            \"isFinite\",\n            \"isNaN\",\n        ],\n        Object: [\n            \"create\",\n            \"getOwnPropertyDescriptor\",\n            \"getOwnPropertyNames\",\n            \"getPrototypeOf\",\n            \"isExtensible\",\n            \"isFrozen\",\n            \"isSealed\",\n            \"keys\",\n        ],\n        String: [\n            \"fromCharCode\",\n            \"raw\",\n        ],\n    });\n\n    function is_static_fn(node) {\n        if (!(node instanceof AST_Dot)) return false;\n        var expr = node.expression;\n        if (!is_undeclared_ref(expr)) return false;\n        var static_fn = static_fns[expr.name];\n        return static_fn && (static_fn[node.property] || expr.name == \"Math\" && node.property == \"random\");\n    }\n\n    // Accommodate when compress option evaluate=false\n    // as well as the common constant expressions !0 and -1\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Constant, return_true);\n        def(AST_RegExp, return_false);\n        var unaryPrefix = makePredicate(\"! ~ - + void\");\n        def(AST_UnaryPrefix, function() {\n            return unaryPrefix[this.operator] && this.expression instanceof AST_Constant;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_constant\", func);\n    });\n\n    // methods to evaluate a constant expression\n    (function(def) {\n        // If the node has been successfully reduced to a constant,\n        // then its value is returned; otherwise the element itself\n        // is returned.\n        //\n        // They can be distinguished as constant value is never a\n        // descendant of AST_Node.\n        //\n        // When `ignore_side_effects` is `true`, inspect the constant value\n        // produced without worrying about any side effects caused by said\n        // expression.\n        AST_Node.DEFMETHOD(\"evaluate\", function(compressor, ignore_side_effects) {\n            if (!compressor.option(\"evaluate\")) return this;\n            var cached = [];\n            var val = this._eval(compressor, ignore_side_effects, cached, 1);\n            cached.forEach(function(node) {\n                delete node._eval;\n            });\n            if (ignore_side_effects) return val;\n            if (!val || val instanceof RegExp) return val;\n            if (typeof val == \"function\" || typeof val == \"object\") return this;\n            return val;\n        });\n        var scan_modified = new TreeWalker(function(node) {\n            if (node instanceof AST_Assign) modified(node.left);\n            if (node instanceof AST_ForEnumeration) modified(node.init);\n            if (node instanceof AST_Unary && UNARY_POSTFIX[node.operator]) modified(node.expression);\n        });\n        function modified(node) {\n            if (node instanceof AST_DestructuredArray) {\n                node.elements.forEach(modified);\n            } else if (node instanceof AST_DestructuredObject) {\n                node.properties.forEach(function(prop) {\n                    modified(prop.value);\n                });\n            } else if (node instanceof AST_PropAccess) {\n                modified(node.expression);\n            } else if (node instanceof AST_SymbolRef) {\n                node.definition().references.forEach(function(ref) {\n                    delete ref._eval;\n                });\n            }\n        }\n        def(AST_Statement, function() {\n            throw new Error(string_template(\"Cannot evaluate a statement [{start}]\", this));\n        });\n        def(AST_Accessor, return_this);\n        def(AST_BigInt, return_this);\n        def(AST_Class, return_this);\n        def(AST_Node, return_this);\n        def(AST_Constant, function() {\n            return this.value;\n        });\n        def(AST_Assign, function(compressor, ignore_side_effects, cached, depth) {\n            var lhs = this.left;\n            if (!ignore_side_effects) {\n                if (!(lhs instanceof AST_SymbolRef)) return this;\n                if (!HOP(lhs, \"_eval\")) {\n                    if (!lhs.fixed) return this;\n                    var def = lhs.definition();\n                    if (!def.fixed) return this;\n                    if (def.undeclared) return this;\n                    if (def.last_ref !== lhs) return this;\n                    if (def.single_use == \"m\") return this;\n                    if (this.right.has_side_effects(compressor)) return this;\n                }\n            }\n            var op = this.operator;\n            var node;\n            if (!HOP(lhs, \"_eval\") && lhs instanceof AST_SymbolRef && lhs.fixed && lhs.definition().fixed) {\n                node = lhs;\n            } else if (op == \"=\") {\n                node = this.right;\n            } else {\n                node = make_node(AST_Binary, this, {\n                    operator: op.slice(0, -1),\n                    left: lhs,\n                    right: this.right,\n                });\n            }\n            lhs.walk(scan_modified);\n            var value = node._eval(compressor, ignore_side_effects, cached, depth);\n            if (typeof value == \"object\") return this;\n            modified(lhs);\n            return value;\n        });\n        def(AST_Sequence, function(compressor, ignore_side_effects, cached, depth) {\n            if (!ignore_side_effects) return this;\n            var exprs = this.expressions;\n            for (var i = 0, last = exprs.length - 1; i < last; i++) {\n                exprs[i].walk(scan_modified);\n            }\n            var tail = exprs[last];\n            var value = tail._eval(compressor, ignore_side_effects, cached, depth);\n            return value === tail ? this : value;\n        });\n        def(AST_Lambda, function(compressor) {\n            if (compressor.option(\"unsafe\")) {\n                var fn = function() {};\n                fn.node = this;\n                fn.toString = function() {\n                    return \"function(){}\";\n                };\n                return fn;\n            }\n            return this;\n        });\n        def(AST_Array, function(compressor, ignore_side_effects, cached, depth) {\n            if (compressor.option(\"unsafe\")) {\n                var elements = [];\n                for (var i = 0; i < this.elements.length; i++) {\n                    var element = this.elements[i];\n                    if (element instanceof AST_Hole) return this;\n                    var value = element._eval(compressor, ignore_side_effects, cached, depth);\n                    if (element === value) return this;\n                    elements.push(value);\n                }\n                return elements;\n            }\n            return this;\n        });\n        def(AST_Object, function(compressor, ignore_side_effects, cached, depth) {\n            if (compressor.option(\"unsafe\")) {\n                var val = {};\n                for (var i = 0; i < this.properties.length; i++) {\n                    var prop = this.properties[i];\n                    if (!(prop instanceof AST_ObjectKeyVal)) return this;\n                    var key = prop.key;\n                    if (key instanceof AST_Node) {\n                        key = key._eval(compressor, ignore_side_effects, cached, depth);\n                        if (key === prop.key) return this;\n                    }\n                    switch (key) {\n                      case \"__proto__\":\n                      case \"toString\":\n                      case \"valueOf\":\n                        return this;\n                    }\n                    val[key] = prop.value._eval(compressor, ignore_side_effects, cached, depth);\n                    if (val[key] === prop.value) return this;\n                }\n                return val;\n            }\n            return this;\n        });\n        var non_converting_unary = makePredicate(\"! typeof void\");\n        def(AST_UnaryPrefix, function(compressor, ignore_side_effects, cached, depth) {\n            var e = this.expression;\n            var op = this.operator;\n            // Function would be evaluated to an array and so typeof would\n            // incorrectly return \"object\". Hence making is a special case.\n            if (compressor.option(\"typeofs\")\n                && op == \"typeof\"\n                && (e instanceof AST_Lambda\n                    || e instanceof AST_SymbolRef\n                        && e.fixed_value() instanceof AST_Lambda)) {\n                return typeof function(){};\n            }\n            var def = e instanceof AST_SymbolRef && e.definition();\n            if (!non_converting_unary[op] && !(def && def.fixed)) depth++;\n            e.walk(scan_modified);\n            var v = e._eval(compressor, ignore_side_effects, cached, depth);\n            if (v === e) {\n                if (ignore_side_effects && op == \"void\") return;\n                return this;\n            }\n            switch (op) {\n              case \"!\": return !v;\n              case \"typeof\":\n                // typeof <RegExp> returns \"object\" or \"function\" on different platforms\n                // so cannot evaluate reliably\n                if (v instanceof RegExp) return this;\n                return typeof v;\n              case \"void\": return;\n              case \"~\": return ~v;\n              case \"-\": return -v;\n              case \"+\": return +v;\n              case \"++\":\n              case \"--\":\n                if (!def) return this;\n                if (!ignore_side_effects) {\n                    if (def.undeclared) return this;\n                    if (def.last_ref !== e) return this;\n                }\n                if (HOP(e, \"_eval\")) v = +(op[0] + 1) + +v;\n                modified(e);\n                return v;\n            }\n            return this;\n        });\n        def(AST_UnaryPostfix, function(compressor, ignore_side_effects, cached, depth) {\n            var e = this.expression;\n            if (!(e instanceof AST_SymbolRef)) {\n                if (!ignore_side_effects) return this;\n            } else if (!HOP(e, \"_eval\")) {\n                if (!e.fixed) return this;\n                if (!ignore_side_effects) {\n                    var def = e.definition();\n                    if (!def.fixed) return this;\n                    if (def.undeclared) return this;\n                    if (def.last_ref !== e) return this;\n                }\n            }\n            if (!(e instanceof AST_SymbolRef && e.definition().fixed)) depth++;\n            e.walk(scan_modified);\n            var v = e._eval(compressor, ignore_side_effects, cached, depth);\n            if (v === e) return this;\n            modified(e);\n            return +v;\n        });\n        var non_converting_binary = makePredicate(\"&& || === !==\");\n        def(AST_Binary, function(compressor, ignore_side_effects, cached, depth) {\n            if (!non_converting_binary[this.operator]) depth++;\n            var left = this.left._eval(compressor, ignore_side_effects, cached, depth);\n            if (left === this.left) return this;\n            if (this.operator == (left ? \"||\" : \"&&\")) return left;\n            var rhs_ignore_side_effects = ignore_side_effects && !(left && typeof left == \"object\");\n            var right = this.right._eval(compressor, rhs_ignore_side_effects, cached, depth);\n            if (right === this.right) return this;\n            var result;\n            switch (this.operator) {\n              case \"&&\" : result = left &&  right; break;\n              case \"||\" : result = left ||  right; break;\n              case \"??\" :\n                result = left == null ? right : left;\n                break;\n              case \"|\"  : result = left |   right; break;\n              case \"&\"  : result = left &   right; break;\n              case \"^\"  : result = left ^   right; break;\n              case \"+\"  : result = left +   right; break;\n              case \"-\"  : result = left -   right; break;\n              case \"*\"  : result = left *   right; break;\n              case \"/\"  : result = left /   right; break;\n              case \"%\"  : result = left %   right; break;\n              case \"<<\" : result = left <<  right; break;\n              case \">>\" : result = left >>  right; break;\n              case \">>>\": result = left >>> right; break;\n              case \"==\" : result = left ==  right; break;\n              case \"===\": result = left === right; break;\n              case \"!=\" : result = left !=  right; break;\n              case \"!==\": result = left !== right; break;\n              case \"<\"  : result = left <   right; break;\n              case \"<=\" : result = left <=  right; break;\n              case \">\"  : result = left >   right; break;\n              case \">=\" : result = left >=  right; break;\n              case \"**\":\n                result = Math.pow(left, right);\n                break;\n              case \"in\":\n                if (right && typeof right == \"object\" && HOP(right, left)) {\n                    result = true;\n                    break;\n                }\n              default:\n                return this;\n            }\n            if (isNaN(result)) return compressor.find_parent(AST_With) ? this : result;\n            if (compressor.option(\"unsafe_math\")\n                && !ignore_side_effects\n                && result\n                && typeof result == \"number\"\n                && (this.operator == \"+\" || this.operator == \"-\")) {\n                var digits = Math.max(0, decimals(left), decimals(right));\n                // 53-bit significand ---> 15.95 decimal places\n                if (digits < 16) return +result.toFixed(digits);\n            }\n            return result;\n\n            function decimals(operand) {\n                var match = /(\\.[0-9]*)?(e[^e]+)?$/.exec(+operand);\n                return (match[1] || \".\").length - 1 - (match[2] || \"\").slice(1);\n            }\n        });\n        def(AST_Conditional, function(compressor, ignore_side_effects, cached, depth) {\n            var condition = this.condition._eval(compressor, ignore_side_effects, cached, depth);\n            if (condition === this.condition) return this;\n            var node = condition ? this.consequent : this.alternative;\n            var value = node._eval(compressor, ignore_side_effects, cached, depth);\n            return value === node ? this : value;\n        });\n        function verify_escaped(ref, depth) {\n            var escaped = ref.definition().escaped;\n            switch (escaped.length) {\n              case 0:\n                return true;\n              case 1:\n                var found = false;\n                escaped[0].walk(new TreeWalker(function(node) {\n                    if (found) return true;\n                    if (node === ref) return found = true;\n                    if (node instanceof AST_Scope) return true;\n                }));\n                return found;\n              default:\n                return depth <= escaped.depth;\n            }\n        }\n        def(AST_SymbolRef, function(compressor, ignore_side_effects, cached, depth) {\n            this._eval = return_this;\n            try {\n                var fixed = this.fixed_value();\n                if (!fixed) return this;\n                var value;\n                if (HOP(fixed, \"_eval\")) {\n                    value = fixed._eval();\n                } else {\n                    value = fixed._eval(compressor, ignore_side_effects, cached, depth);\n                    if (value === fixed) return this;\n                    fixed._eval = function() {\n                        return value;\n                    };\n                    cached.push(fixed);\n                }\n                return value && typeof value == \"object\" && !verify_escaped(this, depth) ? this : value;\n            } finally {\n                delete this._eval;\n            }\n        });\n        var global_objs = {\n            Array: Array,\n            Math: Math,\n            Number: Number,\n            Object: Object,\n            String: String,\n        };\n        var static_values = convert_to_predicate({\n            Math: [\n                \"E\",\n                \"LN10\",\n                \"LN2\",\n                \"LOG2E\",\n                \"LOG10E\",\n                \"PI\",\n                \"SQRT1_2\",\n                \"SQRT2\",\n            ],\n            Number: [\n                \"MAX_VALUE\",\n                \"MIN_VALUE\",\n                \"NaN\",\n                \"NEGATIVE_INFINITY\",\n                \"POSITIVE_INFINITY\",\n            ],\n        });\n        var regexp_props = makePredicate(\"global ignoreCase multiline source\");\n        def(AST_PropAccess, function(compressor, ignore_side_effects, cached, depth) {\n            if (compressor.option(\"unsafe\")) {\n                var val;\n                var exp = this.expression;\n                if (!is_undeclared_ref(exp)) {\n                    val = exp._eval(compressor, ignore_side_effects, cached, depth + 1);\n                    if (val == null || val === exp) return this;\n                }\n                var key = this.property;\n                if (key instanceof AST_Node) {\n                    key = key._eval(compressor, ignore_side_effects, cached, depth);\n                    if (key === this.property) return this;\n                }\n                if (val === undefined) {\n                    var static_value = static_values[exp.name];\n                    if (!static_value || !static_value[key]) return this;\n                    val = global_objs[exp.name];\n                } else if (val instanceof RegExp) {\n                    if (!regexp_props[key]) return this;\n                } else if (typeof val == \"object\") {\n                    if (!HOP(val, key)) return this;\n                } else if (typeof val == \"function\") switch (key) {\n                  case \"name\":\n                    return val.node.name ? val.node.name.name : \"\";\n                  case \"length\":\n                    return val.node.length();\n                  default:\n                    return this;\n                }\n                return val[key];\n            }\n            return this;\n        });\n        function eval_all(nodes, compressor, ignore_side_effects, cached, depth) {\n            var values = [];\n            for (var i = 0; i < nodes.length; i++) {\n                var node = nodes[i];\n                var value = node._eval(compressor, ignore_side_effects, cached, depth);\n                if (node === value) return;\n                values.push(value);\n            }\n            return values;\n        }\n        def(AST_Call, function(compressor, ignore_side_effects, cached, depth) {\n            var exp = this.expression;\n            var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp;\n            if (fn instanceof AST_Arrow || fn instanceof AST_Defun || fn instanceof AST_Function) {\n                if (fn.evaluating) return this;\n                if (fn.name && fn.name.definition().recursive_refs > 0) return this;\n                if (this.is_expr_pure(compressor)) return this;\n                var args = eval_all(this.args, compressor, ignore_side_effects, cached, depth);\n                if (!all(fn.argnames, function(sym, index) {\n                    if (sym instanceof AST_DefaultValue) {\n                        if (!args) return false;\n                        if (args[index] === undefined) {\n                            var value = sym.value._eval(compressor, ignore_side_effects, cached, depth);\n                            if (value === sym.value) return false;\n                            args[index] = value;\n                        }\n                        sym = sym.name;\n                    }\n                    return !(sym instanceof AST_Destructured);\n                })) return this;\n                if (fn.rest instanceof AST_Destructured) return this;\n                if (!args && !ignore_side_effects) return this;\n                var stat = fn.first_statement();\n                if (!(stat instanceof AST_Return)) {\n                    if (ignore_side_effects) {\n                        fn.walk(scan_modified);\n                        var found = false;\n                        fn.evaluating = true;\n                        walk_body(fn, new TreeWalker(function(node) {\n                            if (found) return true;\n                            if (node instanceof AST_Return) {\n                                if (node.value && node.value._eval(compressor, true, cached, depth) !== undefined) {\n                                    found = true;\n                                }\n                                return true;\n                            }\n                            if (node instanceof AST_Scope && node !== fn) return true;\n                        }));\n                        fn.evaluating = false;\n                        if (!found) return;\n                    }\n                    return this;\n                }\n                var val = stat.value;\n                if (!val) return;\n                var cached_args = [];\n                if (!args || all(fn.argnames, function(sym, i) {\n                    return assign(sym, args[i]);\n                }) && !(fn.rest && !assign(fn.rest, args.slice(fn.argnames.length))) || ignore_side_effects) {\n                    if (ignore_side_effects) fn.argnames.forEach(function(sym) {\n                        if (sym instanceof AST_DefaultValue) sym.value.walk(scan_modified);\n                    });\n                    fn.evaluating = true;\n                    val = val._eval(compressor, ignore_side_effects, cached, depth);\n                    fn.evaluating = false;\n                }\n                cached_args.forEach(function(node) {\n                    delete node._eval;\n                });\n                return val === stat.value ? this : val;\n            } else if (compressor.option(\"unsafe\") && exp instanceof AST_PropAccess) {\n                var key = exp.property;\n                if (key instanceof AST_Node) {\n                    key = key._eval(compressor, ignore_side_effects, cached, depth);\n                    if (key === exp.property) return this;\n                }\n                var val;\n                var e = exp.expression;\n                if (is_undeclared_ref(e)) {\n                    var static_fn = static_fns[e.name];\n                    if (!static_fn || !static_fn[key]) return this;\n                    val = global_objs[e.name];\n                } else {\n                    val = e._eval(compressor, ignore_side_effects, cached, depth + 1);\n                    if (val == null || val === e) return this;\n                    var native_fn = native_fns[val.constructor.name];\n                    if (!native_fn || !native_fn[key]) return this;\n                    if (val instanceof RegExp && val.global && !(e instanceof AST_RegExp)) return this;\n                }\n                var args = eval_all(this.args, compressor, ignore_side_effects, cached, depth);\n                if (!args) return this;\n                if (key == \"replace\" && typeof args[1] == \"function\") return this;\n                try {\n                    return val[key].apply(val, args);\n                } catch (ex) {\n                    AST_Node.warn(\"Error evaluating {this} [{start}]\", this);\n                } finally {\n                    if (val instanceof RegExp) val.lastIndex = 0;\n                }\n            }\n            return this;\n\n            function assign(sym, arg) {\n                if (sym instanceof AST_DefaultValue) sym = sym.name;\n                var def = sym.definition();\n                if (def.orig[def.orig.length - 1] !== sym) return false;\n                var value = arg;\n                def.references.forEach(function(node) {\n                    node._eval = function() {\n                        return value;\n                    };\n                    cached_args.push(node);\n                });\n                return true;\n            }\n        });\n        def(AST_New, return_this);\n        def(AST_Template, function(compressor, ignore_side_effects, cached, depth) {\n            if (!compressor.option(\"templates\")) return this;\n            if (this.tag) {\n                if (!is_raw_tag(compressor, this.tag)) return this;\n                decode = function(str) {\n                    return str;\n                };\n            }\n            var exprs = eval_all(this.expressions, compressor, ignore_side_effects, cached, depth);\n            if (!exprs) return this;\n            var malformed = false;\n            var ret = decode(this.strings[0]);\n            for (var i = 0; i < exprs.length; i++) {\n                ret += exprs[i] + decode(this.strings[i + 1]);\n            }\n            if (!malformed) return ret;\n            this._eval = return_this;\n            return this;\n\n            function decode(str) {\n                str = decode_template(str);\n                if (typeof str != \"string\") malformed = true;\n                return str;\n            }\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"_eval\", func);\n    });\n\n    // method to negate an expression\n    (function(def) {\n        function basic_negation(exp) {\n            return make_node(AST_UnaryPrefix, exp, {\n                operator: \"!\",\n                expression: exp,\n            });\n        }\n        function best(orig, alt, first_in_statement) {\n            var negated = basic_negation(orig);\n            if (first_in_statement) return best_of_expression(negated, make_node(AST_SimpleStatement, alt, {\n                body: alt,\n            })) === negated ? negated : alt;\n            return best_of_expression(negated, alt);\n        }\n        def(AST_Node, function() {\n            return basic_negation(this);\n        });\n        def(AST_Statement, function() {\n            throw new Error(\"Cannot negate a statement\");\n        });\n        def(AST_Binary, function(compressor, first_in_statement) {\n            var self = this.clone(), op = this.operator;\n            if (compressor.option(\"unsafe_comps\")) {\n                switch (op) {\n                  case \"<=\" : self.operator = \">\"  ; return self;\n                  case \"<\"  : self.operator = \">=\" ; return self;\n                  case \">=\" : self.operator = \"<\"  ; return self;\n                  case \">\"  : self.operator = \"<=\" ; return self;\n                }\n            }\n            switch (op) {\n              case \"==\" : self.operator = \"!=\"; return self;\n              case \"!=\" : self.operator = \"==\"; return self;\n              case \"===\": self.operator = \"!==\"; return self;\n              case \"!==\": self.operator = \"===\"; return self;\n              case \"&&\":\n                self.operator = \"||\";\n                self.left = self.left.negate(compressor, first_in_statement);\n                self.right = self.right.negate(compressor);\n                return best(this, self, first_in_statement);\n              case \"||\":\n                self.operator = \"&&\";\n                self.left = self.left.negate(compressor, first_in_statement);\n                self.right = self.right.negate(compressor);\n                return best(this, self, first_in_statement);\n            }\n            return basic_negation(this);\n        });\n        def(AST_ClassExpression, function() {\n            return basic_negation(this);\n        });\n        def(AST_Conditional, function(compressor, first_in_statement) {\n            var self = this.clone();\n            self.consequent = self.consequent.negate(compressor);\n            self.alternative = self.alternative.negate(compressor);\n            return best(this, self, first_in_statement);\n        });\n        def(AST_LambdaExpression, function() {\n            return basic_negation(this);\n        });\n        def(AST_Sequence, function(compressor) {\n            var expressions = this.expressions.slice();\n            expressions.push(expressions.pop().negate(compressor));\n            return make_sequence(this, expressions);\n        });\n        def(AST_UnaryPrefix, function() {\n            if (this.operator == \"!\")\n                return this.expression;\n            return basic_negation(this);\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"negate\", function(compressor, first_in_statement) {\n            return func.call(this, compressor, first_in_statement);\n        });\n    });\n\n    var global_pure_fns = makePredicate(\"Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError\");\n    var global_pure_constructors = makePredicate(\"Map Set WeakMap WeakSet\");\n    AST_Call.DEFMETHOD(\"is_expr_pure\", function(compressor) {\n        if (compressor.option(\"unsafe\")) {\n            var expr = this.expression;\n            if (is_undeclared_ref(expr)) {\n                if (global_pure_fns[expr.name]) return true;\n                if (this instanceof AST_New && global_pure_constructors[expr.name]) return true;\n            }\n            if (is_static_fn(expr)) return true;\n        }\n        return compressor.option(\"annotations\") && this.pure || !compressor.pure_funcs(this);\n    });\n    AST_Template.DEFMETHOD(\"is_expr_pure\", function(compressor) {\n        var tag = this.tag;\n        if (!tag) return true;\n        if (compressor.option(\"unsafe\")) {\n            if (is_undeclared_ref(tag) && global_pure_fns[tag.name]) return true;\n            if (tag instanceof AST_Dot && is_undeclared_ref(tag.expression)) {\n                var static_fn = static_fns[tag.expression.name];\n                return static_fn && (static_fn[tag.property]\n                    || tag.expression.name == \"Math\" && tag.property == \"random\");\n            }\n        }\n        return !compressor.pure_funcs(this);\n    });\n    AST_Node.DEFMETHOD(\"is_call_pure\", return_false);\n    AST_Call.DEFMETHOD(\"is_call_pure\", function(compressor) {\n        if (!compressor.option(\"unsafe\")) return false;\n        var dot = this.expression;\n        if (!(dot instanceof AST_Dot)) return false;\n        var exp = dot.expression;\n        var map;\n        var prop = dot.property;\n        if (exp instanceof AST_Array) {\n            map = native_fns.Array;\n        } else if (exp.is_boolean(compressor)) {\n            map = native_fns.Boolean;\n        } else if (exp.is_number(compressor)) {\n            map = native_fns.Number;\n        } else if (exp instanceof AST_RegExp) {\n            map = native_fns.RegExp;\n        } else if (exp.is_string(compressor)) {\n            map = native_fns.String;\n            if (prop == \"replace\") {\n                var arg = this.args[1];\n                if (arg && !arg.is_string(compressor)) return false;\n            }\n        } else if (!dot.may_throw_on_access(compressor)) {\n            map = native_fns.Object;\n        }\n        return map && map[prop];\n    });\n\n    // determine if object spread syntax may cause runtime exception\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Array, return_true);\n        def(AST_Assign, function() {\n            switch (this.operator) {\n              case \"=\":\n                return this.right.safe_to_spread();\n              case \"&&=\":\n              case \"||=\":\n              case \"??=\":\n                return this.left.safe_to_spread() && this.right.safe_to_spread();\n            }\n            return true;\n        });\n        def(AST_Binary, function() {\n            return !lazy_op[this.operator] || this.left.safe_to_spread() && this.right.safe_to_spread();\n        });\n        def(AST_Constant, return_true);\n        def(AST_Lambda, return_true);\n        def(AST_Object, function() {\n            return all(this.properties, function(prop) {\n                return !(prop instanceof AST_ObjectGetter || prop instanceof AST_Spread);\n            });\n        });\n        def(AST_Sequence, function() {\n            return this.tail_node().safe_to_spread();\n        });\n        def(AST_SymbolRef, function() {\n            var fixed = this.fixed_value();\n            return fixed && fixed.safe_to_spread();\n        });\n        def(AST_Unary, return_true);\n    })(function(node, func) {\n        node.DEFMETHOD(\"safe_to_spread\", func);\n    });\n\n    // determine if expression has side effects\n    (function(def) {\n        function any(list, compressor, spread) {\n            return !all(list, spread ? function(node) {\n                return node instanceof AST_Spread ? !spread(node, compressor) : !node.has_side_effects(compressor);\n            } : function(node) {\n                return !node.has_side_effects(compressor);\n            });\n        }\n        function array_spread(node, compressor) {\n            var exp = node.expression;\n            return !exp.is_string(compressor) || exp.has_side_effects(compressor);\n        }\n        def(AST_Node, return_true);\n        def(AST_Array, function(compressor) {\n            return any(this.elements, compressor, array_spread);\n        });\n        def(AST_Assign, function(compressor) {\n            var lhs = this.left;\n            if (!(lhs instanceof AST_PropAccess)) return true;\n            var node = lhs.expression;\n            return !(node instanceof AST_ObjectIdentity)\n                || !node.scope.resolve().new\n                || lhs instanceof AST_Sub && lhs.property.has_side_effects(compressor)\n                || this.right.has_side_effects(compressor);\n        });\n        def(AST_Binary, function(compressor) {\n            return this.left.has_side_effects(compressor)\n                || this.right.has_side_effects(compressor)\n                || !can_drop_op(this, compressor);\n        });\n        def(AST_Block, function(compressor) {\n            return any(this.body, compressor);\n        });\n        def(AST_Call, function(compressor) {\n            if (!this.is_expr_pure(compressor)\n                && (!this.is_call_pure(compressor) || this.expression.has_side_effects(compressor))) {\n                return true;\n            }\n            return any(this.args, compressor, array_spread);\n        });\n        def(AST_Case, function(compressor) {\n            return this.expression.has_side_effects(compressor)\n                || any(this.body, compressor);\n        });\n        def(AST_Class, function(compressor) {\n            var base = this.extends;\n            if (base) {\n                if (base instanceof AST_SymbolRef) base = base.fixed_value();\n                if (!safe_for_extends(base)) return true;\n            }\n            return any(this.properties, compressor);\n        });\n        def(AST_ClassProperty, function(compressor) {\n            return this.key instanceof AST_Node && this.key.has_side_effects(compressor)\n                || this.static && this.value && this.value.has_side_effects(compressor);\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.condition.has_side_effects(compressor)\n                || this.consequent.has_side_effects(compressor)\n                || this.alternative.has_side_effects(compressor);\n        });\n        def(AST_Constant, return_false);\n        def(AST_Definitions, function(compressor) {\n            return any(this.definitions, compressor);\n        });\n        def(AST_DestructuredArray, function(compressor) {\n            return any(this.elements, compressor);\n        });\n        def(AST_DestructuredKeyVal, function(compressor) {\n            return this.key instanceof AST_Node && this.key.has_side_effects(compressor)\n                || this.value.has_side_effects(compressor);\n        });\n        def(AST_DestructuredObject, function(compressor) {\n            return any(this.properties, compressor);\n        });\n        def(AST_Dot, function(compressor) {\n            return this.expression.may_throw_on_access(compressor)\n                || this.expression.has_side_effects(compressor);\n        });\n        def(AST_EmptyStatement, return_false);\n        def(AST_If, function(compressor) {\n            return this.condition.has_side_effects(compressor)\n                || this.body && this.body.has_side_effects(compressor)\n                || this.alternative && this.alternative.has_side_effects(compressor);\n        });\n        def(AST_LabeledStatement, function(compressor) {\n            return this.body.has_side_effects(compressor);\n        });\n        def(AST_Lambda, return_false);\n        def(AST_Object, function(compressor) {\n            return any(this.properties, compressor, function(node, compressor) {\n                var exp = node.expression;\n                return !exp.safe_to_spread() || exp.has_side_effects(compressor);\n            });\n        });\n        def(AST_ObjectIdentity, return_false);\n        def(AST_ObjectProperty, function(compressor) {\n            return this.key instanceof AST_Node && this.key.has_side_effects(compressor)\n                || this.value.has_side_effects(compressor);\n        });\n        def(AST_Sequence, function(compressor) {\n            return any(this.expressions, compressor);\n        });\n        def(AST_SimpleStatement, function(compressor) {\n            return this.body.has_side_effects(compressor);\n        });\n        def(AST_Sub, function(compressor) {\n            return this.expression.may_throw_on_access(compressor)\n                || this.expression.has_side_effects(compressor)\n                || this.property.has_side_effects(compressor);\n        });\n        def(AST_Switch, function(compressor) {\n            return this.expression.has_side_effects(compressor)\n                || any(this.body, compressor);\n        });\n        def(AST_SymbolDeclaration, return_false);\n        def(AST_SymbolRef, function(compressor) {\n            return !this.is_declared(compressor) || !can_drop_symbol(this, compressor);\n        });\n        def(AST_Template, function(compressor) {\n            return !this.is_expr_pure(compressor) || any(this.expressions, compressor);\n        });\n        def(AST_Try, function(compressor) {\n            return any(this.body, compressor)\n                || this.bcatch && this.bcatch.has_side_effects(compressor)\n                || this.bfinally && this.bfinally.has_side_effects(compressor);\n        });\n        def(AST_Unary, function(compressor) {\n            return unary_side_effects[this.operator]\n                || this.expression.has_side_effects(compressor);\n        });\n        def(AST_VarDef, function() {\n            return this.value;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"has_side_effects\", func);\n    });\n\n    // determine if expression may throw\n    (function(def) {\n        def(AST_Node, return_true);\n\n        def(AST_Constant, return_false);\n        def(AST_EmptyStatement, return_false);\n        def(AST_Lambda, return_false);\n        def(AST_ObjectIdentity, return_false);\n        def(AST_SymbolDeclaration, return_false);\n\n        function any(list, compressor) {\n            for (var i = list.length; --i >= 0;)\n                if (list[i].may_throw(compressor))\n                    return true;\n            return false;\n        }\n\n        function call_may_throw(exp, compressor) {\n            if (exp.may_throw(compressor)) return true;\n            if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();\n            if (!(exp instanceof AST_Lambda)) return true;\n            if (any(exp.argnames, compressor)) return true;\n            if (any(exp.body, compressor)) return true;\n            return is_arrow(exp) && exp.value && exp.value.may_throw(compressor);\n        }\n\n        def(AST_Array, function(compressor) {\n            return any(this.elements, compressor);\n        });\n        def(AST_Assign, function(compressor) {\n            if (this.right.may_throw(compressor)) return true;\n            if (!compressor.has_directive(\"use strict\")\n                && this.operator == \"=\"\n                && this.left instanceof AST_SymbolRef) {\n                return false;\n            }\n            return this.left.may_throw(compressor);\n        });\n        def(AST_Await, function(compressor) {\n            return this.expression.may_throw(compressor);\n        });\n        def(AST_Binary, function(compressor) {\n            return this.left.may_throw(compressor)\n                || this.right.may_throw(compressor)\n                || !can_drop_op(this, compressor);\n        });\n        def(AST_Block, function(compressor) {\n            return any(this.body, compressor);\n        });\n        def(AST_Call, function(compressor) {\n            if (any(this.args, compressor)) return true;\n            if (this.is_expr_pure(compressor)) return false;\n            this.may_throw = return_true;\n            var ret = call_may_throw(this.expression, compressor);\n            delete this.may_throw;\n            return ret;\n        });\n        def(AST_Case, function(compressor) {\n            return this.expression.may_throw(compressor)\n                || any(this.body, compressor);\n        });\n        def(AST_Conditional, function(compressor) {\n            return this.condition.may_throw(compressor)\n                || this.consequent.may_throw(compressor)\n                || this.alternative.may_throw(compressor);\n        });\n        def(AST_DefaultValue, function(compressor) {\n            return this.name.may_throw(compressor)\n                || this.value && this.value.may_throw(compressor);\n        });\n        def(AST_Definitions, function(compressor) {\n            return any(this.definitions, compressor);\n        });\n        def(AST_Dot, function(compressor) {\n            return !this.optional && this.expression.may_throw_on_access(compressor)\n                || this.expression.may_throw(compressor);\n        });\n        def(AST_ForEnumeration, function(compressor) {\n            if (this.init.may_throw(compressor)) return true;\n            var obj = this.object;\n            if (obj.may_throw(compressor)) return true;\n            obj = obj.tail_node();\n            if (!(obj instanceof AST_Array || obj.is_string(compressor))) return true;\n            return this.body.may_throw(compressor);\n        });\n        def(AST_If, function(compressor) {\n            return this.condition.may_throw(compressor)\n                || this.body && this.body.may_throw(compressor)\n                || this.alternative && this.alternative.may_throw(compressor);\n        });\n        def(AST_LabeledStatement, function(compressor) {\n            return this.body.may_throw(compressor);\n        });\n        def(AST_Object, function(compressor) {\n            return any(this.properties, compressor);\n        });\n        def(AST_ObjectProperty, function(compressor) {\n            return this.value.may_throw(compressor)\n                || this.key instanceof AST_Node && this.key.may_throw(compressor);\n        });\n        def(AST_Return, function(compressor) {\n            return this.value && this.value.may_throw(compressor);\n        });\n        def(AST_Sequence, function(compressor) {\n            return any(this.expressions, compressor);\n        });\n        def(AST_SimpleStatement, function(compressor) {\n            return this.body.may_throw(compressor);\n        });\n        def(AST_Sub, function(compressor) {\n            return !this.optional && this.expression.may_throw_on_access(compressor)\n                || this.expression.may_throw(compressor)\n                || this.property.may_throw(compressor);\n        });\n        def(AST_Switch, function(compressor) {\n            return this.expression.may_throw(compressor)\n                || any(this.body, compressor);\n        });\n        def(AST_SymbolRef, function(compressor) {\n            return !this.is_declared(compressor) || !can_drop_symbol(this, compressor);\n        });\n        def(AST_Template, function(compressor) {\n            if (any(this.expressions, compressor)) return true;\n            if (this.is_expr_pure(compressor)) return false;\n            if (!this.tag) return false;\n            this.may_throw = return_true;\n            var ret = call_may_throw(this.tag, compressor);\n            delete this.may_throw;\n            return ret;\n        });\n        def(AST_Try, function(compressor) {\n            return (this.bcatch ? this.bcatch.may_throw(compressor) : any(this.body, compressor))\n                || this.bfinally && this.bfinally.may_throw(compressor);\n        });\n        def(AST_Unary, function(compressor) {\n            return this.expression.may_throw(compressor)\n                && !(this.operator == \"typeof\" && this.expression instanceof AST_SymbolRef);\n        });\n        def(AST_VarDef, function(compressor) {\n            return this.name.may_throw(compressor)\n                || this.value && this.value.may_throw(compressor);\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"may_throw\", func);\n    });\n\n    // determine if expression is constant\n    (function(def) {\n        function all_constant(list, scope) {\n            for (var i = list.length; --i >= 0;)\n                if (!list[i].is_constant_expression(scope))\n                    return false;\n            return true;\n        }\n\n        function walk_scoped(self, scope) {\n            var result = true;\n            var scopes = [];\n            self.walk(new TreeWalker(function(node, descend) {\n                if (!result) return true;\n                if (node instanceof AST_BlockScope) {\n                    if (node === self) return;\n                    scopes.push(node);\n                    descend();\n                    scopes.pop();\n                    return true;\n                }\n                if (node instanceof AST_SymbolRef) {\n                    if (self.inlined || node.redef || node.in_arg) {\n                        result = false;\n                        return true;\n                    }\n                    if (self.variables && self.variables.has(node.name)) return true;\n                    var def = node.definition();\n                    if (member(def.scope, scopes)) return true;\n                    if (scope && !def.redefined()) {\n                        var scope_def = scope.find_variable(node.name);\n                        if (scope_def ? scope_def === def : def.undeclared) {\n                            result = \"f\";\n                            return true;\n                        }\n                    }\n                    result = false;\n                    return true;\n                }\n                if (node instanceof AST_ObjectIdentity) {\n                    if (is_arrow(self) && all(scopes, function(s) {\n                        return !(s instanceof AST_Scope) || is_arrow(s);\n                    })) result = false;\n                    return true;\n                }\n            }));\n            return result;\n        }\n\n        def(AST_Node, return_false);\n        def(AST_Array, function(scope) {\n            return all_constant(this.elements, scope);\n        });\n        def(AST_Binary, function(scope) {\n            return this.left.is_constant_expression(scope)\n                && this.right.is_constant_expression(scope)\n                && can_drop_op(this);\n        });\n        def(AST_Class, function(scope) {\n            var base = this.extends;\n            if (base && !safe_for_extends(base)) return false;\n            return all_constant(this.properties, scope);\n        });\n        def(AST_ClassProperty, function(scope) {\n            if (typeof this.key != \"string\") return false;\n            var value = this.value;\n            if (!value) return true;\n            return this.static ? value.is_constant_expression(scope) : walk_scoped(value, scope);\n        });\n        def(AST_Constant, return_true);\n        def(AST_Lambda, function(scope) {\n            return walk_scoped(this, scope);\n        });\n        def(AST_Object, function(scope) {\n            return all_constant(this.properties, scope);\n        });\n        def(AST_ObjectIdentity, function(scope) {\n            return this.scope.resolve() === scope;\n        });\n        def(AST_ObjectProperty, function(scope) {\n            return typeof this.key == \"string\" && this.value.is_constant_expression(scope);\n        });\n        def(AST_Unary, function(scope) {\n            return this.expression.is_constant_expression(scope);\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"is_constant_expression\", func);\n    });\n\n    // tell me if a statement aborts\n    function aborts(thing) {\n        return thing && thing.aborts();\n    }\n    (function(def) {\n        def(AST_Statement, return_null);\n        def(AST_Jump, return_this);\n        function block_aborts() {\n            var n = this.body.length;\n            return n > 0 && aborts(this.body[n - 1]);\n        }\n        def(AST_BlockStatement, block_aborts);\n        def(AST_SwitchBranch, block_aborts);\n        def(AST_If, function() {\n            return this.alternative && aborts(this.body) && aborts(this.alternative) && this;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"aborts\", func);\n    });\n\n    /* -----[ optimizers ]----- */\n\n    var directives = makePredicate([\"use asm\", \"use strict\"]);\n    OPT(AST_Directive, function(self, compressor) {\n        if (compressor.option(\"directives\")\n            && (!directives[self.value] || compressor.has_directive(self.value) !== self)) {\n            return make_node(AST_EmptyStatement, self);\n        }\n        return self;\n    });\n\n    OPT(AST_Debugger, function(self, compressor) {\n        if (compressor.option(\"drop_debugger\"))\n            return make_node(AST_EmptyStatement, self);\n        return self;\n    });\n\n    OPT(AST_LabeledStatement, function(self, compressor) {\n        if (self.body instanceof AST_If || self.body instanceof AST_Break) {\n            var body = tighten_body([ self.body ], compressor);\n            switch (body.length) {\n              case 0:\n                self.body = make_node(AST_EmptyStatement, self);\n                break;\n              case 1:\n                self.body = body[0];\n                break;\n              default:\n                self.body = make_node(AST_BlockStatement, self, { body: body });\n                break;\n            }\n        }\n        return compressor.option(\"unused\") && self.label.references.length == 0 ? self.body : self;\n    });\n\n    OPT(AST_LoopControl, function(self, compressor) {\n        if (!compressor.option(\"dead_code\")) return self;\n        var label = self.label;\n        if (label) {\n            var lct = compressor.loopcontrol_target(self);\n            self.label = null;\n            if (compressor.loopcontrol_target(self) === lct) {\n                remove(label.thedef.references, self);\n            } else {\n                self.label = label;\n            }\n        }\n        return self;\n    });\n\n    OPT(AST_Block, function(self, compressor) {\n        self.body = tighten_body(self.body, compressor);\n        return self;\n    });\n\n    function trim_block(node, parent, in_list) {\n        switch (node.body.length) {\n          case 0:\n            return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n          case 1:\n            var stat = node.body[0];\n            if (!safe_to_trim(stat)) return node;\n            if (parent instanceof AST_IterationStatement && stat instanceof AST_LambdaDefinition) return node;\n            return stat;\n        }\n        return node;\n    }\n\n    OPT(AST_BlockStatement, function(self, compressor) {\n        self.body = tighten_body(self.body, compressor);\n        return trim_block(self, compressor.parent());\n    });\n\n    function drop_rest_farg(fn, compressor) {\n        if (!compressor.option(\"rests\")) return;\n        if (fn.uses_arguments) return;\n        if (!(fn.rest instanceof AST_DestructuredArray)) return;\n        if (!compressor.drop_fargs(fn, compressor.parent())) return;\n        fn.argnames = fn.argnames.concat(fn.rest.elements);\n        fn.rest = fn.rest.rest;\n    }\n\n    OPT(AST_Lambda, function(self, compressor) {\n        drop_rest_farg(self, compressor);\n        self.body = tighten_body(self.body, compressor);\n        return self;\n    });\n\n    OPT(AST_Function, function(self, compressor) {\n        drop_rest_farg(self, compressor);\n        self.body = tighten_body(self.body, compressor);\n        var parent = compressor.parent();\n        if (compressor.option(\"inline\")) for (var i = 0; i < self.body.length; i++) {\n            var stat = self.body[i];\n            if (stat instanceof AST_Directive) continue;\n            if (stat instanceof AST_Return) {\n                if (i != self.body.length - 1) break;\n                var call = stat.value;\n                if (!call || call.TYPE != \"Call\") break;\n                if (call.is_expr_pure(compressor)) break;\n                var exp = call.expression, fn;\n                if (!(exp instanceof AST_SymbolRef)) {\n                    fn = exp;\n                } else if (self.name && self.name.definition() === exp.definition()) {\n                    break;\n                } else {\n                    fn = exp.fixed_value();\n                }\n                if (!(fn instanceof AST_Defun || fn instanceof AST_Function)) break;\n                if (fn.rest) break;\n                if (fn.uses_arguments) break;\n                if (fn === exp) {\n                    if (fn.parent_scope !== self) break;\n                    if (!all(fn.enclosed, function(def) {\n                        return def.scope !== self;\n                    })) break;\n                }\n                if ((fn !== exp || fn.name)\n                    && (parent instanceof AST_ClassMethod || parent instanceof AST_ObjectMethod)\n                    && parent.value === compressor.self()) break;\n                if (fn.contains_this()) break;\n                var len = fn.argnames.length;\n                if (len > 0 && compressor.option(\"inline\") < 2) break;\n                if (len > self.argnames.length) break;\n                if (!all(self.argnames, function(argname) {\n                    return argname instanceof AST_SymbolFunarg;\n                })) break;\n                if (!all(call.args, function(arg) {\n                    return !(arg instanceof AST_Spread);\n                })) break;\n                for (var j = 0; j < len; j++) {\n                    var arg = call.args[j];\n                    if (!(arg instanceof AST_SymbolRef)) break;\n                    if (arg.definition() !== self.argnames[j].definition()) break;\n                }\n                if (j < len) break;\n                for (; j < call.args.length; j++) {\n                    if (call.args[j].has_side_effects(compressor)) break;\n                }\n                if (j < call.args.length) break;\n                if (len < self.argnames.length && !compressor.drop_fargs(self, parent)) {\n                    if (!compressor.drop_fargs(fn, call)) break;\n                    do {\n                        fn.argnames.push(fn.make_var(AST_SymbolFunarg, fn, \"argument_\" + len));\n                    } while (++len < self.argnames.length);\n                }\n                return exp;\n            }\n            break;\n        }\n        return self;\n    });\n\n    var NO_MERGE = makePredicate(\"arguments await yield\");\n    AST_Scope.DEFMETHOD(\"merge_variables\", function(compressor) {\n        if (!compressor.option(\"merge_vars\")) return;\n        var in_arg = [], in_try, root, segment = {}, self = this;\n        var first = [], last = [], index = 0;\n        var declarations = new Dictionary();\n        var references = Object.create(null);\n        var prev = Object.create(null);\n        var tw = new TreeWalker(function(node, descend) {\n            if (node instanceof AST_Assign) {\n                var lhs = node.left;\n                var rhs = node.right;\n                if (lhs instanceof AST_Destructured) {\n                    rhs.walk(tw);\n                    walk_destructured(AST_SymbolRef, mark, lhs);\n                    return true;\n                }\n                if (lazy_op[node.operator.slice(0, -1)]) {\n                    lhs.walk(tw);\n                    push();\n                    rhs.walk(tw);\n                    if (lhs instanceof AST_SymbolRef) mark(lhs);\n                    pop();\n                    return true;\n                }\n                if (lhs instanceof AST_SymbolRef) {\n                    if (node.operator != \"=\") mark(lhs, true);\n                    rhs.walk(tw);\n                    mark(lhs);\n                    return true;\n                }\n                return;\n            }\n            if (node instanceof AST_Binary) {\n                if (!lazy_op[node.operator]) return;\n                walk_cond(node);\n                return true;\n            }\n            if (node instanceof AST_Break) {\n                var target = tw.loopcontrol_target(node);\n                if (!(target instanceof AST_IterationStatement)) insert(target);\n                return true;\n            }\n            if (node instanceof AST_Call) {\n                var exp = node.expression;\n                if (exp instanceof AST_LambdaExpression) {\n                    node.args.forEach(function(arg) {\n                        arg.walk(tw);\n                    });\n                    exp.walk(tw);\n                } else {\n                    descend();\n                    mark_expression(exp);\n                }\n                return true;\n            }\n            if (node instanceof AST_Class) {\n                if (node.name) node.name.walk(tw);\n                if (node.extends) node.extends.walk(tw);\n                node.properties.filter(function(prop) {\n                    if (prop.key instanceof AST_Node) prop.key.walk(tw);\n                    return prop.value;\n                }).forEach(function(prop) {\n                    if (prop.static) {\n                        prop.value.walk(tw);\n                    } else {\n                        push();\n                        segment.block = node;\n                        prop.value.walk(tw);\n                        pop();\n                    }\n                });\n                return true;\n            }\n            if (node instanceof AST_Conditional) {\n                walk_cond(node.condition, node.consequent, node.alternative);\n                return true;\n            }\n            if (node instanceof AST_Continue) {\n                var target = tw.loopcontrol_target(node);\n                if (target instanceof AST_Do) insert(target);\n                return true;\n            }\n            if (node instanceof AST_Do) {\n                push();\n                segment.block = node;\n                segment.loop = true;\n                var save = segment;\n                node.body.walk(tw);\n                if (segment.inserted === node) segment = save;\n                node.condition.walk(tw);\n                pop();\n                return true;\n            }\n            if (node instanceof AST_For) {\n                if (node.init) node.init.walk(tw);\n                push();\n                segment.block = node;\n                segment.loop = true;\n                if (node.condition) node.condition.walk(tw);\n                node.body.walk(tw);\n                if (node.step) node.step.walk(tw);\n                pop();\n                return true;\n            }\n            if (node instanceof AST_ForEnumeration) {\n                node.object.walk(tw);\n                push();\n                segment.block = node;\n                segment.loop = true;\n                node.init.walk(tw);\n                node.body.walk(tw);\n                pop();\n                return true;\n            }\n            if (node instanceof AST_If) {\n                walk_cond(node.condition, node.body, node.alternative);\n                return true;\n            }\n            if (node instanceof AST_LabeledStatement) {\n                push();\n                segment.block = node;\n                var save = segment;\n                node.body.walk(tw);\n                if (segment.inserted === node) segment = save;\n                pop();\n                return true;\n            }\n            if (node instanceof AST_Scope) {\n                push();\n                segment.block = node;\n                if (node === self) root = segment;\n                if (node instanceof AST_Lambda) {\n                    if (node.name) references[node.name.definition().id] = false;\n                    var marker = node.uses_arguments && !tw.has_directive(\"use strict\") ? function(node) {\n                        references[node.definition().id] = false;\n                    } : function(node) {\n                        mark(node);\n                    };\n                    in_arg.push(node);\n                    node.argnames.forEach(function(argname) {\n                        walk_destructured(AST_SymbolFunarg, marker, argname);\n                    });\n                    if (node.rest) walk_destructured(AST_SymbolFunarg, marker, node.rest);\n                    in_arg.pop();\n                }\n                walk_lambda(node, tw);\n                pop();\n                return true;\n            }\n            if (node instanceof AST_Sub) {\n                var exp = node.expression;\n                if (node.optional) {\n                    exp.walk(tw);\n                    push();\n                    node.property.walk(tw);\n                    pop();\n                } else {\n                    descend();\n                }\n                mark_expression(exp);\n                return true;\n            }\n            if (node instanceof AST_Switch) {\n                node.expression.walk(tw);\n                var save = segment;\n                node.body.forEach(function(branch) {\n                    if (branch instanceof AST_Default) return;\n                    branch.expression.walk(tw);\n                    if (save === segment) push();\n                });\n                segment = save;\n                node.body.forEach(function(branch) {\n                    push();\n                    segment.block = node;\n                    var save = segment;\n                    walk_body(branch, tw);\n                    if (segment.inserted === node) segment = save;\n                    pop();\n                });\n                return true;\n            }\n            if (node instanceof AST_SymbolDeclaration) {\n                references[node.definition().id] = false;\n                return true;\n            }\n            if (node instanceof AST_SymbolRef) {\n                mark(node, true);\n                return true;\n            }\n            if (node instanceof AST_Try) {\n                var save_try = in_try;\n                in_try = node;\n                walk_body(node, tw);\n                if (node.bcatch) {\n                    if (node.bcatch.argname) node.bcatch.argname.mark_symbol(function(node) {\n                        if (node instanceof AST_SymbolCatch) {\n                            var def = node.definition();\n                            references[def.id] = false;\n                            if (def = def.redefined()) references[def.id] = false;\n                        }\n                    }, tw);\n                    if (node.bfinally || (in_try = save_try)) {\n                        walk_body(node.bcatch, tw);\n                    } else {\n                        push();\n                        walk_body(node.bcatch, tw);\n                        pop();\n                    }\n                }\n                in_try = save_try;\n                if (node.bfinally) node.bfinally.walk(tw);\n                return true;\n            }\n            if (node instanceof AST_Unary) {\n                if (!UNARY_POSTFIX[node.operator]) return;\n                var sym = node.expression;\n                if (!(sym instanceof AST_SymbolRef)) return;\n                mark(sym, true);\n                return true;\n            }\n            if (node instanceof AST_VarDef) {\n                var assigned = node.value;\n                if (assigned) {\n                    assigned.walk(tw);\n                } else {\n                    assigned = segment.block instanceof AST_ForEnumeration && segment.block.init === tw.parent();\n                }\n                walk_destructured(AST_SymbolDeclaration, assigned ? function(node) {\n                    if (node instanceof AST_SymbolVar) {\n                        mark(node);\n                    } else {\n                        node.walk(tw);\n                    }\n                } : function(node) {\n                    if (node instanceof AST_SymbolVar) {\n                        var id = node.definition().id;\n                        var refs = references[id];\n                        if (refs) {\n                            push_ref(refs, node);\n                        } else if (!(id in references)) {\n                            declarations.add(id, node);\n                        }\n                    } else {\n                        node.walk(tw);\n                    }\n                }, node.name);\n                return true;\n            }\n            if (node instanceof AST_While) {\n                push();\n                segment.block = node;\n                segment.loop = true;\n                descend();\n                pop();\n                return true;\n            }\n\n            function mark_expression(exp) {\n                if (!compressor.option(\"ie\")) return;\n                var sym = root_expr(exp);\n                if (sym instanceof AST_SymbolRef) sym.walk(tw);\n            }\n\n            function walk_cond(condition, consequent, alternative) {\n                var save = segment;\n                var segments = scan_branches(1, condition, consequent, alternative);\n                if (consequent) {\n                    segment = segments.consequent.segment;\n                    for (var i = segments.consequent.level; --i >= 0;) pop();\n                    if (segment !== save) return;\n                }\n                if (alternative) {\n                    segment = segments.alternative.segment;\n                    for (var i = segments.alternative.level; --i >= 0;) pop();\n                    if (segment !== save) return;\n                }\n                segment = save;\n            }\n\n            function scan_branches(level, condition, consequent, alternative) {\n                var segments = {\n                    consequent: {\n                        segment: segment,\n                        level: level,\n                    },\n                    alternative: {\n                        segment: segment,\n                        level: level,\n                    },\n                }\n                if (condition instanceof AST_Binary) switch (condition.operator) {\n                  case \"&&\":\n                    segments.consequent = scan_branches(level + 1, condition.left, condition.right).consequent;\n                    break;\n                  case \"||\":\n                    segments.alternative = scan_branches(level + 1, condition.left, null, condition.right).alternative;\n                    break;\n                  case \"??\":\n                    segments.alternative = scan_branches(level + 1, condition.left, condition.right, condition.right).alternative;\n                    break;\n                  default:\n                    condition.walk(tw);\n                    break;\n                } else if (condition instanceof AST_Conditional) {\n                    scan_branches(level + 1, condition.condition, condition.consequent, condition.alternative);\n                } else {\n                    condition.walk(tw);\n                }\n                if (consequent) {\n                    segment = segments.consequent.segment;\n                    push();\n                    consequent.walk(tw);\n                    segments.consequent.segment = segment;\n                }\n                if (alternative) {\n                    segment = segments.alternative.segment;\n                    push();\n                    alternative.walk(tw);\n                    segments.alternative.segment = segment;\n                }\n                return segments;\n            }\n        });\n        tw.directives = Object.create(compressor.directives);\n        self.walk(tw);\n        var changed = false;\n        var merged = Object.create(null);\n        while (first.length && last.length) {\n            var tail = last.shift();\n            if (!tail) continue;\n            var def = tail.definition;\n            var tail_refs = references[def.id];\n            if (!tail_refs) continue;\n            tail_refs = { end: tail_refs.end };\n            while (def.id in merged) def = merged[def.id];\n            tail_refs.start = references[def.id].start;\n            var skipped = [];\n            do {\n                var head = first.shift();\n                if (tail.index > head.index) continue;\n                var prev_def = head.definition;\n                if (!(prev_def.id in prev)) continue;\n                var head_refs = references[prev_def.id];\n                if (!head_refs) continue;\n                if (head_refs.start.block !== tail_refs.start.block\n                    || !mergeable(head_refs, tail_refs)\n                    || (head_refs.start.loop || !same_scope(def)) && !mergeable(tail_refs, head_refs)\n                    || compressor.option(\"webkit\") && is_funarg(def) !== is_funarg(prev_def)\n                    || prev_def.const_redefs\n                    || !all(head_refs.scopes, function(scope) {\n                        return scope.find_variable(def.name) === def;\n                    })) {\n                    skipped.push(head);\n                    continue;\n                }\n                head_refs.forEach(function(sym) {\n                    sym.thedef = def;\n                    sym.name = def.name;\n                    if (sym instanceof AST_SymbolRef) {\n                        def.references.push(sym);\n                        prev_def.replaced++;\n                    } else {\n                        def.orig.push(sym);\n                        prev_def.eliminated++;\n                    }\n                });\n                if (!prev_def.fixed) def.fixed = false;\n                merged[prev_def.id] = def;\n                changed = true;\n                break;\n            } while (first.length);\n            if (skipped.length) first = skipped.concat(first);\n        }\n        return changed;\n\n        function push() {\n            segment = Object.create(segment);\n        }\n\n        function pop() {\n            segment = Object.getPrototypeOf(segment);\n        }\n\n        function push_ref(refs, sym) {\n            refs.push(sym);\n            push_uniq(refs.scopes, sym.scope);\n            var scope = find_scope(tw);\n            if (scope !== sym.scope) push_uniq(refs.scopes, scope);\n        }\n\n        function walk_destructured(symbol_type, mark, lhs) {\n            var marker = new TreeWalker(function(node) {\n                if (node instanceof AST_Destructured) return;\n                if (node instanceof AST_DefaultValue) {\n                    push();\n                    node.value.walk(tw);\n                    pop();\n                    node.name.walk(marker);\n                } else if (node instanceof AST_DestructuredKeyVal) {\n                    if (!(node.key instanceof AST_Node)) {\n                        node.value.walk(marker);\n                    } else if (node.value instanceof AST_PropAccess) {\n                        push();\n                        segment.block = node;\n                        node.key.walk(tw);\n                        node.value.walk(marker);\n                        pop();\n                    } else {\n                        node.key.walk(tw);\n                        node.value.walk(marker);\n                    }\n                } else if (node instanceof symbol_type) {\n                    mark(node);\n                } else {\n                    node.walk(tw);\n                }\n                return true;\n            });\n            lhs.walk(marker);\n        }\n\n        function mark(sym, read) {\n            var def = sym.definition(), ldef;\n            if (read && !all(in_arg, function(fn) {\n                ldef = fn.variables.get(sym.name);\n                if (!ldef) return true;\n                if (!is_funarg(ldef)) return true;\n                return ldef !== def\n                    && !def.undeclared\n                    && fn.parent_scope.find_variable(sym.name) !== def;\n            })) return references[def.id] = references[ldef.id] = false;\n            var seg = segment;\n            if (in_try) {\n                push();\n                seg = segment;\n                pop();\n            }\n            if (def.id in references) {\n                var refs = references[def.id];\n                if (!refs) return;\n                if (refs.start.block !== seg.block) return references[def.id] = false;\n                push_ref(refs, sym);\n                refs.end = seg;\n                if (def.id in prev) {\n                    last[prev[def.id]] = null;\n                } else if (!read) {\n                    return;\n                }\n            } else if ((ldef = self.variables.get(def.name)) !== def) {\n                if (ldef && root === seg) references[ldef.id] = false;\n                return references[def.id] = false;\n            } else if (compressor.exposed(def) || NO_MERGE[sym.name]) {\n                return references[def.id] = false;\n            } else {\n                var refs = declarations.get(def.id) || [];\n                refs.scopes = [];\n                push_ref(refs, sym);\n                references[def.id] = refs;\n                if (!read) {\n                    refs.start = seg;\n                    return first.push({\n                        index: index++,\n                        definition: def,\n                    });\n                }\n                if (seg.block !== self) return references[def.id] = false;\n                refs.start = root;\n            }\n            prev[def.id] = last.length;\n            last.push({\n                index: index++,\n                definition: def,\n            });\n        }\n\n        function insert(target) {\n            var stack = [];\n            while (true) {\n                if (HOP(segment, \"block\")) {\n                    var block = segment.block;\n                    if (block instanceof AST_LabeledStatement) block = block.body;\n                    if (block === target) break;\n                }\n                stack.push(segment);\n                pop();\n            }\n            segment.inserted = segment.block;\n            push();\n            while (stack.length) {\n                var seg = stack.pop();\n                push();\n                if (HOP(seg, \"block\")) segment.block = seg.block;\n                if (HOP(seg, \"loop\")) segment.loop = seg.loop;\n            }\n        }\n\n        function must_visit(base, segment) {\n            return base === segment || base.isPrototypeOf(segment);\n        }\n\n        function mergeable(head, tail) {\n            return must_visit(head.start, head.end) || must_visit(head.start, tail.start);\n        }\n    });\n\n    function fill_holes(orig, elements) {\n        for (var i = elements.length; --i >= 0;) {\n            if (!elements[i]) elements[i] = make_node(AST_Hole, orig);\n        }\n    }\n\n    function to_class_expr(defcl, drop_name) {\n        var cl = make_node(AST_ClassExpression, defcl);\n        if (cl.name) cl.name = drop_name ? null : make_node(AST_SymbolClass, cl.name);\n        return cl;\n    }\n\n    function to_func_expr(defun, drop_name) {\n        var ctor;\n        switch (defun.CTOR) {\n          case AST_AsyncDefun:\n            ctor = AST_AsyncFunction;\n            break;\n          case AST_AsyncGeneratorDefun:\n            ctor = AST_AsyncGeneratorFunction;\n            break;\n          case AST_Defun:\n            ctor = AST_Function;\n            break;\n          case AST_GeneratorDefun:\n            ctor = AST_GeneratorFunction;\n            break;\n        }\n        var fn = make_node(ctor, defun);\n        fn.name = drop_name ? null : make_node(AST_SymbolLambda, defun.name);\n        return fn;\n    }\n\n    AST_Scope.DEFMETHOD(\"drop_unused\", function(compressor) {\n        if (!compressor.option(\"unused\")) return;\n        var self = this;\n        var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;\n        var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;\n        var assign_as_unused = /keep_assign/.test(compressor.option(\"unused\")) ? return_false : function(node, props) {\n            var sym, nested = false;\n            if (node instanceof AST_Assign) {\n                if (node.write_only || node.operator == \"=\") sym = extract_reference(node.left, props);\n            } else if (node instanceof AST_Unary) {\n                if (node.write_only) sym = extract_reference(node.expression, props);\n            }\n            if (!(sym instanceof AST_SymbolRef)) return;\n            var def = sym.definition();\n            if (export_defaults[def.id]) return;\n            if (compressor.exposed(def)) return;\n            if (!can_drop_symbol(sym, compressor, nested)) return;\n            return sym;\n\n            function extract_reference(node, props) {\n                if (node instanceof AST_PropAccess) {\n                    var expr = node.expression;\n                    if (!expr.may_throw_on_access(compressor, true)) {\n                        nested = true;\n                        if (props && node instanceof AST_Sub) props.unshift(node.property);\n                        return extract_reference(expr, props);\n                    }\n                } else if (node instanceof AST_Assign && node.operator == \"=\") {\n                    node.write_only = \"p\";\n                    var ref = extract_reference(node.right);\n                    if (!props) return ref;\n                    props.assign = node;\n                    return ref instanceof AST_SymbolRef ? ref : node.left;\n                }\n                return node;\n            }\n        };\n        var assign_in_use = Object.create(null);\n        var export_defaults = Object.create(null);\n        var find_variable = function(name) {\n            find_variable = compose(self, 0, noop);\n            return find_variable(name);\n\n            function compose(child, level, find) {\n                var parent = compressor.parent(level);\n                if (!parent) return find;\n                var in_arg = parent instanceof AST_Lambda && member(child, parent.argnames);\n                return compose(parent, level + 1, in_arg ? function(name) {\n                    var def = find(name);\n                    if (def) return def;\n                    def = parent.variables.get(name);\n                    if (def) {\n                        var sym = def.orig[0];\n                        if (sym instanceof AST_SymbolFunarg || sym instanceof AST_SymbolLambda) return def;\n                    }\n                } : parent.variables ? function(name) {\n                    return find(name) || parent.variables.get(name);\n                } : find);\n            }\n        };\n        var for_ins = Object.create(null);\n        var in_use = [];\n        var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use\n        var lambda_ids = Object.create(null);\n        var value_read = Object.create(null);\n        var value_modified = Object.create(null);\n        var var_defs = Object.create(null);\n        if (self instanceof AST_Toplevel && compressor.top_retain) {\n            self.variables.each(function(def) {\n                if (compressor.top_retain(def) && !(def.id in in_use_ids)) {\n                    AST_Node.info(\"Retaining variable {name}\", def);\n                    in_use_ids[def.id] = true;\n                    in_use.push(def);\n                }\n            });\n        }\n        var assignments = new Dictionary();\n        var initializations = new Dictionary();\n        // pass 1: find out which symbols are directly used in\n        // this scope (not in nested scopes).\n        var scope = this;\n        var tw = new TreeWalker(function(node, descend) {\n            if (node instanceof AST_Lambda && node.uses_arguments && !tw.has_directive(\"use strict\")) {\n                node.each_argname(function(argname) {\n                    var def = argname.definition();\n                    if (!(def.id in in_use_ids)) {\n                        in_use_ids[def.id] = true;\n                        in_use.push(def);\n                    }\n                });\n            }\n            if (node === self) return;\n            if (scope === self) {\n                if (node instanceof AST_DefClass) {\n                    var def = node.name.definition();\n                    var drop = drop_funcs && !def.exported;\n                    if (!drop && !(def.id in in_use_ids)) {\n                        in_use_ids[def.id] = true;\n                        in_use.push(def);\n                    }\n                    var used = tw.parent() instanceof AST_ExportDefault;\n                    if (used) {\n                        export_defaults[def.id] = true;\n                    } else if (drop && !(def.id in lambda_ids)) {\n                        lambda_ids[def.id] = 1;\n                    }\n                    if (node.extends) node.extends.walk(tw);\n                    var values = [];\n                    node.properties.forEach(function(prop) {\n                        if (prop.key instanceof AST_Node) prop.key.walk(tw);\n                        var value = prop.value;\n                        if (!value) return;\n                        if (is_static_field_or_init(prop)) {\n                            if (!used && value.contains_this()) used = true;\n                            walk_class_prop(value);\n                        } else {\n                            values.push(value);\n                        }\n                    });\n                    values.forEach(drop && used ? walk_class_prop : function(value) {\n                        initializations.add(def.id, value);\n                    });\n                    return true;\n                }\n                if (node instanceof AST_LambdaDefinition) {\n                    var def = node.name.definition();\n                    var drop = drop_funcs && !def.exported;\n                    if (!drop && !(def.id in in_use_ids)) {\n                        in_use_ids[def.id] = true;\n                        in_use.push(def);\n                    }\n                    initializations.add(def.id, node);\n                    if (tw.parent() instanceof AST_ExportDefault) {\n                        export_defaults[def.id] = true;\n                        return scan_ref_scoped(node, descend, true);\n                    }\n                    if (drop && !(def.id in lambda_ids)) lambda_ids[def.id] = 1;\n                    return true;\n                }\n                if (node instanceof AST_Definitions) {\n                    node.definitions.forEach(function(defn) {\n                        var value = defn.value;\n                        var side_effects = value\n                            && (defn.name instanceof AST_Destructured || value.has_side_effects(compressor));\n                        var shared = side_effects && value.tail_node().operator == \"=\";\n                        defn.name.mark_symbol(function(name) {\n                            if (!(name instanceof AST_SymbolDeclaration)) return;\n                            var def = name.definition();\n                            var_defs[def.id] = (var_defs[def.id] || 0) + 1;\n                            if (node instanceof AST_Var && def.orig[0] instanceof AST_SymbolCatch) {\n                                var redef = def.redefined();\n                                if (redef) var_defs[redef.id] = (var_defs[redef.id] || 0) + 1;\n                            }\n                            if (!(def.id in in_use_ids) && (!drop_vars || def.exported\n                                || (node instanceof AST_Const ? def.redefined() : def.const_redefs)\n                                || !(node instanceof AST_Var || is_safe_lexical(def)))) {\n                                in_use_ids[def.id] = true;\n                                in_use.push(def);\n                            }\n                            if (value) {\n                                if (!side_effects) {\n                                    initializations.add(def.id, value);\n                                } else if (shared) {\n                                    verify_safe_usage(def, name, value_modified[def.id]);\n                                }\n                                assignments.add(def.id, defn);\n                            }\n                            unmark_lambda(def);\n                            return true;\n                        }, tw);\n                        if (side_effects) value.walk(tw);\n                    });\n                    return true;\n                }\n                if (node instanceof AST_SymbolFunarg) {\n                    var def = node.definition();\n                    var_defs[def.id] = (var_defs[def.id] || 0) + 1;\n                    assignments.add(def.id, node);\n                    var fixed = node.fixed_value(true);\n                    if (fixed && fixed.tail_node().operator == \"=\") {\n                        verify_safe_usage(def, node, value_modified[def.id]);\n                    }\n                    return true;\n                }\n                if (node instanceof AST_SymbolImport) {\n                    var def = node.definition();\n                    if (!(def.id in in_use_ids) && (!drop_vars || !is_safe_lexical(def))) {\n                        in_use_ids[def.id] = true;\n                        in_use.push(def);\n                    }\n                    return true;\n                }\n            }\n            return scan_ref_scoped(node, descend, true);\n\n            function walk_class_prop(value) {\n                var save_scope = scope;\n                scope = node;\n                value.walk(tw);\n                scope = save_scope;\n            }\n        });\n        tw.directives = Object.create(compressor.directives);\n        self.walk(tw);\n        var drop_fn_name = compressor.option(\"keep_fnames\") ? return_false : compressor.option(\"ie\") ? function(def) {\n            return !compressor.exposed(def) && def.references.length == def.replaced;\n        } : function(def) {\n            if (!(def.id in in_use_ids)) return true;\n            if (def.orig.length - def.eliminated < 2) return false;\n            // function argument will always overshadow its name\n            if (def.orig[1] instanceof AST_SymbolFunarg) return true;\n            // retain if referenced within destructured object of argument\n            return all(def.references, function(ref) {\n                return !ref.in_arg;\n            });\n        };\n        if (compressor.option(\"ie\")) initializations.each(function(init, id) {\n            if (id in in_use_ids) return;\n            init.forEach(function(init) {\n                init.walk(new TreeWalker(function(node) {\n                    if (node instanceof AST_Function && node.name && !drop_fn_name(node.name.definition())) {\n                        node.walk(tw);\n                        return true;\n                    }\n                    if (node instanceof AST_Scope) return true;\n                }));\n            });\n        });\n        // pass 2: for every used symbol we need to walk its\n        // initialization code to figure out if it uses other\n        // symbols (that may not be in_use).\n        tw = new TreeWalker(scan_ref_scoped);\n        for (var i = 0; i < in_use.length; i++) {\n            var init = initializations.get(in_use[i].id);\n            if (init) init.forEach(function(init) {\n                init.walk(tw);\n            });\n        }\n        Object.keys(assign_in_use).forEach(function(id) {\n            var assigns = assign_in_use[id];\n            if (!assigns) {\n                delete assign_in_use[id];\n                return;\n            }\n            assigns = assigns.reduce(function(in_use, assigns) {\n                assigns.forEach(function(assign) {\n                    push_uniq(in_use, assign);\n                });\n                return in_use;\n            }, []);\n            var in_use = (assignments.get(id) || []).filter(function(node) {\n                return find_if(node instanceof AST_Unary ? function(assign) {\n                    return assign === node;\n                } : function(assign) {\n                    if (assign === node) return true;\n                    if (assign instanceof AST_Unary) return false;\n                    return get_rvalue(assign) === get_rvalue(node);\n                }, assigns);\n            });\n            if (assigns.length == in_use.length) {\n                assign_in_use[id] = in_use;\n            } else {\n                delete assign_in_use[id];\n            }\n        });\n        // pass 3: we should drop declarations not in_use\n        var calls_to_drop_args = [];\n        var fns_with_marked_args = [];\n        var trimmer = new TreeTransformer(function(node) {\n            if (node instanceof AST_DefaultValue) return trim_default(trimmer, node);\n            if (node instanceof AST_Destructured && node.rest) node.rest = node.rest.transform(trimmer);\n            if (node instanceof AST_DestructuredArray) {\n                var trim = !node.rest;\n                for (var i = node.elements.length; --i >= 0;) {\n                    var element = node.elements[i].transform(trimmer);\n                    if (element) {\n                        node.elements[i] = element;\n                        trim = false;\n                    } else if (trim) {\n                        node.elements.pop();\n                    } else {\n                        node.elements[i] = make_node(AST_Hole, node.elements[i]);\n                    }\n                }\n                return node;\n            }\n            if (node instanceof AST_DestructuredObject) {\n                var properties = [];\n                node.properties.forEach(function(prop) {\n                    var retain = false;\n                    if (prop.key instanceof AST_Node) {\n                        prop.key = prop.key.transform(tt);\n                        retain = prop.key.has_side_effects(compressor);\n                    }\n                    if ((retain || node.rest) && is_decl(prop.value)) {\n                        prop.value = prop.value.transform(tt);\n                        properties.push(prop);\n                    } else {\n                        var value = prop.value.transform(trimmer);\n                        if (!value && node.rest) {\n                            if (prop.value instanceof AST_DestructuredArray) {\n                                value = make_node(AST_DestructuredArray, prop.value, { elements: [] });\n                            } else {\n                                value = make_node(AST_DestructuredObject, prop.value, { properties: [] });\n                            }\n                        }\n                        if (value) {\n                            prop.value = value;\n                            properties.push(prop);\n                        }\n                    }\n                });\n                node.properties = properties;\n                return node;\n            }\n            if (node instanceof AST_SymbolDeclaration) return trim_decl(node);\n        });\n        var tt = new TreeTransformer(function(node, descend, in_list) {\n            var parent = tt.parent();\n            if (drop_vars) {\n                var props = [], sym = assign_as_unused(node, props);\n                if (sym) {\n                    var value;\n                    if (can_drop_lhs(sym, node)) {\n                        if (node instanceof AST_Assign) {\n                            value = get_rhs(node);\n                            if (node.write_only === true) value = value.drop_side_effect_free(compressor);\n                        }\n                        if (!value) value = make_node(AST_Number, node, { value: 0 });\n                    }\n                    if (value) {\n                        if (props.assign) {\n                            var assign = props.assign.drop_side_effect_free(compressor);\n                            if (assign) {\n                                assign.write_only = true;\n                                props.unshift(assign);\n                            }\n                        }\n                        if (!(parent instanceof AST_Sequence)\n                            || parent.tail_node() === node\n                            || value.has_side_effects(compressor)) {\n                            props.push(value);\n                        }\n                        switch (props.length) {\n                          case 0:\n                            return List.skip;\n                          case 1:\n                            return maintain_this_binding(parent, node, props[0].transform(tt));\n                          default:\n                            return make_sequence(node, props.map(function(prop) {\n                                return prop.transform(tt);\n                            }));\n                        }\n                    }\n                } else if (node instanceof AST_UnaryPostfix\n                    && node.expression instanceof AST_SymbolRef\n                    && indexOf_assign(node.expression.definition(), node) < 0) {\n                    return make_node(AST_UnaryPrefix, node, {\n                        operator: \"+\",\n                        expression: node.expression,\n                    });\n                }\n            }\n            if (node instanceof AST_Binary && node.operator == \"instanceof\") {\n                var sym = node.right;\n                if (!(sym instanceof AST_SymbolRef)) return;\n                if (sym.definition().id in in_use_ids) return;\n                var lhs = node.left.drop_side_effect_free(compressor);\n                var value = make_node(AST_False, node).optimize(compressor);\n                return lhs ? make_sequence(node, [ lhs, value ]) : value;\n            }\n            if (node instanceof AST_Call) {\n                calls_to_drop_args.push(node);\n                node.args = node.args.map(function(arg) {\n                    return arg.transform(tt);\n                });\n                node.expression = node.expression.transform(tt);\n                return node;\n            }\n            if (scope !== self) return;\n            if (drop_funcs && node !== self && node instanceof AST_DefClass) {\n                var def = node.name.definition();\n                if (!(def.id in in_use_ids)) {\n                    log(node.name, \"Dropping unused class {name}\");\n                    def.eliminated++;\n                    descend(node, tt);\n                    var trimmed = to_class_expr(node, true);\n                    if (parent instanceof AST_ExportDefault) return trimmed;\n                    trimmed = trimmed.drop_side_effect_free(compressor, true);\n                    if (trimmed) return make_node(AST_SimpleStatement, node, { body: trimmed });\n                    return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n                }\n            }\n            if (node instanceof AST_ClassExpression && node.name && drop_fn_name(node.name.definition())) {\n                node.name = null;\n            }\n            if (node instanceof AST_Lambda) {\n                if (drop_funcs && node !== self && node instanceof AST_LambdaDefinition) {\n                    var def = node.name.definition();\n                    if (!(def.id in in_use_ids)) {\n                        log(node.name, \"Dropping unused function {name}\");\n                        def.eliminated++;\n                        if (parent instanceof AST_ExportDefault) {\n                            descend_scope();\n                            return to_func_expr(node, true);\n                        }\n                        return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n                    }\n                }\n                descend_scope();\n                if (node instanceof AST_LambdaExpression && node.name && drop_fn_name(node.name.definition())) {\n                    node.name = null;\n                }\n                if (!(node instanceof AST_Accessor)) {\n                    var args, spread, trim = compressor.drop_fargs(node, parent);\n                    if (trim && parent instanceof AST_Call && parent.expression === node) {\n                        args = parent.args;\n                        for (spread = 0; spread < args.length; spread++) {\n                            if (args[spread] instanceof AST_Spread) break;\n                        }\n                    }\n                    var argnames = node.argnames;\n                    var rest = node.rest;\n                    var after = false, before = false;\n                    if (rest) {\n                        before = true;\n                        if (!args || spread < argnames.length || rest instanceof AST_SymbolFunarg) {\n                            rest = rest.transform(trimmer);\n                        } else {\n                            var trimmed = trim_destructured(rest, make_node(AST_Array, parent, {\n                                elements: args.slice(argnames.length),\n                            }), trim_decl, !node.uses_arguments, rest);\n                            rest = trimmed.name;\n                            args.length = argnames.length;\n                            if (trimmed.value.elements.length) [].push.apply(args, trimmed.value.elements);\n                        }\n                        if (rest instanceof AST_Destructured && !rest.rest) {\n                            if (rest instanceof AST_DestructuredArray) {\n                                if (rest.elements.length == 0) rest = null;\n                            } else if (rest.properties.length == 0) {\n                                rest = null;\n                            }\n                        }\n                        node.rest = rest;\n                        if (rest) {\n                            trim = false;\n                            after = true;\n                        }\n                    }\n                    var default_length = trim ? -1 : node.length();\n                    var trim_value = args && !node.uses_arguments && parent !== compressor.parent();\n                    for (var i = argnames.length; --i >= 0;) {\n                        var sym = argnames[i];\n                        if (sym instanceof AST_SymbolFunarg) {\n                            var def = sym.definition();\n                            if (def.id in in_use_ids) {\n                                trim = false;\n                                if (indexOf_assign(def, sym) < 0) sym.unused = null;\n                            } else if (trim) {\n                                log(sym, \"Dropping unused function argument {name}\");\n                                argnames.pop();\n                                def.eliminated++;\n                                sym.unused = true;\n                            } else {\n                                sym.unused = true;\n                            }\n                        } else {\n                            before = true;\n                            var funarg;\n                            if (!args || spread < i) {\n                                funarg = sym.transform(trimmer);\n                            } else {\n                                var trimmed = trim_destructured(sym, args[i], trim_decl, trim_value, sym);\n                                funarg = trimmed.name;\n                                if (trimmed.value) args[i] = trimmed.value;\n                            }\n                            if (funarg) {\n                                trim = false;\n                                argnames[i] = funarg;\n                                if (!after) after = !(funarg instanceof AST_SymbolFunarg);\n                            } else if (trim) {\n                                log_default(sym, \"Dropping unused default argument {name}\");\n                                argnames.pop();\n                            } else if (i > default_length) {\n                                log_default(sym, \"Dropping unused default argument assignment {name}\");\n                                if (sym.name instanceof AST_SymbolFunarg) {\n                                    sym.name.unused = true;\n                                } else {\n                                    after = true;\n                                }\n                                argnames[i] = sym.name;\n                            } else {\n                                log_default(sym, \"Dropping unused default argument value {name}\");\n                                argnames[i] = sym = sym.clone();\n                                sym.value = make_node(AST_Number, sym, { value: 0 });\n                                after = true;\n                            }\n                        }\n                    }\n                    if (before && !after && node.uses_arguments && !tt.has_directive(\"use strict\")) {\n                        node.rest = make_node(AST_DestructuredArray, node, { elements: [] });\n                    }\n                    fns_with_marked_args.push(node);\n                }\n                return node;\n            }\n            if (node instanceof AST_Catch && node.argname instanceof AST_Destructured) {\n                node.argname.transform(trimmer);\n            }\n            if (node instanceof AST_Definitions && !(parent instanceof AST_ForEnumeration && parent.init === node)) {\n                // place uninitialized names at the start\n                var body = [], head = [], tail = [];\n                // for unused names whose initialization has\n                // side effects, we can cascade the init. code\n                // into the next one, or next statement.\n                var side_effects = [];\n                var duplicated = 0;\n                var is_var = node instanceof AST_Var;\n                node.definitions.forEach(function(def) {\n                    if (def.value) def.value = def.value.transform(tt);\n                    var value = def.value;\n                    if (def.name instanceof AST_Destructured) {\n                        var trimmed = trim_destructured(def.name, value, function(node) {\n                            if (!drop_vars) return node;\n                            if (node.definition().id in in_use_ids) return node;\n                            if (is_catch(node)) return node;\n                            if (is_var && !can_drop_symbol(node)) return node;\n                            return null;\n                        }, true);\n                        if (trimmed.name) {\n                            def = make_node(AST_VarDef, def, {\n                                name: trimmed.name,\n                                value: value = trimmed.value,\n                            });\n                            flush();\n                        } else if (trimmed.value) {\n                            side_effects.push(trimmed.value);\n                        }\n                        return;\n                    }\n                    var sym = def.name.definition();\n                    var drop_sym = is_var ? can_drop_symbol(def.name) : is_safe_lexical(sym);\n                    if (!drop_sym || !drop_vars || sym.id in in_use_ids) {\n                        var index;\n                        if (value && ((index = indexOf_assign(sym, def)) < 0 || self_assign(value.tail_node()))) {\n                            def = def.clone();\n                            value = value.drop_side_effect_free(compressor);\n                            if (value) AST_Node.warn(\"Side effects in definition of variable {name} [{start}]\", def.name);\n                            if (node instanceof AST_Const) {\n                                def.value = value || make_node(AST_Number, def, { value: 0 });\n                            } else {\n                                def.value = null;\n                                if (value) side_effects.push(value);\n                            }\n                            value = null;\n                            if (index >= 0) assign_in_use[sym.id][index] = def;\n                        }\n                        var old_def, fn;\n                        if (!value && !(node instanceof AST_Let)) {\n                            if (parent instanceof AST_ExportDeclaration) {\n                                flush();\n                            } else if (drop_sym && var_defs[sym.id] > 1) {\n                                AST_Node.info(\"Dropping declaration of variable {name} [{start}]\", def.name);\n                                var_defs[sym.id]--;\n                                sym.eliminated++;\n                            } else {\n                                head.push(def);\n                            }\n                        } else if (compressor.option(\"functions\")\n                            && !compressor.option(\"ie\")\n                            && drop_sym\n                            && value\n                            && var_defs[sym.id] == 1\n                            && sym.assignments == 0\n                            && (fn = value.tail_node()) instanceof AST_LambdaExpression\n                            && !is_arguments(sym)\n                            && !is_arrow(fn)\n                            && assigned_once(fn, sym.references)\n                            && can_declare_defun(fn)\n                            && (old_def = rename_def(fn, def.name.name)) !== false) {\n                            AST_Node.warn(\"Declaring {name} as function [{start}]\", def.name);\n                            var ctor;\n                            switch (fn.CTOR) {\n                              case AST_AsyncFunction:\n                                ctor = AST_AsyncDefun;\n                                break;\n                              case AST_AsyncGeneratorFunction:\n                                ctor = AST_AsyncGeneratorDefun;\n                                break;\n                              case AST_Function:\n                                ctor = AST_Defun;\n                                break;\n                              case AST_GeneratorFunction:\n                                ctor = AST_GeneratorDefun;\n                                break;\n                            }\n                            var defun = make_node(ctor, fn);\n                            defun.name = make_node(AST_SymbolDefun, def.name);\n                            var name_def = def.name.scope.resolve().def_function(defun.name);\n                            if (old_def) old_def.forEach(function(node) {\n                                node.name = name_def.name;\n                                node.thedef = name_def;\n                                node.reference();\n                            });\n                            body.push(defun);\n                            if (value !== fn) [].push.apply(side_effects, value.expressions.slice(0, -1));\n                            sym.eliminated++;\n                        } else {\n                            if (drop_sym\n                                && var_defs[sym.id] > 1\n                                && !(parent instanceof AST_ExportDeclaration)\n                                && sym.orig.indexOf(def.name) > sym.eliminated) {\n                                var_defs[sym.id]--;\n                                duplicated++;\n                            }\n                            flush();\n                        }\n                    } else if (is_catch(def.name)) {\n                        value = value && value.drop_side_effect_free(compressor);\n                        if (value) side_effects.push(value);\n                        if (var_defs[sym.id] > 1) {\n                            AST_Node.warn(\"Dropping duplicated declaration of variable {name} [{start}]\", def.name);\n                            var_defs[sym.id]--;\n                            sym.eliminated++;\n                        } else {\n                            def.value = null;\n                            head.push(def);\n                        }\n                    } else {\n                        value = value && value.drop_side_effect_free(compressor);\n                        if (value) {\n                            AST_Node.warn(\"Side effects in initialization of unused variable {name} [{start}]\", def.name);\n                            side_effects.push(value);\n                        } else {\n                            log(def.name, \"Dropping unused variable {name}\");\n                        }\n                        sym.eliminated++;\n                    }\n\n                    function self_assign(ref) {\n                        return ref instanceof AST_SymbolRef && ref.definition() === sym;\n                    }\n\n                    function assigned_once(fn, refs) {\n                        if (refs.length == 0) return fn === def.name.fixed_value();\n                        return all(refs, function(ref) {\n                            return fn === ref.fixed_value();\n                        });\n                    }\n\n                    function can_declare_defun(fn) {\n                        if (!is_var || compressor.has_directive(\"use strict\") || !(fn instanceof AST_Function)) {\n                            return parent instanceof AST_Scope;\n                        }\n                        return parent instanceof AST_Block\n                            || parent instanceof AST_For && parent.init === node\n                            || parent instanceof AST_If;\n                    }\n\n                    function rename_def(fn, name) {\n                        if (!fn.name) return null;\n                        var def = fn.name.definition();\n                        if (def.orig.length > 1) return null;\n                        if (def.assignments > 0) return false;\n                        if (def.name == name) return def;\n                        if (compressor.option(\"keep_fnames\")) return false;\n                        var forbidden;\n                        switch (name) {\n                          case \"await\":\n                            forbidden = is_async;\n                            break;\n                          case \"yield\":\n                            forbidden = is_generator;\n                            break;\n                        }\n                        return all(def.references, function(ref) {\n                            var scope = ref.scope;\n                            if (scope.find_variable(name) !== sym) return false;\n                            if (forbidden) do {\n                                scope = scope.resolve();\n                                if (forbidden(scope)) return false;\n                            } while (scope !== fn && (scope = scope.parent_scope));\n                            return true;\n                        }) && def;\n                    }\n\n                    function is_catch(node) {\n                        var sym = node.definition();\n                        return sym.orig[0] instanceof AST_SymbolCatch && sym.scope.resolve() === node.scope.resolve();\n                    }\n\n                    function flush() {\n                        if (side_effects.length > 0) {\n                            if (tail.length == 0) {\n                                body.push(make_node(AST_SimpleStatement, node, {\n                                    body: make_sequence(node, side_effects),\n                                }));\n                            } else if (value) {\n                                side_effects.push(value);\n                                def.value = make_sequence(value, side_effects);\n                            } else {\n                                def.value = make_node(AST_UnaryPrefix, def, {\n                                    operator: \"void\",\n                                    expression: make_sequence(def, side_effects),\n                                });\n                            }\n                            side_effects = [];\n                        }\n                        tail.push(def);\n                    }\n                });\n                switch (head.length) {\n                  case 0:\n                    if (tail.length == 0) break;\n                    if (tail.length == duplicated) {\n                        [].unshift.apply(side_effects, tail.map(function(def) {\n                            AST_Node.info(\"Dropping duplicated definition of variable {name} [{start}]\", def.name);\n                            var sym = def.name.definition();\n                            var ref = make_node(AST_SymbolRef, def.name);\n                            sym.references.push(ref);\n                            var assign = make_node(AST_Assign, def, {\n                                operator: \"=\",\n                                left: ref,\n                                right: def.value,\n                            });\n                            var index = indexOf_assign(sym, def);\n                            if (index >= 0) assign_in_use[sym.id][index] = assign;\n                            sym.assignments++;\n                            sym.eliminated++;\n                            return assign;\n                        }));\n                        break;\n                    }\n                  case 1:\n                    if (tail.length == 0) {\n                        var id = head[0].name.definition().id;\n                        if (id in for_ins) {\n                            node.definitions = head;\n                            for_ins[id].init = node;\n                            break;\n                        }\n                    }\n                  default:\n                    var seq;\n                    if (tail.length > 0 && (seq = tail[0].value) instanceof AST_Sequence) {\n                        tail[0].value = seq.tail_node();\n                        body.push(make_node(AST_SimpleStatement, node, {\n                            body: make_sequence(seq, seq.expressions.slice(0, -1)),\n                        }));\n                    }\n                    node.definitions = head.concat(tail);\n                    body.push(node);\n                }\n                if (side_effects.length > 0) {\n                    body.push(make_node(AST_SimpleStatement, node, { body: make_sequence(node, side_effects) }));\n                }\n                return insert_statements(body, node, in_list);\n            }\n            if (node instanceof AST_Assign) {\n                descend(node, tt);\n                if (!(node.left instanceof AST_Destructured)) return node;\n                var trimmed = trim_destructured(node.left, node.right, function(node) {\n                    return node;\n                }, node.write_only === true);\n                if (trimmed.name) return make_node(AST_Assign, node, {\n                    operator: node.operator,\n                    left: trimmed.name,\n                    right: trimmed.value,\n                });\n                if (trimmed.value) return trimmed.value;\n                if (parent instanceof AST_Sequence && parent.tail_node() !== node) return List.skip;\n                return make_node(AST_Number, node, { value: 0 });\n            }\n            if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {\n                // Certain combination of unused name + side effect leads to invalid AST:\n                //    https://github.com/mishoo/UglifyJS/issues/1830\n                // We fix it at this stage by moving the label inwards, back to the `for`.\n                descend(node, tt);\n                if (node.body instanceof AST_BlockStatement) {\n                    var block = node.body;\n                    node.body = block.body.pop();\n                    block.body.push(node);\n                    return in_list ? List.splice(block.body) : block;\n                }\n                return node;\n            }\n            if (node instanceof AST_Scope) {\n                descend_scope();\n                return node;\n            }\n            if (node instanceof AST_SymbolImport) {\n                if (!compressor.option(\"imports\") || node.definition().id in in_use_ids) return node;\n                return in_list ? List.skip : null;\n            }\n\n            function descend_scope() {\n                var save_scope = scope;\n                scope = node;\n                descend(node, tt);\n                scope = save_scope;\n            }\n        }, function(node, in_list) {\n            if (node instanceof AST_BlockStatement) return trim_block(node, tt.parent(), in_list);\n            if (node instanceof AST_ExportDeclaration) {\n                var block = node.body;\n                if (!(block instanceof AST_BlockStatement)) return;\n                node.body = block.body.pop();\n                block.body.push(node);\n                return in_list ? List.splice(block.body) : block;\n            }\n            if (node instanceof AST_For) return patch_for_init(node, in_list);\n            if (node instanceof AST_ForIn) {\n                if (!drop_vars || !compressor.option(\"loops\")) return;\n                if (!is_empty(node.body)) return;\n                var sym = get_init_symbol(node);\n                if (!sym) return;\n                var def = sym.definition();\n                if (def.id in in_use_ids) return;\n                log(sym, \"Dropping unused loop variable {name}\");\n                if (for_ins[def.id] === node) delete for_ins[def.id];\n                var body = [];\n                var value = node.object.drop_side_effect_free(compressor);\n                if (value) {\n                    AST_Node.warn(\"Side effects in object of for-in loop [{start}]\", value);\n                    body.push(make_node(AST_SimpleStatement, node, { body: value }));\n                }\n                if (node.init instanceof AST_Definitions && def.orig[0] instanceof AST_SymbolCatch) {\n                    body.push(node.init);\n                }\n                return insert_statements(body, node, in_list);\n            }\n            if (node instanceof AST_Import) {\n                if (node.properties && node.properties.length == 0) node.properties = null;\n                return node;\n            }\n            if (node instanceof AST_Sequence) {\n                if (node.expressions.length > 1) return;\n                return maintain_this_binding(tt.parent(), node, node.expressions[0]);\n            }\n        });\n        tt.push(compressor.parent());\n        tt.directives = Object.create(compressor.directives);\n        self.transform(tt);\n        if (self instanceof AST_Lambda\n            && self.body.length == 1\n            && self.body[0] instanceof AST_Directive\n            && self.body[0].value == \"use strict\") {\n            self.body.length = 0;\n        }\n        calls_to_drop_args.forEach(function(call) {\n            drop_unused_call_args(call, compressor, fns_with_marked_args);\n        });\n\n        function log(sym, text) {\n            AST_Node[sym.definition().references.length > 0 ? \"info\" : \"warn\"](text + \" [{start}]\", sym);\n        }\n\n        function log_default(node, text) {\n            if (node.name instanceof AST_SymbolFunarg) {\n                log(node.name, text);\n            } else {\n                AST_Node.info(text + \" [{start}]\", node);\n            }\n        }\n\n        function get_rvalue(expr) {\n            return expr[expr instanceof AST_Assign ? \"right\" : \"value\"];\n        }\n\n        function insert_statements(body, orig, in_list) {\n            switch (body.length) {\n              case 0:\n                return in_list ? List.skip : make_node(AST_EmptyStatement, orig);\n              case 1:\n                return body[0];\n              default:\n                return in_list ? List.splice(body) : make_node(AST_BlockStatement, orig, { body: body });\n            }\n        }\n\n        function track_assigns(def, node) {\n            if (def.scope.resolve() !== self) return false;\n            if (!def.fixed || !node.fixed) assign_in_use[def.id] = false;\n            return assign_in_use[def.id] !== false;\n        }\n\n        function add_assigns(def, node) {\n            if (!assign_in_use[def.id]) assign_in_use[def.id] = [];\n            if (node.fixed.assigns) push_uniq(assign_in_use[def.id], node.fixed.assigns);\n        }\n\n        function indexOf_assign(def, node) {\n            var nodes = assign_in_use[def.id];\n            return nodes && nodes.indexOf(node);\n        }\n\n        function unmark_lambda(def) {\n            if (lambda_ids[def.id] > 1 && !(def.id in in_use_ids)) {\n                in_use_ids[def.id] = true;\n                in_use.push(def);\n            }\n            lambda_ids[def.id] = 0;\n        }\n\n        function verify_safe_usage(def, read, modified) {\n            if (def.id in in_use_ids) return;\n            if (read && modified) {\n                in_use_ids[def.id] = read;\n                in_use.push(def);\n            } else {\n                value_read[def.id] = read;\n                value_modified[def.id] = modified;\n            }\n        }\n\n        function can_drop_lhs(sym, node) {\n            var def = sym.definition();\n            var in_use = in_use_ids[def.id];\n            if (!in_use) return true;\n            if (node[node instanceof AST_Assign ? \"left\" : \"expression\"] !== sym) return false;\n            return in_use === sym && def.references.length - def.replaced == 1 || indexOf_assign(def, node) < 0;\n        }\n\n        function get_rhs(assign) {\n            var rhs = assign.right;\n            if (!assign.write_only) return rhs;\n            if (!(rhs instanceof AST_Binary && lazy_op[rhs.operator])) return rhs;\n            if (!(rhs.left instanceof AST_SymbolRef)) return rhs;\n            if (!(assign.left instanceof AST_SymbolRef)) return rhs;\n            var def = assign.left.definition();\n            if (rhs.left.definition() !== def) return rhs;\n            if (rhs.right.has_side_effects(compressor)) return rhs;\n            if (track_assigns(def, rhs.left)) add_assigns(def, rhs.left);\n            return rhs.right;\n        }\n\n        function get_init_symbol(for_in) {\n            var init = for_in.init;\n            if (init instanceof AST_Definitions) {\n                init = init.definitions[0].name;\n                return init instanceof AST_SymbolDeclaration && init;\n            }\n            while (init instanceof AST_PropAccess) init = init.expression.tail_node();\n            if (init instanceof AST_SymbolRef) return init;\n        }\n\n        function scan_ref_scoped(node, descend, init) {\n            if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) {\n                var def = node.left.definition();\n                if (def.scope.resolve() === self) assignments.add(def.id, node);\n            }\n            if (node instanceof AST_SymbolRef && node.in_arg) var_defs[node.definition().id] = 0;\n            if (node instanceof AST_Unary && node.expression instanceof AST_SymbolRef) {\n                var def = node.expression.definition();\n                if (def.scope.resolve() === self) assignments.add(def.id, node);\n            }\n            var props = [], sym = assign_as_unused(node, props);\n            if (sym) {\n                var node_def = sym.definition();\n                if (node_def.scope.resolve() !== self && self.variables.get(sym.name) !== node_def) return;\n                if (is_arguments(node_def) && !all(self.argnames, function(argname) {\n                    return !argname.match_symbol(function(node) {\n                        if (node instanceof AST_SymbolFunarg) {\n                            var def = node.definition();\n                            return def.references.length > def.replaced;\n                        }\n                    }, true);\n                })) return;\n                if (node.write_only === \"p\" && node.right.may_throw_on_access(compressor, true)) return;\n                var assign = props.assign;\n                if (assign) {\n                    initializations.add(node_def.id, assign.left);\n                    assign.write_only = true;\n                    assign.walk(tw);\n                }\n                props.forEach(function(prop) {\n                    prop.walk(tw);\n                });\n                if (node instanceof AST_Assign) {\n                    var fixed = sym.fixed_value();\n                    var right = get_rhs(node);\n                    var safe = fixed && fixed.is_constant();\n                    var shared = false;\n                    if (init\n                        && node.write_only === true\n                        && (safe || node.left === sym || right.equals(sym))\n                        && !right.has_side_effects(compressor)) {\n                        initializations.add(node_def.id, right);\n                    } else {\n                        right.walk(tw);\n                        shared = right.tail_node().operator == \"=\";\n                    }\n                    if (node.left === sym) {\n                        if (!node.write_only || shared) {\n                            verify_safe_usage(node_def, sym, value_modified[node_def.id]);\n                        }\n                    } else if (!safe) {\n                        verify_safe_usage(node_def, value_read[node_def.id], true);\n                    }\n                }\n                if (track_assigns(node_def, sym) && is_lhs(sym, node) !== sym) add_assigns(node_def, sym);\n                unmark_lambda(node_def);\n                return true;\n            }\n            if (node instanceof AST_Binary) {\n                if (node.operator != \"instanceof\") return;\n                var sym = node.right;\n                if (!(sym instanceof AST_SymbolRef)) return;\n                var id = sym.definition().id;\n                if (!lambda_ids[id]) return;\n                node.left.walk(tw);\n                lambda_ids[id]++;\n                return true;\n            }\n            if (node instanceof AST_ForIn) {\n                if (node.init instanceof AST_SymbolRef && scope === self) {\n                    var id = node.init.definition().id;\n                    if (!(id in for_ins)) for_ins[id] = node;\n                }\n                if (!drop_vars || !compressor.option(\"loops\")) return;\n                if (!is_empty(node.body)) return;\n                if (node.init.has_side_effects(compressor)) return;\n                var sym = get_init_symbol(node);\n                if (!sym) return;\n                var def = sym.definition();\n                if (def.scope.resolve() !== self) {\n                    var d = find_variable(sym.name);\n                    if (d === def || d && d.redefined() === def) return;\n                }\n                node.object.walk(tw);\n                return true;\n            }\n            if (node instanceof AST_SymbolRef) {\n                var node_def = node.definition();\n                if (!(node_def.id in in_use_ids)) {\n                    in_use_ids[node_def.id] = true;\n                    in_use.push(node_def);\n                }\n                if (cross_scope(node_def.scope, node.scope)) {\n                    var redef = node_def.redefined();\n                    if (redef && !(redef.id in in_use_ids)) {\n                        in_use_ids[redef.id] = true;\n                        in_use.push(redef);\n                    }\n                }\n                if (track_assigns(node_def, node)) add_assigns(node_def, node);\n                return true;\n            }\n            if (node instanceof AST_Scope) {\n                var save_scope = scope;\n                scope = node;\n                descend();\n                scope = save_scope;\n                return true;\n            }\n        }\n\n        function is_decl(node) {\n            return (node instanceof AST_DefaultValue ? node.name : node) instanceof AST_SymbolDeclaration;\n        }\n\n        function trim_decl(node) {\n            if (node.definition().id in in_use_ids) return node;\n            if (node instanceof AST_SymbolFunarg) node.unused = true;\n            return null;\n        }\n\n        function trim_default(trimmer, node) {\n            node.value = node.value.transform(tt);\n            var name = node.name.transform(trimmer);\n            if (!name) {\n                if (node.name instanceof AST_Destructured) return null;\n                var value = node.value.drop_side_effect_free(compressor);\n                if (!value) return null;\n                log(node.name, \"Side effects in default value of unused variable {name}\");\n                node = node.clone();\n                node.name.unused = null;\n                node.value = value;\n            }\n            return node;\n        }\n\n        function trim_destructured(node, value, process, drop, root) {\n            var unwind = true;\n            var trimmer = new TreeTransformer(function(node) {\n                if (node instanceof AST_DefaultValue) {\n                    if (!(compressor.option(\"default_values\") && value && value.is_defined(compressor))) {\n                        var save_drop = drop;\n                        drop = false;\n                        var trimmed = trim_default(trimmer, node);\n                        drop = save_drop;\n                        if (!trimmed && drop && value) value = value.drop_side_effect_free(compressor);\n                        return trimmed;\n                    } else if (node === root) {\n                        root = node = node.name;\n                    } else {\n                        node = node.name;\n                    }\n                }\n                if (node instanceof AST_DestructuredArray) {\n                    var save_drop = drop;\n                    var save_unwind = unwind;\n                    var save_value = value;\n                    if (value instanceof AST_SymbolRef) {\n                        drop = false;\n                        value = value.fixed_value();\n                    }\n                    var last_side_effects, native, values;\n                    if (value instanceof AST_Array) {\n                        native = true;\n                        values = value.elements;\n                        if (save_unwind) for (last_side_effects = values.length; --last_side_effects >= 0;) {\n                            if (values[last_side_effects].has_side_effects(compressor)) break;\n                        }\n                    } else {\n                        native = value && value.is_string(compressor);\n                        values = false;\n                        last_side_effects = node.elements.length;\n                    }\n                    var elements = [], newValues = drop && [], pos = 0;\n                    node.elements.forEach(function(element, index) {\n                        if (save_unwind) unwind = index >= last_side_effects;\n                        value = values && values[index];\n                        if (value instanceof AST_Hole) {\n                            value = null;\n                        } else if (value instanceof AST_Spread) {\n                            if (drop) {\n                                newValues.length = pos;\n                                fill_holes(save_value, newValues);\n                                [].push.apply(newValues, values.slice(index));\n                                save_value.elements = newValues;\n                            }\n                            value = values = false;\n                        }\n                        element = element.transform(trimmer);\n                        if (element) elements[pos] = element;\n                        if (drop && value) newValues[pos] = value;\n                        if (element || value || !drop || !values) pos++;\n                    });\n                    value = values && make_node(AST_Array, save_value, {\n                        elements: values.slice(node.elements.length),\n                    });\n                    if (node.rest) {\n                        var was_drop = drop;\n                        drop = false;\n                        node.rest = node.rest.transform(compressor.option(\"rests\") ? trimmer : tt);\n                        drop = was_drop;\n                        if (node.rest) elements.length = pos;\n                    }\n                    if (drop) {\n                        if (value && !node.rest) value = value.drop_side_effect_free(compressor);\n                        if (value instanceof AST_Array) {\n                            value = value.elements;\n                        } else if (value instanceof AST_Sequence) {\n                            value = value.expressions;\n                        } else if (value) {\n                            value = [ value ];\n                        }\n                        if (value && value.length) {\n                            newValues.length = pos;\n                            [].push.apply(newValues, value);\n                        }\n                    }\n                    value = save_value;\n                    unwind = save_unwind;\n                    drop = save_drop;\n                    if (values && newValues) {\n                        fill_holes(value, newValues);\n                        value = value.clone();\n                        value.elements = newValues;\n                    }\n                    if (!native) {\n                        elements.length = node.elements.length;\n                    } else if (!node.rest) SHORTHAND: switch (elements.length) {\n                      case 0:\n                        if (node === root) break;\n                        if (drop) value = value.drop_side_effect_free(compressor);\n                        return null;\n                      default:\n                        if (!drop) break;\n                        if (!unwind) break;\n                        if (node === root) break;\n                        var pos = elements.length, sym;\n                        while (--pos >= 0) {\n                            var element = elements[pos];\n                            if (element) {\n                                sym = element;\n                                break;\n                            }\n                        }\n                        if (pos < 0) break;\n                        for (var i = pos; --i >= 0;) {\n                            if (elements[i]) break SHORTHAND;\n                        }\n                        if (sym.has_side_effects(compressor)) break;\n                        if (value.has_side_effects(compressor) && sym.match_symbol(function(node) {\n                            return node instanceof AST_PropAccess;\n                        })) break;\n                        value = make_node(AST_Sub, node, {\n                            expression: value,\n                            property: make_node(AST_Number, node, { value: pos }),\n                        });\n                        return sym;\n                    }\n                    fill_holes(node, elements);\n                    node.elements = elements;\n                    return node;\n                }\n                if (node instanceof AST_DestructuredObject) {\n                    var save_drop = drop;\n                    var save_unwind = unwind;\n                    var save_value = value;\n                    if (value instanceof AST_SymbolRef) {\n                        drop = false;\n                        value = value.fixed_value();\n                    }\n                    var last_side_effects, prop_keys, prop_map, values;\n                    if (value instanceof AST_Object) {\n                        last_side_effects = -1;\n                        prop_keys = [];\n                        prop_map = new Dictionary();\n                        values = value.properties.map(function(prop, index) {\n                            if (save_unwind && prop.has_side_effects(compressor)) last_side_effects = index;\n                            prop = prop.clone();\n                            if (prop instanceof AST_Spread) {\n                                prop_map = false;\n                            } else {\n                                var key = prop.key;\n                                if (key instanceof AST_Node) key = key.evaluate(compressor, true);\n                                if (key instanceof AST_Node) {\n                                    prop_map = false;\n                                } else if (prop_map && !(prop instanceof AST_ObjectSetter)) {\n                                    prop_map.set(key, prop);\n                                }\n                                prop_keys[index] = key;\n                            }\n                            return prop;\n                        });\n                    } else {\n                        last_side_effects = node.properties.length;\n                    }\n                    if (node.rest) {\n                        value = false;\n                        node.rest = node.rest.transform(compressor.option(\"rests\") ? trimmer : tt);\n                    }\n                    var can_drop = new Dictionary();\n                    var drop_keys = drop && new Dictionary();\n                    var properties = [];\n                    node.properties.map(function(prop) {\n                        var key = prop.key;\n                        if (key instanceof AST_Node) {\n                            prop.key = key = key.transform(tt);\n                            key = key.evaluate(compressor, true);\n                        }\n                        if (key instanceof AST_Node) {\n                            drop_keys = false;\n                        } else {\n                            can_drop.set(key, !can_drop.has(key));\n                        }\n                        return key;\n                    }).forEach(function(key, index) {\n                        var prop = node.properties[index], trimmed;\n                        if (save_unwind) unwind = index >= last_side_effects;\n                        if (key instanceof AST_Node) {\n                            drop = false;\n                            value = false;\n                            trimmed = prop.value.transform(trimmer) || retain_lhs(prop.value);\n                        } else {\n                            drop = drop_keys && can_drop.get(key);\n                            var mapped = prop_map && prop_map.get(key);\n                            if (mapped) {\n                                value = mapped.value;\n                                if (value instanceof AST_Accessor) value = false;\n                            } else {\n                                value = false;\n                            }\n                            trimmed = prop.value.transform(trimmer);\n                            if (!trimmed) {\n                                if (node.rest || retain_key(prop)) trimmed = retain_lhs(prop.value);\n                                if (drop_keys && !drop_keys.has(key)) {\n                                    if (mapped) {\n                                        drop_keys.set(key, mapped);\n                                        if (value === null) {\n                                            prop_map.set(key, retain_key(mapped) && make_node(AST_ObjectKeyVal, mapped, {\n                                                key: mapped.key,\n                                                value: make_node(AST_Number, mapped, { value: 0 }),\n                                            }));\n                                        }\n                                    } else {\n                                        drop_keys.set(key, true);\n                                    }\n                                }\n                            } else if (drop_keys) {\n                                drop_keys.set(key, false);\n                            }\n                            if (value) mapped.value = value;\n                        }\n                        if (trimmed) {\n                            prop.value = trimmed;\n                            properties.push(prop);\n                        }\n                    });\n                    value = save_value;\n                    unwind = save_unwind;\n                    drop = save_drop;\n                    if (drop_keys && prop_keys) {\n                        value = value.clone();\n                        value.properties = List(values, function(prop, index) {\n                            if (prop instanceof AST_Spread) return prop;\n                            var key = prop_keys[index];\n                            if (key instanceof AST_Node) return prop;\n                            if (key === \"__proto__\") return prop;\n                            if (drop_keys.has(key)) {\n                                var mapped = drop_keys.get(key);\n                                if (!mapped) return prop;\n                                if (mapped === prop) return prop_map.get(key) || List.skip;\n                            } else if (node.rest) {\n                                return prop;\n                            }\n                            var trimmed = prop.value.drop_side_effect_free(compressor);\n                            if (trimmed) {\n                                prop.value = trimmed;\n                                return prop;\n                            }\n                            return retain_key(prop) ? make_node(AST_ObjectKeyVal, prop, {\n                                key: prop.key,\n                                value: make_node(AST_Number, prop, { value: 0 }),\n                            }) : List.skip;\n                        });\n                    }\n                    if (value && !node.rest) switch (properties.length) {\n                      case 0:\n                        if (node === root) break;\n                        if (value.may_throw_on_access(compressor, true)) break;\n                        if (drop) value = value.drop_side_effect_free(compressor);\n                        return null;\n                      case 1:\n                        if (!drop) break;\n                        if (!unwind) break;\n                        if (node === root) break;\n                        var prop = properties[0];\n                        if (prop.key instanceof AST_Node) break;\n                        if (prop.value.has_side_effects(compressor)) break;\n                        if (value.has_side_effects(compressor) && prop.value.match_symbol(function(node) {\n                            return node instanceof AST_PropAccess;\n                        })) break;\n                        value = is_identifier_string(prop.key) ? make_node(AST_Dot, node, {\n                            expression: value,\n                            property: prop.key,\n                        }) : make_node(AST_Sub, node, {\n                            expression: value,\n                            property: make_node_from_constant(prop.key, prop),\n                        });\n                        return prop.value;\n                    }\n                    node.properties = properties;\n                    return node;\n                }\n                if (node instanceof AST_Hole) {\n                    node = null;\n                } else {\n                    node = process(node);\n                }\n                if (!node && drop && value) value = value.drop_side_effect_free(compressor);\n                return node;\n            });\n            return {\n                name: node.transform(trimmer),\n                value: value,\n            };\n\n            function retain_key(prop) {\n                return prop.key instanceof AST_Node && prop.key.has_side_effects(compressor);\n            }\n\n            function clear_write_only(node) {\n                if (node instanceof AST_Assign) {\n                    node.write_only = false;\n                    clear_write_only(node.right);\n                } else if (node instanceof AST_Binary) {\n                    if (!lazy_op[node.operator]) return;\n                    clear_write_only(node.left);\n                    clear_write_only(node.right);\n                } else if (node instanceof AST_Conditional) {\n                    clear_write_only(node.consequent);\n                    clear_write_only(node.alternative);\n                } else if (node instanceof AST_Sequence) {\n                    clear_write_only(node.tail_node());\n                } else if (node instanceof AST_Unary) {\n                    node.write_only = false;\n                }\n            }\n\n            function retain_lhs(node) {\n                if (node instanceof AST_DefaultValue) return retain_lhs(node.name);\n                if (node instanceof AST_Destructured) {\n                    if (value === null) {\n                        value = make_node(AST_Number, node, { value: 0 });\n                    } else if (value) {\n                        if (value.may_throw_on_access(compressor, true)) {\n                            value = make_node(AST_Array, node, {\n                                elements: value instanceof AST_Sequence ? value.expressions : [ value ],\n                            });\n                        } else {\n                            clear_write_only(value);\n                        }\n                    }\n                    return make_node(AST_DestructuredObject, node, { properties: [] });\n                }\n                node.unused = null;\n                return node;\n            }\n        }\n    });\n\n    AST_Scope.DEFMETHOD(\"hoist_declarations\", function(compressor) {\n        if (compressor.has_directive(\"use asm\")) return;\n        var hoist_funs = compressor.option(\"hoist_funs\");\n        var hoist_vars = compressor.option(\"hoist_vars\");\n        var self = this;\n        if (hoist_vars) {\n            // let's count var_decl first, we seem to waste a lot of\n            // space if we hoist `var` when there's only one.\n            var var_decl = 0;\n            self.walk(new TreeWalker(function(node) {\n                if (var_decl > 1) return true;\n                if (node instanceof AST_ExportDeclaration) return true;\n                if (node instanceof AST_Scope && node !== self) return true;\n                if (node instanceof AST_Var) {\n                    var_decl++;\n                    return true;\n                }\n            }));\n            if (var_decl <= 1) hoist_vars = false;\n        }\n        if (!hoist_funs && !hoist_vars) return;\n        var consts = new Dictionary();\n        var dirs = [];\n        var hoisted = [];\n        var vars = new Dictionary();\n        var tt = new TreeTransformer(function(node, descend, in_list) {\n            if (node === self) return;\n            if (node instanceof AST_Directive) {\n                dirs.push(node);\n                return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n            }\n            if (node instanceof AST_LambdaDefinition) {\n                if (!hoist_funs) return node;\n                var p = tt.parent();\n                if (p instanceof AST_ExportDeclaration) return node;\n                if (p instanceof AST_ExportDefault) return node;\n                if (p !== self && compressor.has_directive(\"use strict\")) return node;\n                hoisted.push(node);\n                return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n            }\n            if (node instanceof AST_Var) {\n                if (!hoist_vars) return node;\n                var p = tt.parent();\n                if (p instanceof AST_ExportDeclaration) return node;\n                if (!all(node.definitions, function(defn) {\n                    var sym = defn.name;\n                    return sym instanceof AST_SymbolVar\n                        && !consts.has(sym.name)\n                        && self.find_variable(sym.name) === sym.definition();\n                })) return node;\n                node.definitions.forEach(function(defn) {\n                    var name = defn.name.name;\n                    if (!vars.has(name)) vars.set(name, defn);\n                });\n                var seq = node.to_assignments();\n                if (p instanceof AST_ForEnumeration && p.init === node) {\n                    if (seq) return seq;\n                    var sym = node.definitions[0].name;\n                    return make_node(AST_SymbolRef, sym);\n                }\n                if (p instanceof AST_For && p.init === node) return seq;\n                if (!seq) return in_list ? List.skip : make_node(AST_EmptyStatement, node);\n                return make_node(AST_SimpleStatement, node, { body: seq });\n            }\n            if (node instanceof AST_Scope) return node;\n            if (node instanceof AST_SymbolConst) {\n                consts.set(node.name, true);\n                return node;\n            }\n        });\n        self.transform(tt);\n        if (vars.size() > 0) {\n            // collect only vars which don't show up in self's arguments list\n            var defns = [];\n            if (self instanceof AST_Lambda) self.each_argname(function(argname) {\n                if (all(argname.definition().references, function(ref) {\n                    return !ref.in_arg;\n                })) vars.del(argname.name);\n            });\n            vars.each(function(defn) {\n                var name = defn.name;\n                defn = defn.clone();\n                defn.name = name.clone();\n                defn.value = null;\n                defns.push(defn);\n                var orig = name.definition().orig;\n                orig.splice(orig.indexOf(name), 0, defn.name);\n            });\n            if (defns.length > 0) hoisted.push(make_node(AST_Var, self, { definitions: defns }));\n        }\n        self.body = dirs.concat(hoisted, self.body);\n    });\n\n    function scan_local_returns(fn, transform) {\n        fn.walk(new TreeWalker(function(node) {\n            if (node instanceof AST_Return) {\n                transform(node);\n                return true;\n            }\n            if (node instanceof AST_Scope && node !== fn) return true;\n        }));\n    }\n\n    function map_self_returns(fn) {\n        var map = Object.create(null);\n        scan_local_returns(fn, function(node) {\n            var value = node.value;\n            if (value) value = value.tail_node();\n            if (value instanceof AST_SymbolRef) {\n                var id = value.definition().id;\n                map[id] = (map[id] || 0) + 1;\n            }\n        });\n        return map;\n    }\n\n    function can_trim_returns(def, self_returns, compressor) {\n        if (compressor.exposed(def)) return false;\n        switch (def.references.length - def.replaced - (self_returns[def.id] || 0)) {\n          case def.drop_return:\n            return \"d\";\n          case def.bool_return:\n            return true;\n        }\n    }\n\n    function process_boolean_returns(fn, compressor) {\n        scan_local_returns(fn, function(node) {\n            node.in_bool = true;\n            var value = node.value;\n            if (value) {\n                var ev = fuzzy_eval(compressor, value);\n                if (!ev) {\n                    value = value.drop_side_effect_free(compressor);\n                    node.value = value ? make_sequence(node.value, [\n                        value,\n                        make_node(AST_Number, node.value, { value: 0 }),\n                    ]) : null;\n                } else if (!(ev instanceof AST_Node)) {\n                    value = value.drop_side_effect_free(compressor);\n                    node.value = value ? make_sequence(node.value, [\n                        value,\n                        make_node(AST_Number, node.value, { value: 1 }),\n                    ]) : make_node(AST_Number, node.value, { value: 1 });\n                }\n            }\n        });\n    }\n\n    AST_Scope.DEFMETHOD(\"process_returns\", noop);\n    AST_Defun.DEFMETHOD(\"process_returns\", function(compressor) {\n        if (!compressor.option(\"booleans\")) return;\n        if (compressor.parent() instanceof AST_ExportDefault) return;\n        switch (can_trim_returns(this.name.definition(), map_self_returns(this), compressor)) {\n          case \"d\":\n            drop_returns(compressor, this, true);\n            break;\n          case true:\n            process_boolean_returns(this, compressor);\n            break;\n        }\n    });\n    AST_Function.DEFMETHOD(\"process_returns\", function(compressor) {\n        if (!compressor.option(\"booleans\")) return;\n        var drop = true;\n        var self_returns = map_self_returns(this);\n        if (this.name && !can_trim(this.name.definition())) return;\n        var parent = compressor.parent();\n        if (parent instanceof AST_Assign) {\n            if (parent.operator != \"=\") return;\n            var sym = parent.left;\n            if (!(sym instanceof AST_SymbolRef)) return;\n            if (!can_trim(sym.definition())) return;\n        } else if (parent instanceof AST_Call && parent.expression !== this) {\n            var exp = parent.expression;\n            if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();\n            if (!(exp instanceof AST_Lambda)) return;\n            if (exp.uses_arguments || exp.pinned()) return;\n            var args = parent.args, sym;\n            for (var i = 0; i < args.length; i++) {\n                var arg = args[i];\n                if (arg === this) {\n                    sym = exp.argnames[i];\n                    if (!sym && exp.rest) return;\n                    break;\n                }\n                if (arg instanceof AST_Spread) return;\n            }\n            if (sym instanceof AST_DefaultValue) sym = sym.name;\n            if (sym instanceof AST_SymbolFunarg && !can_trim(sym.definition())) return;\n        } else if (parent.TYPE == \"Call\") {\n            compressor.pop();\n            var in_bool = compressor.in_boolean_context();\n            compressor.push(this);\n            switch (in_bool) {\n              case true:\n                drop = false;\n              case \"d\":\n                break;\n              default:\n                return;\n            }\n        } else return;\n        if (drop) {\n            drop_returns(compressor, this, true);\n        } else {\n            process_boolean_returns(this, compressor);\n        }\n\n        function can_trim(def) {\n            switch (can_trim_returns(def, self_returns, compressor)) {\n              case true:\n                drop = false;\n              case \"d\":\n                return true;\n            }\n        }\n    });\n\n    AST_BlockScope.DEFMETHOD(\"var_names\", function() {\n        var var_names = this._var_names;\n        if (!var_names) {\n            this._var_names = var_names = new Dictionary();\n            this.enclosed.forEach(function(def) {\n                var_names.set(def.name, true);\n            });\n            this.variables.each(function(def, name) {\n                var_names.set(name, true);\n            });\n        }\n        return var_names;\n    });\n\n    AST_Scope.DEFMETHOD(\"make_var\", function(type, orig, prefix) {\n        var scopes = [ this ];\n        if (orig instanceof AST_SymbolDeclaration) orig.definition().references.forEach(function(ref) {\n            var s = ref.scope;\n            do {\n                if (!push_uniq(scopes, s)) return;\n                s = s.parent_scope;\n            } while (s && s !== this);\n        });\n        prefix = prefix.replace(/^[^a-z_$]|[^a-z0-9_$]/gi, \"_\");\n        var name = prefix;\n        for (var i = 0; !all(scopes, function(scope) {\n            return !scope.var_names().has(name);\n        }); i++) name = prefix + \"$\" + i;\n        var sym = make_node(type, orig, {\n            name: name,\n            scope: this,\n        });\n        var def = this.def_variable(sym);\n        scopes.forEach(function(scope) {\n            scope.enclosed.push(def);\n            scope.var_names().set(name, true);\n        });\n        return sym;\n    });\n\n    AST_Scope.DEFMETHOD(\"hoist_properties\", function(compressor) {\n        if (!compressor.option(\"hoist_props\") || compressor.has_directive(\"use asm\")) return;\n        var self = this;\n        if (is_arrow(self) && self.value) return;\n        var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false;\n        var defs_by_id = Object.create(null);\n        var tt = new TreeTransformer(function(node, descend) {\n            if (node instanceof AST_Assign) {\n                if (node.operator != \"=\") return;\n                if (!node.write_only) return;\n                if (!can_hoist(node.left, node.right, 1)) return;\n                descend(node, tt);\n                var defs = new Dictionary();\n                var assignments = [];\n                var decls = [];\n                node.right.properties.forEach(function(prop) {\n                    var decl = make_sym(AST_SymbolVar, node.left, prop.key);\n                    decls.push(make_node(AST_VarDef, node, {\n                        name: decl,\n                        value: null,\n                    }));\n                    var sym = make_node(AST_SymbolRef, node, {\n                        name: decl.name,\n                        scope: self,\n                        thedef: decl.definition(),\n                    });\n                    sym.reference();\n                    assignments.push(make_node(AST_Assign, node, {\n                        operator: \"=\",\n                        left: sym,\n                        right: prop.value,\n                    }));\n                });\n                defs.value = node.right;\n                defs_by_id[node.left.definition().id] = defs;\n                self.body.splice(self.body.indexOf(tt.stack[1]) + 1, 0, make_node(AST_Var, node, {\n                    definitions: decls,\n                }));\n                return make_sequence(node, assignments);\n            }\n            if (node instanceof AST_Scope) {\n                if (node === self) return;\n                var parent = tt.parent();\n                if (parent.TYPE == \"Call\" && parent.expression === node) return;\n                return node;\n            }\n            if (node instanceof AST_VarDef) {\n                if (!can_hoist(node.name, node.value, 0)) return;\n                descend(node, tt);\n                var defs = new Dictionary();\n                var var_defs = [];\n                var decl = node.clone();\n                decl.value = node.name instanceof AST_SymbolConst ? make_node(AST_Number, node, { value: 0 }) : null;\n                var_defs.push(decl);\n                node.value.properties.forEach(function(prop) {\n                    var_defs.push(make_node(AST_VarDef, node, {\n                        name: make_sym(node.name.CTOR, node.name, prop.key),\n                        value: prop.value,\n                    }));\n                });\n                defs.value = node.value;\n                defs_by_id[node.name.definition().id] = defs;\n                return List.splice(var_defs);\n            }\n\n            function make_sym(type, sym, key) {\n                var new_var = self.make_var(type, sym, sym.name + \"_\" + key);\n                defs.set(key, new_var.definition());\n                return new_var;\n            }\n        });\n        self.transform(tt);\n        self.transform(new TreeTransformer(function(node, descend) {\n            if (node instanceof AST_PropAccess) {\n                if (!(node.expression instanceof AST_SymbolRef)) return;\n                var defs = defs_by_id[node.expression.definition().id];\n                if (!defs) return;\n                if (node.expression.fixed_value() !== defs.value) return;\n                var def = defs.get(node.get_property());\n                var sym = make_node(AST_SymbolRef, node, {\n                    name: def.name,\n                    scope: node.expression.scope,\n                    thedef: def,\n                });\n                sym.reference();\n                return sym;\n            }\n            if (node instanceof AST_SymbolRef) {\n                var defs = defs_by_id[node.definition().id];\n                if (!defs) return;\n                if (node.fixed_value() !== defs.value) return;\n                return make_node(AST_Object, node, { properties: [] });\n            }\n        }));\n\n        function can_hoist(sym, right, count) {\n            if (!(sym instanceof AST_Symbol)) return;\n            var def = sym.definition();\n            if (def.assignments != count) return;\n            if (def.references.length - def.replaced == count) return;\n            if (def.single_use) return;\n            if (self.find_variable(sym.name) !== def) return;\n            if (top_retain(def)) return;\n            if (sym.fixed_value() !== right) return;\n            var fixed = sym.fixed || def.fixed;\n            if (fixed.direct_access) return;\n            if (fixed.escaped && fixed.escaped.depth == 1) return;\n            return right instanceof AST_Object\n                && right.properties.length > 0\n                && can_drop_symbol(sym, compressor)\n                && all(right.properties, function(prop) {\n                    return can_hoist_property(prop) && prop.key !== \"__proto__\";\n                });\n        }\n    });\n\n    function fn_name_unused(fn, compressor) {\n        if (!fn.name || !compressor.option(\"ie\")) return true;\n        var def = fn.name.definition();\n        if (compressor.exposed(def)) return false;\n        return all(def.references, function(sym) {\n            return !(sym instanceof AST_SymbolRef);\n        });\n    }\n\n    function drop_returns(compressor, exp, ignore_name) {\n        if (!(exp instanceof AST_Lambda)) return;\n        var arrow = is_arrow(exp);\n        var async = is_async(exp);\n        var changed = false;\n        var drop_body = false;\n        if (arrow && compressor.option(\"arrows\")) {\n            if (!exp.value) {\n                drop_body = true;\n            } else if (!async || needs_enqueuing(compressor, exp.value)) {\n                var dropped = exp.value.drop_side_effect_free(compressor);\n                if (dropped !== exp.value) {\n                    changed = true;\n                    exp.value = dropped;\n                }\n            }\n        } else if (!is_generator(exp)) {\n            if (!ignore_name && exp.name) {\n                var def = exp.name.definition();\n                drop_body = def.references.length == def.replaced;\n            } else {\n                drop_body = true;\n            }\n        }\n        if (drop_body) {\n            exp.process_expression(false, function(node) {\n                var value = node.value;\n                if (value) {\n                    if (async && !needs_enqueuing(compressor, value)) return node;\n                    value = value.drop_side_effect_free(compressor, true);\n                }\n                changed = true;\n                if (!value) return make_node(AST_EmptyStatement, node);\n                return make_node(AST_SimpleStatement, node, { body: value });\n            });\n            scan_local_returns(exp, function(node) {\n                var value = node.value;\n                if (value) {\n                    if (async && !needs_enqueuing(compressor, value)) return;\n                    var dropped = value.drop_side_effect_free(compressor);\n                    if (dropped !== value) {\n                        changed = true;\n                        if (dropped && async && !needs_enqueuing(compressor, dropped)) {\n                            dropped = dropped.negate(compressor);\n                        }\n                        node.value = dropped;\n                    }\n                }\n            });\n        }\n        if (async && compressor.option(\"awaits\")) {\n            if (drop_body) exp.process_expression(\"awaits\", function(node) {\n                var body = node.body;\n                if (body instanceof AST_Await) {\n                    if (needs_enqueuing(compressor, body.expression)) {\n                        changed = true;\n                        body = body.expression.drop_side_effect_free(compressor, true);\n                        if (!body) return make_node(AST_EmptyStatement, node);\n                        node.body = body;\n                    }\n                } else if (body instanceof AST_Sequence) {\n                    var exprs = body.expressions;\n                    for (var i = exprs.length; --i >= 0;) {\n                        var tail = exprs[i];\n                        if (!(tail instanceof AST_Await)) break;\n                        var value = tail.expression;\n                        if (!needs_enqueuing(compressor, value)) break;\n                        changed = true;\n                        if (exprs[i] = value.drop_side_effect_free(compressor)) break;\n                    }\n                    switch (i) {\n                      case -1:\n                        return make_node(AST_EmptyStatement, node);\n                      case 0:\n                        node.body = exprs[0];\n                        break;\n                      default:\n                        exprs.length = i + 1;\n                        break;\n                    }\n                }\n                return node;\n            });\n            var abort = !drop_body && exp.name || arrow && exp.value && !needs_enqueuing(compressor, exp.value);\n            var tw = new TreeWalker(function(node) {\n                if (abort) return true;\n                if (tw.parent() === exp && node.may_throw(compressor)) return abort = true;\n                if (node instanceof AST_Await) return abort = true;\n                if (node instanceof AST_ForAwaitOf) return abort = true;\n                if (node instanceof AST_Return) {\n                    if (node.value && !needs_enqueuing(compressor, node.value)) return abort = true;\n                    return;\n                }\n                if (node instanceof AST_Scope && node !== exp) return true;\n            });\n            exp.walk(tw);\n            if (!abort) {\n                var ctor;\n                switch (exp.CTOR) {\n                  case AST_AsyncArrow:\n                    ctor = AST_Arrow;\n                    break;\n                  case AST_AsyncFunction:\n                    ctor = AST_Function;\n                    break;\n                  case AST_AsyncGeneratorFunction:\n                    ctor = AST_GeneratorFunction;\n                    break;\n                }\n                return make_node(ctor, exp);\n            }\n        }\n        return changed && exp.clone();\n    }\n\n    // drop_side_effect_free()\n    // remove side-effect-free parts which only affects return value\n    (function(def) {\n        // Drop side-effect-free elements from an array of expressions.\n        // Returns an array of expressions with side-effects or null\n        // if all elements were dropped. Note: original array may be\n        // returned if nothing changed.\n        function trim(nodes, compressor, first_in_statement, spread) {\n            var len = nodes.length;\n            var ret = [], changed = false;\n            for (var i = 0; i < len; i++) {\n                var node = nodes[i];\n                var trimmed;\n                if (spread && node instanceof AST_Spread) {\n                    trimmed = spread(node, compressor, first_in_statement);\n                } else {\n                    trimmed = node.drop_side_effect_free(compressor, first_in_statement);\n                }\n                if (trimmed !== node) changed = true;\n                if (trimmed) {\n                    ret.push(trimmed);\n                    first_in_statement = false;\n                }\n            }\n            return ret.length ? changed ? ret : nodes : null;\n        }\n        function array_spread(node, compressor, first_in_statement) {\n            var exp = node.expression;\n            if (!exp.is_string(compressor)) return node;\n            return exp.drop_side_effect_free(compressor, first_in_statement);\n        }\n        function convert_spread(node) {\n            return node instanceof AST_Spread ? make_node(AST_Array, node, { elements: [ node ] }) : node;\n        }\n        def(AST_Node, return_this);\n        def(AST_Accessor, return_null);\n        def(AST_Array, function(compressor, first_in_statement) {\n            var values = trim(this.elements, compressor, first_in_statement, array_spread);\n            if (!values) return null;\n            if (values === this.elements && all(values, function(node) {\n                return node instanceof AST_Spread;\n            })) return this;\n            return make_sequence(this, values.map(convert_spread));\n        });\n        def(AST_Assign, function(compressor) {\n            var left = this.left;\n            if (left instanceof AST_PropAccess) {\n                var expr = left.expression;\n                if (expr.may_throw_on_access(compressor, true)) return this;\n                if (compressor.has_directive(\"use strict\") && expr.is_constant()) return this;\n            }\n            if (left.has_side_effects(compressor)) return this;\n            if (lazy_op[this.operator.slice(0, -1)]) return this;\n            this.write_only = true;\n            if (!root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) return this;\n            return this.right.drop_side_effect_free(compressor);\n        });\n        def(AST_Await, function(compressor) {\n            if (!compressor.option(\"awaits\")) return this;\n            var exp = this.expression;\n            if (!needs_enqueuing(compressor, exp)) return this;\n            if (exp instanceof AST_UnaryPrefix && exp.operator == \"!\") exp = exp.expression;\n            var dropped = exp.drop_side_effect_free(compressor);\n            if (dropped === exp) return this;\n            if (!dropped) {\n                dropped = make_node(AST_Number, exp, { value: 0 });\n            } else if (!needs_enqueuing(compressor, dropped)) {\n                dropped = dropped.negate(compressor);\n            }\n            var node = this.clone();\n            node.expression = dropped;\n            return node;\n        });\n        def(AST_Binary, function(compressor, first_in_statement) {\n            var left = this.left;\n            var right = this.right;\n            var op = this.operator;\n            if (!can_drop_op(this, compressor)) {\n                var lhs = left.drop_side_effect_free(compressor, first_in_statement);\n                if (lhs === left) return this;\n                var node = this.clone();\n                if (lhs) {\n                    node.left = lhs;\n                } else if (op == \"instanceof\" && !left.is_constant()) {\n                    node.left = make_node(AST_Array, left, { elements: [] });\n                } else {\n                    node.left = make_node(AST_Number, left, { value: 0 });\n                }\n                return node;\n            }\n            var rhs = right.drop_side_effect_free(compressor, first_in_statement);\n            if (!rhs) return left.drop_side_effect_free(compressor, first_in_statement);\n            if (lazy_op[op] && rhs.has_side_effects(compressor)) {\n                var node = this;\n                if (rhs !== right) {\n                    node = node.clone();\n                    node.right = rhs.drop_side_effect_free(compressor);\n                }\n                if (op == \"??\") return node;\n                var negated = node.clone();\n                negated.operator = op == \"&&\" ? \"||\" : \"&&\";\n                negated.left = left.negate(compressor, first_in_statement);\n                var negated_rhs = negated.right.tail_node();\n                if (negated_rhs instanceof AST_Binary && negated.operator == negated_rhs.operator) swap_chain(negated);\n                var best = first_in_statement ? best_of_statement : best_of_expression;\n                return op == \"&&\" ? best(node, negated) : best(negated, node);\n            }\n            var lhs = left.drop_side_effect_free(compressor, first_in_statement);\n            if (!lhs) return rhs;\n            rhs = rhs.drop_side_effect_free(compressor);\n            if (!rhs) return lhs;\n            return make_sequence(this, [ lhs, rhs ]);\n        });\n        function assign_this_only(fn, compressor) {\n            fn.new = true;\n            var result = all(fn.body, function(stat) {\n                return !stat.has_side_effects(compressor);\n            }) && all(fn.argnames, function(argname) {\n                return !argname.match_symbol(return_false);\n            }) && !(fn.rest && fn.rest.match_symbol(return_false));\n            fn.new = false;\n            return result;\n        }\n        def(AST_Call, function(compressor, first_in_statement) {\n            var self = this;\n            if (self.is_expr_pure(compressor)) {\n                if (self.pure) AST_Node.warn(\"Dropping __PURE__ call [{start}]\", self);\n                var args = trim(self.args, compressor, first_in_statement, array_spread);\n                return args && make_sequence(self, args.map(convert_spread));\n            }\n            var exp = self.expression;\n            if (self.is_call_pure(compressor)) {\n                var exprs = self.args.slice();\n                exprs.unshift(exp.expression);\n                exprs = trim(exprs, compressor, first_in_statement, array_spread);\n                return exprs && make_sequence(self, exprs.map(convert_spread));\n            }\n            if (compressor.option(\"yields\") && is_generator(exp) && fn_name_unused(exp, compressor)) {\n                var call = self.clone();\n                call.expression = make_node(AST_Function, exp);\n                call.expression.body = [];\n                return call;\n            }\n            var dropped = drop_returns(compressor, exp);\n            if (dropped) {\n                // always shallow clone to ensure stripping of negated IIFEs\n                self = self.clone();\n                self.expression = dropped;\n                // avoid extraneous traversal\n                if (exp._squeezed) self.expression._squeezed = true;\n            }\n            if (self instanceof AST_New) {\n                var fn = exp;\n                if (fn instanceof AST_SymbolRef) fn = fn.fixed_value();\n                if (fn instanceof AST_Lambda) {\n                    if (assign_this_only(fn, compressor)) {\n                        var exprs = self.args.slice();\n                        exprs.unshift(exp);\n                        exprs = trim(exprs, compressor, first_in_statement, array_spread);\n                        return exprs && make_sequence(self, exprs.map(convert_spread));\n                    }\n                    if (!fn.contains_this()) {\n                        self = make_node(AST_Call, self);\n                        self.expression = self.expression.clone();\n                        self.args = self.args.slice();\n                    }\n                }\n            }\n            self.call_only = true;\n            return self;\n        });\n        def(AST_ClassExpression, function(compressor, first_in_statement) {\n            var self = this;\n            var exprs = [], values = [], init = 0;\n            var props = self.properties;\n            for (var i = 0; i < props.length; i++) {\n                var prop = props[i];\n                if (prop.key instanceof AST_Node) exprs.push(prop.key);\n                if (!is_static_field_or_init(prop)) continue;\n                var value = prop.value;\n                if (!value.has_side_effects(compressor)) continue;\n                if (value.contains_this()) return self;\n                if (prop instanceof AST_ClassInit) {\n                    init++;\n                    values.push(prop);\n                } else {\n                    values.push(value);\n                }\n            }\n            var base = self.extends;\n            if (base) {\n                if (base instanceof AST_SymbolRef) base = base.fixed_value();\n                base = !safe_for_extends(base);\n                if (!base) exprs.unshift(self.extends);\n            }\n            exprs = trim(exprs, compressor, first_in_statement);\n            if (exprs) first_in_statement = false;\n            values = trim(values, compressor, first_in_statement);\n            if (!exprs) {\n                if (!base && !values && !self.name) return null;\n                exprs = [];\n            }\n            if (base || self.name || !compressor.has_directive(\"use strict\")) {\n                var node = to_class_expr(self);\n                if (!base) node.extends = null;\n                node.properties = [];\n                if (values) {\n                    if (values.length == init) {\n                        if (exprs.length) values.unshift(make_node(AST_ClassField, self, {\n                            key: make_sequence(self, exprs),\n                            value: null,\n                        }));\n                        node.properties = values;\n                    } else node.properties.push(make_node(AST_ClassField, self, {\n                        static: true,\n                        key: exprs.length ? make_sequence(self, exprs) : \"c\",\n                        value: make_value(),\n                    }));\n                } else if (exprs.length) node.properties.push(make_node(AST_ClassMethod, self, {\n                    key: make_sequence(self, exprs),\n                    value: make_node(AST_Function, self, {\n                        argnames: [],\n                        body: [],\n                    }).init_vars(node),\n                }));\n                return node;\n            }\n            if (values) exprs.push(make_node(AST_Call, self, {\n                expression: make_node(AST_Arrow, self, {\n                    argnames: [],\n                    body: [],\n                    value: make_value(),\n                }).init_vars(self.parent_scope, self),\n                args: [],\n            }));\n            return make_sequence(self, exprs);\n\n            function make_value() {\n                return make_sequence(self, values.map(function(node) {\n                    if (!(node instanceof AST_ClassInit)) return node;\n                    var fn = make_node(AST_Arrow, node.value);\n                    fn.argnames = [];\n                    return make_node(AST_Call, node, {\n                        expression: fn,\n                        args: [],\n                    });\n                }));\n            }\n        });\n        def(AST_Conditional, function(compressor) {\n            var consequent = this.consequent.drop_side_effect_free(compressor);\n            var alternative = this.alternative.drop_side_effect_free(compressor);\n            if (consequent === this.consequent && alternative === this.alternative) return this;\n            var exprs;\n            if (compressor.option(\"ie\")) {\n                exprs = [];\n                if (consequent instanceof AST_Function) {\n                    exprs.push(consequent);\n                    consequent = null;\n                }\n                if (alternative instanceof AST_Function) {\n                    exprs.push(alternative);\n                    alternative = null;\n                }\n            }\n            var node;\n            if (!consequent) {\n                node = alternative ? make_node(AST_Binary, this, {\n                    operator: \"||\",\n                    left: this.condition,\n                    right: alternative,\n                }) : this.condition.drop_side_effect_free(compressor);\n            } else if (!alternative) {\n                node = make_node(AST_Binary, this, {\n                    operator: \"&&\",\n                    left: this.condition,\n                    right: consequent,\n                });\n            } else {\n                node = this.clone();\n                node.consequent = consequent;\n                node.alternative = alternative;\n            }\n            if (!exprs) return node;\n            if (node) exprs.push(node);\n            return exprs.length == 0 ? null : make_sequence(this, exprs);\n        });\n        def(AST_Constant, return_null);\n        def(AST_Dot, function(compressor, first_in_statement) {\n            var expr = this.expression;\n            if (expr.may_throw_on_access(compressor)) return this;\n            return expr.drop_side_effect_free(compressor, first_in_statement);\n        });\n        def(AST_Function, function(compressor) {\n            return fn_name_unused(this, compressor) ? null : this;\n        });\n        def(AST_LambdaExpression, return_null);\n        def(AST_Object, function(compressor, first_in_statement) {\n            var exprs = [];\n            this.properties.forEach(function(prop) {\n                if (prop instanceof AST_Spread) {\n                    exprs.push(prop);\n                } else {\n                    if (prop.key instanceof AST_Node) exprs.push(prop.key);\n                    exprs.push(prop.value);\n                }\n            });\n            var values = trim(exprs, compressor, first_in_statement, function(node, compressor, first_in_statement) {\n                var exp = node.expression;\n                return exp.safe_to_spread() ? exp.drop_side_effect_free(compressor, first_in_statement) : node;\n            });\n            if (!values) return null;\n            if (values === exprs && !all(values, function(node) {\n                return !(node instanceof AST_Spread);\n            })) return this;\n            return make_sequence(this, values.map(function(node) {\n                return node instanceof AST_Spread ? make_node(AST_Object, node, { properties: [ node ] }) : node;\n            }));\n        });\n        def(AST_ObjectIdentity, return_null);\n        def(AST_Sequence, function(compressor, first_in_statement) {\n            var expressions = trim(this.expressions, compressor, first_in_statement);\n            if (!expressions) return null;\n            var end = expressions.length - 1;\n            var last = expressions[end];\n            if (compressor.option(\"awaits\") && end > 0 && last instanceof AST_Await && last.expression.is_constant()) {\n                expressions = expressions.slice(0, -1);\n                end--;\n                var expr = expressions[end];\n                last.expression = needs_enqueuing(compressor, expr) ? expr : expr.negate(compressor);\n                expressions[end] = last;\n            }\n            var assign, cond, lhs;\n            if (compressor.option(\"conditionals\")\n                && end > 0\n                && (assign = expressions[end - 1]) instanceof AST_Assign\n                && assign.operator == \"=\"\n                && (lhs = assign.left) instanceof AST_SymbolRef\n                && (cond = to_conditional_assignment(compressor, lhs.definition(), assign.right, last))) {\n                assign = assign.clone();\n                assign.right = cond;\n                expressions = expressions.slice(0, -2);\n                expressions.push(assign.drop_side_effect_free(compressor, first_in_statement));\n            }\n            return expressions === this.expressions ? this : make_sequence(this, expressions);\n        });\n        def(AST_Sub, function(compressor, first_in_statement) {\n            var self = this;\n            var expr = self.expression;\n            if (expr.may_throw_on_access(compressor)) return self;\n            var prop = self.property;\n            if (self.optional) {\n                prop = prop.drop_side_effect_free(compressor);\n                if (!prop) return expr.drop_side_effect_free(compressor, first_in_statement);\n                self = self.clone();\n                self.property = prop;\n                return self;\n            }\n            expr = expr.drop_side_effect_free(compressor, first_in_statement);\n            if (!expr) return prop.drop_side_effect_free(compressor, first_in_statement);\n            prop = prop.drop_side_effect_free(compressor);\n            if (!prop) return expr;\n            return make_sequence(self, [ expr, prop ]);\n        });\n        def(AST_SymbolRef, function(compressor) {\n            return this.is_declared(compressor) && can_drop_symbol(this, compressor) ? null : this;\n        });\n        def(AST_Template, function(compressor, first_in_statement) {\n            var self = this;\n            if (self.is_expr_pure(compressor)) {\n                var expressions = self.expressions;\n                if (expressions.length == 0) return null;\n                return make_sequence(self, expressions).drop_side_effect_free(compressor, first_in_statement);\n            }\n            var tag = self.tag;\n            var dropped = drop_returns(compressor, tag);\n            if (dropped) {\n                // always shallow clone to signal internal changes\n                self = self.clone();\n                self.tag = dropped;\n                // avoid extraneous traversal\n                if (tag._squeezed) self.tag._squeezed = true;\n            }\n            return self;\n        });\n        def(AST_Unary, function(compressor, first_in_statement) {\n            var exp = this.expression;\n            if (unary_side_effects[this.operator]) {\n                this.write_only = !exp.has_side_effects(compressor);\n                return this;\n            }\n            if (this.operator == \"typeof\" && exp instanceof AST_SymbolRef && can_drop_symbol(exp, compressor)) {\n                return null;\n            }\n            var node = exp.drop_side_effect_free(compressor, first_in_statement);\n            if (first_in_statement && node && is_iife_call(node)) {\n                if (node === exp && this.operator == \"!\") return this;\n                return node.negate(compressor, first_in_statement);\n            }\n            return node;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"drop_side_effect_free\", func);\n    });\n\n    OPT(AST_SimpleStatement, function(self, compressor) {\n        if (compressor.option(\"side_effects\")) {\n            var body = self.body;\n            var node = body.drop_side_effect_free(compressor, true);\n            if (!node) {\n                AST_Node.warn(\"Dropping side-effect-free statement [{start}]\", self);\n                return make_node(AST_EmptyStatement, self);\n            }\n            if (node !== body) {\n                return make_node(AST_SimpleStatement, self, { body: node });\n            }\n        }\n        return self;\n    });\n\n    OPT(AST_While, function(self, compressor) {\n        return compressor.option(\"loops\") ? make_node(AST_For, self).optimize(compressor) : self;\n    });\n\n    function has_loop_control(loop, parent, type) {\n        if (!type) type = AST_LoopControl;\n        var found = false;\n        var tw = new TreeWalker(function(node) {\n            if (found || node instanceof AST_Scope) return true;\n            if (node instanceof type && tw.loopcontrol_target(node) === loop) {\n                return found = true;\n            }\n        });\n        if (parent instanceof AST_LabeledStatement) tw.push(parent);\n        tw.push(loop);\n        loop.body.walk(tw);\n        return found;\n    }\n\n    OPT(AST_Do, function(self, compressor) {\n        if (!compressor.option(\"loops\")) return self;\n        var cond = fuzzy_eval(compressor, self.condition);\n        if (!(cond instanceof AST_Node)) {\n            if (cond && !has_loop_control(self, compressor.parent(), AST_Continue)) return make_node(AST_For, self, {\n                body: make_node(AST_BlockStatement, self.body, {\n                    body: [\n                        self.body,\n                        make_node(AST_SimpleStatement, self.condition, { body: self.condition }),\n                    ],\n                }),\n            }).optimize(compressor);\n            if (!has_loop_control(self, compressor.parent())) return make_node(AST_BlockStatement, self.body, {\n                body: [\n                    self.body,\n                    make_node(AST_SimpleStatement, self.condition, { body: self.condition }),\n                ],\n            }).optimize(compressor);\n        }\n        if (self.body instanceof AST_BlockStatement && !has_loop_control(self, compressor.parent(), AST_Continue)) {\n            var body = self.body.body;\n            for (var i = body.length; --i >= 0;) {\n                var stat = body[i];\n                if (stat instanceof AST_If\n                    && !stat.alternative\n                    && stat.body instanceof AST_Break\n                    && compressor.loopcontrol_target(stat.body) === self) {\n                    if (has_block_scope_refs(stat.condition)) break;\n                    self.condition = make_node(AST_Binary, self, {\n                        operator: \"&&\",\n                        left: stat.condition.negate(compressor),\n                        right: self.condition,\n                    });\n                    body.splice(i, 1);\n                } else if (stat instanceof AST_SimpleStatement) {\n                    if (has_block_scope_refs(stat.body)) break;\n                    self.condition = make_sequence(self, [\n                        stat.body,\n                        self.condition,\n                    ]);\n                    body.splice(i, 1);\n                } else if (!is_declaration(stat, true)) {\n                    break;\n                }\n            }\n            self.body = trim_block(self.body, compressor.parent());\n        }\n        if (self.body instanceof AST_EmptyStatement) return make_node(AST_For, self).optimize(compressor);\n        if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, {\n            condition: make_sequence(self.condition, [\n                self.body.body,\n                self.condition,\n            ]),\n            body: make_node(AST_EmptyStatement, self),\n        }).optimize(compressor);\n        return self;\n\n        function has_block_scope_refs(node) {\n            var found = false;\n            node.walk(new TreeWalker(function(node) {\n                if (found) return true;\n                if (node instanceof AST_SymbolRef) {\n                    if (!member(node.definition(), self.enclosed)) found = true;\n                    return true;\n                }\n            }));\n            return found;\n        }\n    });\n\n    function if_break_in_loop(self, compressor) {\n        var first = first_statement(self.body);\n        if (compressor.option(\"dead_code\")\n            && (first instanceof AST_Break\n                || first instanceof AST_Continue && external_target(first)\n                || first instanceof AST_Exit)) {\n            var body = [];\n            if (is_statement(self.init)) {\n                body.push(self.init);\n            } else if (self.init) {\n                body.push(make_node(AST_SimpleStatement, self.init, { body: self.init }));\n            }\n            var retain = external_target(first) || first instanceof AST_Exit;\n            if (self.condition && retain) {\n                body.push(make_node(AST_If, self, {\n                    condition: self.condition,\n                    body: first,\n                    alternative: null,\n                }));\n            } else if (self.condition) {\n                body.push(make_node(AST_SimpleStatement, self.condition, { body: self.condition }));\n            } else if (retain) {\n                body.push(first);\n            }\n            extract_declarations_from_unreachable_code(compressor, self.body, body);\n            return make_node(AST_BlockStatement, self, { body: body });\n        }\n        if (first instanceof AST_If) {\n            var ab = first_statement(first.body);\n            if (ab instanceof AST_Break && !external_target(ab)) {\n                if (self.condition) {\n                    self.condition = make_node(AST_Binary, self.condition, {\n                        left: self.condition,\n                        operator: \"&&\",\n                        right: first.condition.negate(compressor),\n                    });\n                } else {\n                    self.condition = first.condition.negate(compressor);\n                }\n                var body = as_statement_array(first.alternative);\n                extract_declarations_from_unreachable_code(compressor, first.body, body);\n                return drop_it(body);\n            }\n            ab = first_statement(first.alternative);\n            if (ab instanceof AST_Break && !external_target(ab)) {\n                if (self.condition) {\n                    self.condition = make_node(AST_Binary, self.condition, {\n                        left: self.condition,\n                        operator: \"&&\",\n                        right: first.condition,\n                    });\n                } else {\n                    self.condition = first.condition;\n                }\n                var body = as_statement_array(first.body);\n                extract_declarations_from_unreachable_code(compressor, first.alternative, body);\n                return drop_it(body);\n            }\n        }\n        return self;\n\n        function first_statement(body) {\n            return body instanceof AST_BlockStatement ? body.body[0] : body;\n        }\n\n        function external_target(node) {\n            return compressor.loopcontrol_target(node) !== compressor.self();\n        }\n\n        function drop_it(rest) {\n            if (self.body instanceof AST_BlockStatement) {\n                self.body = self.body.clone();\n                self.body.body = rest.concat(self.body.body.slice(1));\n                self.body = self.body.transform(compressor);\n            } else {\n                self.body = make_node(AST_BlockStatement, self.body, { body: rest }).transform(compressor);\n            }\n            return if_break_in_loop(self, compressor);\n        }\n    }\n\n    OPT(AST_For, function(self, compressor) {\n        if (!compressor.option(\"loops\")) return self;\n        if (compressor.option(\"side_effects\")) {\n            if (self.init) self.init = self.init.drop_side_effect_free(compressor);\n            if (self.step) self.step = self.step.drop_side_effect_free(compressor);\n        }\n        if (self.condition) {\n            var cond = fuzzy_eval(compressor, self.condition);\n            if (!cond) {\n                if (compressor.option(\"dead_code\")) {\n                    var body = [];\n                    if (is_statement(self.init)) {\n                        body.push(self.init);\n                    } else if (self.init) {\n                        body.push(make_node(AST_SimpleStatement, self.init, { body: self.init }));\n                    }\n                    body.push(make_node(AST_SimpleStatement, self.condition, { body: self.condition }));\n                    extract_declarations_from_unreachable_code(compressor, self.body, body);\n                    return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n                }\n            } else if (!(cond instanceof AST_Node)) {\n                self.body = make_node(AST_BlockStatement, self.body, {\n                    body: [\n                        make_node(AST_SimpleStatement, self.condition, { body: self.condition }),\n                        self.body,\n                    ],\n                });\n                self.condition = null;\n            }\n        }\n        return if_break_in_loop(self, compressor);\n    });\n\n    OPT(AST_ForEnumeration, function(self, compressor) {\n        if (compressor.option(\"varify\") && is_lexical_definition(self.init)) {\n            var name = self.init.definitions[0].name;\n            if ((compressor.option(\"module\") || name instanceof AST_Destructured || name instanceof AST_SymbolLet)\n                && !name.match_symbol(function(node) {\n                    if (node instanceof AST_SymbolDeclaration) {\n                        var def = node.definition();\n                        return !same_scope(def) || may_overlap(compressor, def);\n                    }\n                }, true)) {\n                self.init = to_var(self.init, self.resolve());\n            } else if (self.init.can_letify(compressor, true)) {\n                self.init = to_let(self.init, self);\n            }\n        }\n        return self;\n    });\n\n    function mark_locally_defined(condition, consequent, alternative) {\n        if (condition instanceof AST_Sequence) condition = condition.tail_node();\n        if (!(condition instanceof AST_Binary)) return;\n        if (!(condition.left instanceof AST_String)) {\n            switch (condition.operator) {\n              case \"&&\":\n                mark_locally_defined(condition.left, consequent);\n                mark_locally_defined(condition.right, consequent);\n                break;\n              case \"||\":\n                mark_locally_defined(negate(condition.left), alternative);\n                mark_locally_defined(negate(condition.right), alternative);\n                break;\n            }\n            return;\n        }\n        if (!(condition.right instanceof AST_UnaryPrefix)) return;\n        if (condition.right.operator != \"typeof\") return;\n        var sym = condition.right.expression;\n        if (!is_undeclared_ref(sym)) return;\n        var body;\n        var undef = condition.left.value == \"undefined\";\n        switch (condition.operator) {\n          case \"==\":\n            body = undef ? alternative : consequent;\n            break;\n          case \"!=\":\n            body = undef ? consequent : alternative;\n            break;\n          default:\n            return;\n        }\n        if (!body) return;\n        var abort = false;\n        var def = sym.definition();\n        var fn;\n        var refs = [];\n        var scanned = [];\n        var tw = new TreeWalker(function(node, descend) {\n            if (abort) return true;\n            if (node instanceof AST_Assign) {\n                var ref = node.left;\n                if (!(ref instanceof AST_SymbolRef && ref.definition() === def)) return;\n                node.right.walk(tw);\n                switch (node.operator) {\n                  case \"=\":\n                  case \"&&=\":\n                    abort = true;\n                }\n                return true;\n            }\n            if (node instanceof AST_Call) {\n                descend();\n                fn = node.expression.tail_node();\n                var save;\n                if (fn instanceof AST_SymbolRef) {\n                    fn = fn.fixed_value();\n                    save = refs.length;\n                }\n                if (!(fn instanceof AST_Lambda)) {\n                    abort = true;\n                } else if (push_uniq(scanned, fn)) {\n                    fn.walk(tw);\n                }\n                if (save >= 0) refs.length = save;\n                return true;\n            }\n            if (node instanceof AST_DWLoop) {\n                var save = refs.length;\n                descend();\n                if (abort) refs.length = save;\n                return true;\n            }\n            if (node instanceof AST_For) {\n                if (node.init) node.init.walk(tw);\n                var save = refs.length;\n                if (node.condition) node.condition.walk(tw);\n                node.body.walk(tw);\n                if (node.step) node.step.walk(tw);\n                if (abort) refs.length = save;\n                return true;\n            }\n            if (node instanceof AST_ForEnumeration) {\n                node.object.walk(tw);\n                var save = refs.length;\n                node.init.walk(tw);\n                node.body.walk(tw);\n                if (abort) refs.length = save;\n                return true;\n            }\n            if (node instanceof AST_Scope) {\n                if (node === fn) return;\n                return true;\n            }\n            if (node instanceof AST_SymbolRef) {\n                if (node.definition() === def) refs.push(node);\n                return true;\n            }\n        });\n        body.walk(tw);\n        refs.forEach(function(ref) {\n            ref.defined = true;\n        });\n\n        function negate(node) {\n            if (!(node instanceof AST_Binary)) return;\n            switch (node.operator) {\n              case \"==\":\n                node = node.clone();\n                node.operator = \"!=\";\n                return node;\n              case \"!=\":\n                node = node.clone();\n                node.operator = \"==\";\n                return node;\n            }\n        }\n    }\n\n    function fuzzy_eval(compressor, node, nullish) {\n        if (node.truthy) return true;\n        if (is_undefined(node)) return undefined;\n        if (node.falsy && !nullish) return false;\n        if (node.is_truthy()) return true;\n        return node.evaluate(compressor, true);\n    }\n\n    function mark_duplicate_condition(compressor, node) {\n        var child;\n        var level = 0;\n        var negated = false;\n        var parent = compressor.self();\n        if (!is_statement(parent)) while (true) {\n            child = parent;\n            parent = compressor.parent(level++);\n            if (parent instanceof AST_Binary) {\n                switch (child) {\n                  case parent.left:\n                    if (lazy_op[parent.operator]) continue;\n                    break;\n                  case parent.right:\n                    if (match(parent.left)) switch (parent.operator) {\n                      case \"&&\":\n                        node[negated ? \"falsy\" : \"truthy\"] = true;\n                        break;\n                      case \"||\":\n                      case \"??\":\n                        node[negated ? \"truthy\" : \"falsy\"] = true;\n                        break;\n                    }\n                    break;\n                }\n            } else if (parent instanceof AST_Conditional) {\n                var cond = parent.condition;\n                if (cond === child) continue;\n                if (match(cond)) switch (child) {\n                  case parent.consequent:\n                    node[negated ? \"falsy\" : \"truthy\"] = true;\n                    break;\n                  case parent.alternative:\n                    node[negated ? \"truthy\" : \"falsy\"] = true;\n                    break;\n                }\n            } else if (parent instanceof AST_Exit) {\n                break;\n            } else if (parent instanceof AST_If) {\n                break;\n            } else if (parent instanceof AST_Sequence) {\n                if (parent.expressions[0] === child) continue;\n            } else if (parent instanceof AST_SimpleStatement) {\n                break;\n            }\n            return;\n        }\n        while (true) {\n            child = parent;\n            parent = compressor.parent(level++);\n            if (parent instanceof AST_BlockStatement) {\n                if (parent.body[0] === child) continue;\n            } else if (parent instanceof AST_If) {\n                if (match(parent.condition)) switch (child) {\n                  case parent.body:\n                    node[negated ? \"falsy\" : \"truthy\"] = true;\n                    break;\n                  case parent.alternative:\n                    node[negated ? \"truthy\" : \"falsy\"] = true;\n                    break;\n                }\n            }\n            return;\n        }\n\n        function match(cond) {\n            if (node.equals(cond)) return true;\n            if (!(cond instanceof AST_UnaryPrefix)) return false;\n            if (cond.operator != \"!\") return false;\n            if (!node.equals(cond.expression)) return false;\n            negated = true;\n            return true;\n        }\n    }\n\n    OPT(AST_If, function(self, compressor) {\n        if (is_empty(self.alternative)) self.alternative = null;\n\n        if (!compressor.option(\"conditionals\")) return self;\n        if (compressor.option(\"booleans\") && !self.condition.has_side_effects(compressor)) {\n            mark_duplicate_condition(compressor, self.condition);\n        }\n        // if condition can be statically determined, warn and drop\n        // one of the blocks.  note, statically determined implies\n        // “has no side effects”; also it doesn't work for cases like\n        // `x && true`, though it probably should.\n        if (compressor.option(\"dead_code\")) {\n            var cond = fuzzy_eval(compressor, self.condition);\n            if (!cond) {\n                AST_Node.warn(\"Condition always false [{start}]\", self.condition);\n                var body = [\n                    make_node(AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor),\n                ];\n                extract_declarations_from_unreachable_code(compressor, self.body, body);\n                if (self.alternative) body.push(self.alternative);\n                return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n            } else if (!(cond instanceof AST_Node)) {\n                AST_Node.warn(\"Condition always true [{start}]\", self.condition);\n                var body = [\n                    make_node(AST_SimpleStatement, self.condition, { body: self.condition }).transform(compressor),\n                    self.body,\n                ];\n                if (self.alternative) extract_declarations_from_unreachable_code(compressor, self.alternative, body);\n                return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n            }\n        }\n        var negated = self.condition.negate(compressor);\n        var self_condition_length = self.condition.print_to_string().length;\n        var negated_length = negated.print_to_string().length;\n        var negated_is_best = negated_length < self_condition_length;\n        if (self.alternative && negated_is_best) {\n            negated_is_best = false; // because we already do the switch here.\n            // no need to swap values of self_condition_length and negated_length\n            // here because they are only used in an equality comparison later on.\n            self.condition = negated;\n            var tmp = self.body;\n            self.body = self.alternative;\n            self.alternative = is_empty(tmp) ? null : tmp;\n        }\n        var body_defuns = [];\n        var body_var_defs = [];\n        var body_refs = [];\n        var body_exprs = sequencesize(self.body, body_defuns, body_var_defs, body_refs);\n        var alt_defuns = [];\n        var alt_var_defs = [];\n        var alt_refs = [];\n        var alt_exprs = sequencesize(self.alternative, alt_defuns, alt_var_defs, alt_refs);\n        if (body_exprs instanceof AST_BlockStatement || alt_exprs instanceof AST_BlockStatement) {\n            var body = [], var_defs = [];\n            if (body_exprs) {\n                [].push.apply(body, body_defuns);\n                [].push.apply(var_defs, body_var_defs);\n                if (body_exprs instanceof AST_BlockStatement) {\n                    self.body = body_exprs;\n                } else if (body_exprs.length == 0) {\n                    self.body = make_node(AST_EmptyStatement, self.body);\n                } else {\n                    self.body = make_node(AST_SimpleStatement, self.body, {\n                        body: make_sequence(self.body, body_exprs),\n                    });\n                }\n                body_refs.forEach(process_to_assign);\n            }\n            if (alt_exprs) {\n                [].push.apply(body, alt_defuns);\n                [].push.apply(var_defs, alt_var_defs);\n                if (alt_exprs instanceof AST_BlockStatement) {\n                    self.alternative = alt_exprs;\n                } else if (alt_exprs.length == 0) {\n                    self.alternative = null;\n                } else {\n                    self.alternative = make_node(AST_SimpleStatement, self.alternative, {\n                        body: make_sequence(self.alternative, alt_exprs),\n                    });\n                }\n                alt_refs.forEach(process_to_assign);\n            }\n            if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));\n            if (body.length > 0) {\n                body.push(self.transform(compressor));\n                return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n            }\n        } else if (body_exprs && alt_exprs) {\n            var body = body_defuns.concat(alt_defuns);\n            if (body_var_defs.length > 0 || alt_var_defs.length > 0) body.push(make_node(AST_Var, self, {\n                definitions: body_var_defs.concat(alt_var_defs),\n            }));\n            if (body_exprs.length == 0) {\n                body.push(make_node(AST_SimpleStatement, self.condition, {\n                    body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {\n                        operator: \"||\",\n                        left: self.condition,\n                        right: make_sequence(self.alternative, alt_exprs),\n                    }).transform(compressor) : self.condition.clone(),\n                }).optimize(compressor));\n            } else if (alt_exprs.length == 0) {\n                if (self_condition_length === negated_length && !negated_is_best\n                    && self.condition instanceof AST_Binary && self.condition.operator == \"||\") {\n                    // although the code length of self.condition and negated are the same,\n                    // negated does not require additional surrounding parentheses.\n                    // see https://github.com/mishoo/UglifyJS/issues/979\n                    negated_is_best = true;\n                }\n                body.push(make_node(AST_SimpleStatement, self, {\n                    body: make_node(AST_Binary, self, {\n                        operator: negated_is_best ? \"||\" : \"&&\",\n                        left: negated_is_best ? negated : self.condition,\n                        right: make_sequence(self.body, body_exprs),\n                    }).transform(compressor),\n                }).optimize(compressor));\n            } else {\n                body.push(make_node(AST_SimpleStatement, self, {\n                    body: make_node(AST_Conditional, self, {\n                        condition: self.condition,\n                        consequent: make_sequence(self.body, body_exprs),\n                        alternative: make_sequence(self.alternative, alt_exprs),\n                    }),\n                }).optimize(compressor));\n            }\n            body_refs.forEach(process_to_assign);\n            alt_refs.forEach(process_to_assign);\n            return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n        }\n        if (is_empty(self.body)) self = make_node(AST_If, self, {\n            condition: negated,\n            body: self.alternative,\n            alternative: null,\n        });\n        if (self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {\n            var cons_value = self.body.value;\n            var alt_value = self.alternative.value;\n            if (!cons_value && !alt_value) return make_node(AST_BlockStatement, self, {\n                body: [\n                    make_node(AST_SimpleStatement, self, { body: self.condition }),\n                    self.body,\n                ],\n            }).optimize(compressor);\n            if (cons_value && alt_value || !keep_return_void()) {\n                var exit = make_node(self.body.CTOR, self, {\n                    value: make_node(AST_Conditional, self, {\n                        condition: self.condition,\n                        consequent: cons_value || make_node(AST_Undefined, self.body).transform(compressor),\n                        alternative: alt_value || make_node(AST_Undefined, self.alternative).transform(compressor),\n                    }),\n                });\n                if (exit instanceof AST_Return) exit.in_bool = self.body.in_bool || self.alternative.in_bool;\n                return exit;\n            }\n        }\n        if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {\n            self = make_node(AST_If, self, {\n                condition: make_node(AST_Binary, self.condition, {\n                    operator: \"&&\",\n                    left: self.condition,\n                    right: self.body.condition,\n                }),\n                body: self.body.body,\n                alternative: null,\n            });\n        }\n        if (aborts(self.body) && self.alternative) {\n            var alt = self.alternative;\n            self.alternative = null;\n            return make_node(AST_BlockStatement, self, { body: [ self, alt ] }).optimize(compressor);\n        }\n        if (aborts(self.alternative)) {\n            var body = self.body;\n            self.body = self.alternative;\n            self.condition = negated_is_best ? negated : self.condition.negate(compressor);\n            self.alternative = null;\n            return make_node(AST_BlockStatement, self, { body: [ self, body ] }).optimize(compressor);\n        }\n        if (self.alternative) {\n            var body_stats = as_array(self.body);\n            var body_index = last_index(body_stats);\n            var alt_stats = as_array(self.alternative);\n            var alt_index = last_index(alt_stats);\n            for (var stats = []; body_index >= 0 && alt_index >= 0;) {\n                var stat = body_stats[body_index];\n                var alt_stat = alt_stats[alt_index];\n                if (stat.equals(alt_stat)) {\n                    body_stats.splice(body_index--, 1);\n                    alt_stats.splice(alt_index--, 1);\n                    stats.unshift(merge_expression(stat, alt_stat));\n                } else {\n                    if (!(stat instanceof AST_SimpleStatement)) break;\n                    if (!(alt_stat instanceof AST_SimpleStatement)) break;\n                    var expr1 = stat.body.tail_node();\n                    var expr2 = alt_stat.body.tail_node();\n                    if (!expr1.equals(expr2)) break;\n                    body_index = pop_expr(body_stats, stat.body, body_index);\n                    alt_index = pop_expr(alt_stats, alt_stat.body, alt_index);\n                    stats.unshift(make_node(AST_SimpleStatement, expr1, { body: merge_expression(expr1, expr2) }));\n                }\n            }\n            if (stats.length > 0) {\n                self.body = body_stats.length > 0 ? make_node(AST_BlockStatement, self, {\n                    body: body_stats,\n                }) : make_node(AST_EmptyStatement, self);\n                self.alternative = alt_stats.length > 0 ? make_node(AST_BlockStatement, self, {\n                    body: alt_stats,\n                }) : null;\n                stats.unshift(self);\n                return make_node(AST_BlockStatement, self, { body: stats }).optimize(compressor);\n            }\n        }\n        if (compressor.option(\"typeofs\")) mark_locally_defined(self.condition, self.body, self.alternative);\n        return self;\n\n        function as_array(node) {\n            return node instanceof AST_BlockStatement ? node.body : [ node ];\n        }\n\n        function keep_return_void() {\n            var has_finally = false, level = 0, node = compressor.self();\n            do {\n                if (node instanceof AST_Catch) {\n                    if (compressor.parent(level).bfinally) has_finally = true;\n                    level++;\n                } else if (node instanceof AST_Finally) {\n                    level++;\n                } else if (node instanceof AST_Scope) {\n                    return has_finally && in_async_generator(node);\n                } else if (node instanceof AST_Try) {\n                    if (node.bfinally) has_finally = true;\n                }\n            } while (node = compressor.parent(level++));\n        }\n\n        function last_index(stats) {\n            for (var index = stats.length; --index >= 0;) {\n                if (!is_declaration(stats[index], true)) break;\n            }\n            return index;\n        }\n\n        function pop_expr(stats, body, index) {\n            if (body instanceof AST_Sequence) {\n                stats[index] = make_node(AST_SimpleStatement, body, {\n                    body: make_sequence(body, body.expressions.slice(0, -1)),\n                });\n            } else {\n                stats.splice(index--, 1);\n            }\n            return index;\n        }\n\n        function sequencesize(stat, defuns, var_defs, refs) {\n            if (stat == null) return [];\n            if (stat instanceof AST_BlockStatement) {\n                var exprs = [];\n                for (var i = 0; i < stat.body.length; i++) {\n                    var line = stat.body[i];\n                    if (line instanceof AST_EmptyStatement) continue;\n                    if (line instanceof AST_Exit) {\n                        if (i == 0) return;\n                        if (exprs.length > 0) {\n                            line = line.clone();\n                            exprs.push(line.value || make_node(AST_Undefined, line).transform(compressor));\n                            line.value = make_sequence(stat, exprs);\n                        }\n                        var block = stat.clone();\n                        block.body = block.body.slice(i + 1);\n                        block.body.unshift(line);\n                        return block;\n                    }\n                    if (line instanceof AST_LambdaDefinition) {\n                        defuns.push(line);\n                    } else if (line instanceof AST_SimpleStatement) {\n                        if (!compressor.option(\"sequences\") && exprs.length > 0) return;\n                        exprs.push(line.body);\n                    } else if (line instanceof AST_Var) {\n                        if (!compressor.option(\"sequences\") && exprs.length > 0) return;\n                        line.remove_initializers(compressor, var_defs);\n                        line.definitions.forEach(process_var_def);\n                    } else {\n                        return;\n                    }\n                }\n                return exprs;\n            }\n            if (stat instanceof AST_LambdaDefinition) {\n                defuns.push(stat);\n                return [];\n            }\n            if (stat instanceof AST_EmptyStatement) return [];\n            if (stat instanceof AST_SimpleStatement) return [ stat.body ];\n            if (stat instanceof AST_Var) {\n                var exprs = [];\n                stat.remove_initializers(compressor, var_defs);\n                stat.definitions.forEach(process_var_def);\n                return exprs;\n            }\n\n            function process_var_def(var_def) {\n                if (!var_def.value) return;\n                exprs.push(make_node(AST_Assign, var_def, {\n                    operator: \"=\",\n                    left: var_def.name.convert_symbol(AST_SymbolRef, function(ref) {\n                        refs.push(ref);\n                    }),\n                    right: var_def.value,\n                }));\n            }\n        }\n    });\n\n    OPT(AST_Switch, function(self, compressor) {\n        if (!compressor.option(\"switches\")) return self;\n        if (!compressor.option(\"dead_code\")) return self;\n        var body = [];\n        var branch;\n        var decl = [];\n        var default_branch;\n        var exact_match;\n        var side_effects = [];\n        for (var i = 0, len = self.body.length; i < len; i++) {\n            branch = self.body[i];\n            if (branch instanceof AST_Default) {\n                var prev = body[body.length - 1];\n                if (default_branch || is_break(branch.body[0], compressor) && (!prev || aborts(prev))) {\n                    eliminate_branch(branch, prev);\n                    continue;\n                } else {\n                    default_branch = branch;\n                }\n            } else {\n                var exp = branch.expression;\n                var equals = make_node(AST_Binary, self, {\n                    operator: \"===\",\n                    left: self.expression,\n                    right: exp,\n                }).evaluate(compressor, true);\n                if (!equals) {\n                    if (exp.has_side_effects(compressor)) side_effects.push(exp);\n                    eliminate_branch(branch, body[body.length - 1]);\n                    continue;\n                }\n                if (!(equals instanceof AST_Node)) {\n                    if (default_branch) {\n                        var default_index = body.indexOf(default_branch);\n                        body.splice(default_index, 1);\n                        eliminate_branch(default_branch, body[default_index - 1]);\n                        default_branch = null;\n                    }\n                    if (exp.has_side_effects(compressor)) {\n                        exact_match = branch;\n                    } else {\n                        default_branch = branch = make_node(AST_Default, branch);\n                    }\n                    while (++i < len) eliminate_branch(self.body[i], branch);\n                }\n            }\n            if (i + 1 >= len || aborts(branch)) {\n                var prev = body[body.length - 1];\n                var statements = branch.body;\n                if (aborts(prev)) switch (prev.body.length - statements.length) {\n                  case 1:\n                    var stat = prev.body[prev.body.length - 1];\n                    if (!is_break(stat, compressor)) break;\n                    statements = statements.concat(stat);\n                  case 0:\n                    var prev_block = make_node(AST_BlockStatement, prev);\n                    var next_block = make_node(AST_BlockStatement, branch, { body: statements });\n                    if (prev_block.equals(next_block)) prev.body = [];\n                }\n            }\n            if (side_effects.length) {\n                if (branch instanceof AST_Default) {\n                    body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));\n                } else {\n                    side_effects.push(branch.expression);\n                    branch.expression = make_sequence(self, side_effects);\n                }\n                side_effects = [];\n            }\n            body.push(branch);\n        }\n        if (side_effects.length && !exact_match) {\n            body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));\n        }\n        while (branch = body[body.length - 1]) {\n            var stat = branch.body[branch.body.length - 1];\n            if (is_break(stat, compressor)) branch.body.pop();\n            if (branch === default_branch) {\n                if (!has_declarations_only(branch)) break;\n            } else if (branch.expression.has_side_effects(compressor)) {\n                break;\n            } else if (default_branch) {\n                if (!has_declarations_only(default_branch)) break;\n                if (body[body.length - 2] !== default_branch) break;\n                default_branch.body = default_branch.body.concat(branch.body);\n                branch.body = [];\n            } else if (!has_declarations_only(branch)) break;\n            eliminate_branch(branch);\n            if (body.pop() === default_branch) default_branch = null;\n        }\n        if (!branch) {\n            decl.push(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));\n            if (side_effects.length) decl.push(make_node(AST_SimpleStatement, self, {\n                body: make_sequence(self, side_effects),\n            }));\n            return make_node(AST_BlockStatement, self, { body: decl }).optimize(compressor);\n        }\n        if (branch === default_branch) while (branch = body[body.length - 2]) {\n            if (branch instanceof AST_Default) break;\n            if (!has_declarations_only(branch)) break;\n            var exp = branch.expression;\n            if (exp.has_side_effects(compressor)) {\n                var prev = body[body.length - 3];\n                if (prev && !aborts(prev)) break;\n                default_branch.body.unshift(make_node(AST_SimpleStatement, self, { body: exp }));\n            }\n            eliminate_branch(branch);\n            body.splice(-2, 1);\n        }\n        body[0].body = decl.concat(body[0].body);\n        self.body = body;\n        if (compressor.option(\"conditionals\")) switch (body.length) {\n          case 1:\n            if (!no_break(body[0])) break;\n            var exp = body[0].expression;\n            var statements = body[0].body.slice();\n            if (body[0] !== default_branch && body[0] !== exact_match) return make_node(AST_If, self, {\n                condition: make_node(AST_Binary, self, {\n                    operator: \"===\",\n                    left: self.expression,\n                    right: exp,\n                }),\n                body: make_node(AST_BlockStatement, self, { body: statements }),\n                alternative: null,\n            }).optimize(compressor);\n            if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, { body: exp }));\n            statements.unshift(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));\n            return make_node(AST_BlockStatement, self, { body: statements }).optimize(compressor);\n          case 2:\n            if (!member(default_branch, body) || !no_break(body[1])) break;\n            var statements = body[0].body.slice();\n            var exclusive = statements.length && is_break(statements[statements.length - 1], compressor);\n            if (exclusive) statements.pop();\n            if (!all(statements, no_break)) break;\n            var alternative = body[1].body.length && make_node(AST_BlockStatement, body[1]);\n            var node = make_node(AST_If, self, {\n                condition: make_node(AST_Binary, self, body[0] === default_branch ? {\n                    operator: \"!==\",\n                    left: self.expression,\n                    right: body[1].expression,\n                } : {\n                    operator: \"===\",\n                    left: self.expression,\n                    right: body[0].expression,\n                }),\n                body: make_node(AST_BlockStatement, body[0], { body: statements }),\n                alternative: exclusive && alternative || null,\n            });\n            if (!exclusive && alternative) node = make_node(AST_BlockStatement, self, { body: [ node, alternative ] });\n            return node.optimize(compressor);\n        }\n        return self;\n\n        function is_break(node, tw) {\n            return node instanceof AST_Break && tw.loopcontrol_target(node) === self;\n        }\n\n        function no_break(node) {\n            var found = false;\n            var tw = new TreeWalker(function(node) {\n                if (found\n                    || node instanceof AST_Lambda\n                    || node instanceof AST_SimpleStatement) return true;\n                if (is_break(node, tw)) found = true;\n            });\n            tw.push(self);\n            node.walk(tw);\n            return !found;\n        }\n\n        function eliminate_branch(branch, prev) {\n            if (prev && !aborts(prev)) {\n                prev.body = prev.body.concat(branch.body);\n            } else {\n                extract_declarations_from_unreachable_code(compressor, branch, decl);\n            }\n        }\n    });\n\n    OPT(AST_Try, function(self, compressor) {\n        self.body = tighten_body(self.body, compressor);\n        if (compressor.option(\"dead_code\")) {\n            if (has_declarations_only(self)\n                && !(self.bcatch && self.bcatch.argname && self.bcatch.argname.match_symbol(function(node) {\n                    return node instanceof AST_SymbolCatch && !can_drop_symbol(node);\n                }, true))) {\n                var body = [];\n                if (self.bcatch) {\n                    extract_declarations_from_unreachable_code(compressor, self.bcatch, body);\n                    body.forEach(function(stat) {\n                        if (!(stat instanceof AST_Var)) return;\n                        stat.definitions.forEach(function(var_def) {\n                            var def = var_def.name.definition().redefined();\n                            if (!def) return;\n                            var_def.name = var_def.name.clone();\n                            var_def.name.thedef = def;\n                        });\n                    });\n                }\n                body.unshift(make_node(AST_BlockStatement, self).optimize(compressor));\n                if (self.bfinally) {\n                    body.push(make_node(AST_BlockStatement, self.bfinally).optimize(compressor));\n                }\n                return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n            }\n            if (self.bfinally && has_declarations_only(self.bfinally)) {\n                var body = make_node(AST_BlockStatement, self.bfinally).optimize(compressor);\n                body = self.body.concat(body);\n                if (!self.bcatch) return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);\n                self.body = body;\n                self.bfinally = null;\n            }\n        }\n        return self;\n    });\n\n    function remove_initializers(make_value) {\n        return function(compressor, defns) {\n            var dropped = false;\n            this.definitions.forEach(function(defn) {\n                if (defn.value) dropped = true;\n                defn.name.match_symbol(function(node) {\n                    if (node instanceof AST_SymbolDeclaration) defns.push(make_node(AST_VarDef, node, {\n                        name: node,\n                        value: make_value(compressor, node),\n                    }));\n                }, true);\n            });\n            return dropped;\n        };\n    }\n\n    AST_Const.DEFMETHOD(\"remove_initializers\", remove_initializers(function(compressor, node) {\n        return make_node(AST_Undefined, node).optimize(compressor);\n    }));\n    AST_Let.DEFMETHOD(\"remove_initializers\", remove_initializers(return_null));\n    AST_Var.DEFMETHOD(\"remove_initializers\", remove_initializers(return_null));\n\n    AST_Definitions.DEFMETHOD(\"to_assignments\", function() {\n        var assignments = this.definitions.reduce(function(a, defn) {\n            var def = defn.name.definition();\n            var value = defn.value;\n            if (value) {\n                if (value instanceof AST_Sequence) value = value.clone();\n                var name = make_node(AST_SymbolRef, defn.name);\n                var assign = make_node(AST_Assign, defn, {\n                    operator: \"=\",\n                    left: name,\n                    right: value,\n                });\n                a.push(assign);\n                var fixed = function() {\n                    return assign.right;\n                };\n                fixed.assigns = [ assign ];\n                fixed.direct_access = def.direct_access;\n                fixed.escaped = def.escaped;\n                name.fixed = fixed;\n                def.references.forEach(function(ref) {\n                    if (!ref.fixed) return;\n                    var assigns = ref.fixed.assigns;\n                    if (!assigns) return;\n                    if (assigns[0] !== defn) return;\n                    if (assigns.length > 1 || ref.fixed.to_binary || ref.fixed.to_prefix) {\n                        assigns[0] = assign;\n                    } else {\n                        ref.fixed = fixed;\n                        if (def.fixed === ref.fixed) def.fixed = fixed;\n                    }\n                });\n                def.references.push(name);\n                def.assignments++;\n            }\n            def.eliminated++;\n            return a;\n        }, []);\n        if (assignments.length == 0) return null;\n        return make_sequence(this, assignments);\n    });\n\n    function is_safe_lexical(def) {\n        return def.name != \"arguments\" && def.orig.length < (def.orig[0] instanceof AST_SymbolLambda ? 3 : 2);\n    }\n\n    function may_overlap(compressor, def) {\n        if (compressor.exposed(def)) return true;\n        var scope = def.scope.resolve();\n        for (var s = def.scope; s !== scope;) {\n            s = s.parent_scope;\n            if (s.var_names().has(def.name)) return true;\n        }\n    }\n\n    function to_let(stat, scope) {\n        return make_node(AST_Let, stat, {\n            definitions: stat.definitions.map(function(defn) {\n                return make_node(AST_VarDef, defn, {\n                    name: defn.name.convert_symbol(AST_SymbolLet, function(name, node) {\n                        var def = name.definition();\n                        def.orig[def.orig.indexOf(node)] = name;\n                        for (var s = scope; s !== def.scope && (s = s.parent_scope);) {\n                            remove(s.enclosed, def);\n                            s._var_names = undefined;\n                        }\n                        def.scope.variables.del(def.name);\n                        scope.variables.set(def.name, def);\n                        def.scope = scope;\n                    }),\n                    value: defn.value,\n                });\n            }),\n        });\n    }\n\n    function to_var(stat, scope) {\n        return make_node(AST_Var, stat, {\n            definitions: stat.definitions.map(function(defn) {\n                return make_node(AST_VarDef, defn, {\n                    name: defn.name.convert_symbol(AST_SymbolVar, function(name, node) {\n                        var def = name.definition();\n                        def.orig[def.orig.indexOf(node)] = name;\n                        if (def.scope === scope) return;\n                        def.scope = scope;\n                        scope.variables.set(def.name, def);\n                        scope.enclosed.push(def);\n                        scope.var_names().set(def.name, true);\n                    }),\n                    value: defn.value,\n                });\n            }),\n        });\n    }\n\n    (function(def) {\n        def(AST_Node, return_false);\n        def(AST_Const, function(compressor, assigned) {\n            assigned = assigned ? 1 : 0;\n            var defns = this.definitions;\n            if (!compressor.option(\"module\") && all(defns, function(defn) {\n                return defn.name instanceof AST_SymbolConst;\n            })) return false;\n            return all(defns, function(defn) {\n                return !defn.name.match_symbol(function(node) {\n                    if (node instanceof AST_SymbolDeclaration) return node.definition().assignments != assigned;\n                }, true);\n            });\n        });\n        def(AST_Var, function(compressor) {\n            return all(this.definitions, function(defn) {\n                return !defn.name.match_symbol(function(node) {\n                    if (!(node instanceof AST_SymbolDeclaration)) return false;\n                    var def = node.definition();\n                    if (def.first_decl !== node) return true;\n                    if (!safe_from_tdz(compressor, node)) return true;\n                    var defn_scope = node.scope;\n                    if (defn_scope instanceof AST_Scope) return false;\n                    return !all(def.references, function(ref) {\n                        var scope = ref.scope;\n                        do {\n                            if (scope === defn_scope) return true;\n                        } while (scope = scope.parent_scope);\n                        return false;\n                    });\n                }, true);\n            });\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"can_letify\", func);\n    });\n\n    function safe_from_tdz(compressor, sym) {\n        var def = sym.definition();\n        return (def.fixed || def.fixed === 0)\n            && is_safe_lexical(def)\n            && same_scope(def)\n            && !may_overlap(compressor, def);\n    }\n\n    AST_Definitions.DEFMETHOD(\"can_varify\", function(compressor) {\n        return all(this.definitions, function(defn) {\n            return !defn.name.match_symbol(function(node) {\n                if (node instanceof AST_SymbolDeclaration) return !safe_from_tdz(compressor, node);\n            }, true);\n        });\n    });\n\n    OPT(AST_Const, function(self, compressor) {\n        if (!compressor.option(\"varify\")) return self;\n        if (self.can_varify(compressor)) return to_var(self, compressor.find_parent(AST_Scope));\n        if (self.can_letify(compressor)) return to_let(self, find_scope(compressor));\n        return self;\n    });\n\n    OPT(AST_Let, function(self, compressor) {\n        if (!compressor.option(\"varify\")) return self;\n        if (self.can_varify(compressor)) return to_var(self, compressor.find_parent(AST_Scope));\n        return self;\n    });\n\n    function trim_optional_chain(node, compressor) {\n        if (!compressor.option(\"optional_chains\")) return;\n        if (node.terminal) do {\n            var expr = node.expression;\n            if (node.optional) {\n                var ev = fuzzy_eval(compressor, expr, true);\n                if (ev == null) return make_node(AST_UnaryPrefix, node, {\n                    operator: \"void\",\n                    expression: expr,\n                }).optimize(compressor);\n                if (!(ev instanceof AST_Node)) node.optional = false;\n            }\n            node = expr;\n        } while ((node.TYPE == \"Call\" || node instanceof AST_PropAccess) && !node.terminal);\n    }\n\n    function lift_sequence_in_expression(node, compressor) {\n        var exp = node.expression;\n        if (!(exp instanceof AST_Sequence)) return node;\n        var x = exp.expressions.slice();\n        var e = node.clone();\n        e.expression = x.pop();\n        x.push(e);\n        return make_sequence(node, x);\n    }\n\n    function drop_unused_call_args(call, compressor, fns_with_marked_args) {\n        var exp = call.expression;\n        var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp;\n        if (!(fn instanceof AST_Lambda)) return;\n        if (fn.uses_arguments) return;\n        if (fn.pinned()) return;\n        if (fns_with_marked_args && fns_with_marked_args.indexOf(fn) < 0) return;\n        var args = call.args;\n        if (!all(args, function(arg) {\n            return !(arg instanceof AST_Spread);\n        })) return;\n        var argnames = fn.argnames;\n        var is_iife = fn === exp && !fn.name;\n        if (fn.rest) {\n            if (!(is_iife && compressor.option(\"rests\"))) return;\n            var insert = argnames.length;\n            args = args.slice(0, insert);\n            while (args.length < insert) args.push(make_node(AST_Undefined, call).optimize(compressor));\n            args.push(make_node(AST_Array, call, { elements: call.args.slice(insert) }));\n            argnames = argnames.concat(fn.rest);\n            fn.rest = null;\n        } else {\n            args = args.slice();\n            argnames = argnames.slice();\n        }\n        var pos = 0, last = 0;\n        var drop_defaults = is_iife && compressor.option(\"default_values\");\n        var drop_fargs = is_iife && compressor.drop_fargs(fn, call) ? function(argname, arg) {\n            if (!argname) return true;\n            if (argname instanceof AST_DestructuredArray) {\n                return argname.elements.length == 0 && !argname.rest && arg instanceof AST_Array;\n            }\n            if (argname instanceof AST_DestructuredObject) {\n                return argname.properties.length == 0 && !argname.rest && arg && !arg.may_throw_on_access(compressor);\n            }\n            return argname.unused;\n        } : return_false;\n        var side_effects = [];\n        for (var i = 0; i < args.length; i++) {\n            var argname = argnames[i];\n            if (drop_defaults && argname instanceof AST_DefaultValue && args[i].is_defined(compressor)) {\n                argnames[i] = argname = argname.name;\n            }\n            if (!argname || argname.unused !== undefined) {\n                var node = args[i].drop_side_effect_free(compressor);\n                if (drop_fargs(argname)) {\n                    if (argname) argnames.splice(i, 1);\n                    args.splice(i, 1);\n                    if (node) side_effects.push(node);\n                    i--;\n                    continue;\n                } else if (node) {\n                    side_effects.push(node);\n                    args[pos++] = make_sequence(call, side_effects);\n                    side_effects = [];\n                } else if (argname) {\n                    if (side_effects.length) {\n                        args[pos++] = make_sequence(call, side_effects);\n                        side_effects = [];\n                    } else {\n                        args[pos++] = make_node(AST_Number, args[i], { value: 0 });\n                        continue;\n                    }\n                }\n            } else if (drop_fargs(argname, args[i])) {\n                var node = args[i].drop_side_effect_free(compressor);\n                argnames.splice(i, 1);\n                args.splice(i, 1);\n                if (node) side_effects.push(node);\n                i--;\n                continue;\n            } else {\n                side_effects.push(args[i]);\n                args[pos++] = make_sequence(call, side_effects);\n                side_effects = [];\n            }\n            last = pos;\n        }\n        for (; i < argnames.length; i++) {\n            if (drop_fargs(argnames[i])) argnames.splice(i--, 1);\n        }\n        fn.argnames = argnames;\n        args.length = last;\n        call.args = args;\n        if (!side_effects.length) return;\n        var arg = make_sequence(call, side_effects);\n        args.push(args.length < argnames.length ? make_node(AST_UnaryPrefix, call, {\n            operator: \"void\",\n            expression: arg,\n        }) : arg);\n    }\n\n    function avoid_await_yield(compressor, parent_scope) {\n        if (!parent_scope) parent_scope = compressor.find_parent(AST_Scope);\n        var avoid = [];\n        if (is_async(parent_scope) || parent_scope instanceof AST_Toplevel && compressor.option(\"module\")) {\n            avoid.push(\"await\");\n        }\n        if (is_generator(parent_scope)) avoid.push(\"yield\");\n        return avoid.length && makePredicate(avoid);\n    }\n\n    function safe_from_await_yield(fn, avoid) {\n        if (!avoid) return true;\n        var safe = true;\n        var tw = new TreeWalker(function(node) {\n            if (!safe) return true;\n            if (node instanceof AST_Scope) {\n                if (node === fn) return;\n                if (is_arrow(node)) {\n                    for (var i = 0; safe && i < node.argnames.length; i++) node.argnames[i].walk(tw);\n                } else if (node instanceof AST_LambdaDefinition && avoid[node.name.name]) {\n                    safe = false;\n                }\n                return true;\n            }\n            if (node instanceof AST_Symbol && avoid[node.name] && node !== fn.name) safe = false;\n        });\n        fn.walk(tw);\n        return safe;\n    }\n\n    function safe_from_strict_mode(fn, compressor) {\n        return fn.in_strict_mode(compressor) || !compressor.has_directive(\"use strict\");\n    }\n\n    OPT(AST_Call, function(self, compressor) {\n        var exp = self.expression;\n        var terminated = trim_optional_chain(self, compressor);\n        if (terminated) return terminated;\n        if (compressor.option(\"sequences\")) {\n            if (exp instanceof AST_PropAccess) {\n                var seq = lift_sequence_in_expression(exp, compressor);\n                if (seq !== exp) {\n                    var call = self.clone();\n                    call.expression = seq.expressions.pop();\n                    seq.expressions.push(call);\n                    return seq.optimize(compressor);\n                }\n            } else if (!needs_unbinding(exp.tail_node())) {\n                var seq = lift_sequence_in_expression(self, compressor);\n                if (seq !== self) return seq.optimize(compressor);\n            }\n        }\n        if (compressor.option(\"unused\")) drop_unused_call_args(self, compressor);\n        if (compressor.option(\"unsafe\")) {\n            if (is_undeclared_ref(exp)) switch (exp.name) {\n              case \"Array\":\n                // Array(n) ---> [ , , ... , ]\n                if (self.args.length == 1) {\n                    var first = self.args[0];\n                    if (first instanceof AST_Number) try {\n                        var length = first.value;\n                        if (length > 6) break;\n                        var elements = Array(length);\n                        for (var i = 0; i < length; i++) elements[i] = make_node(AST_Hole, self);\n                        return make_node(AST_Array, self, { elements: elements });\n                    } catch (ex) {\n                        AST_Node.warn(\"Invalid array length: {length} [{start}]\", {\n                            length: length,\n                            start: self.start,\n                        });\n                        break;\n                    }\n                    if (!first.is_boolean(compressor) && !first.is_string(compressor)) break;\n                }\n                // Array(...) ---> [ ... ]\n                return make_node(AST_Array, self, { elements: self.args });\n              case \"Object\":\n                // Object() ---> {}\n                if (self.args.length == 0) return make_node(AST_Object, self, { properties: [] });\n                break;\n              case \"String\":\n                // String() ---> \"\"\n                if (self.args.length == 0) return make_node(AST_String, self, { value: \"\" });\n                // String(x) ---> \"\" + x\n                if (self.args.length == 1) return make_node(AST_Binary, self, {\n                    operator: \"+\",\n                    left: make_node(AST_String, self, { value: \"\" }),\n                    right: self.args[0],\n                }).optimize(compressor);\n                break;\n              case \"Number\":\n                // Number() ---> 0\n                if (self.args.length == 0) return make_node(AST_Number, self, { value: 0 });\n                // Number(x) ---> +(\"\" + x)\n                if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {\n                    operator: \"+\",\n                    expression: make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: make_node(AST_String, self, { value: \"\" }),\n                        right: self.args[0],\n                    }),\n                }).optimize(compressor);\n                break;\n              case \"Boolean\":\n                // Boolean() ---> false\n                if (self.args.length == 0) return make_node(AST_False, self).optimize(compressor);\n                // Boolean(x) ---> !!x\n                if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {\n                    operator: \"!\",\n                    expression: make_node(AST_UnaryPrefix, self, {\n                        operator: \"!\",\n                        expression: self.args[0],\n                    }),\n                }).optimize(compressor);\n                break;\n              case \"RegExp\":\n                // attempt to convert RegExp(...) to literal\n                var params = [];\n                if (all(self.args, function(arg) {\n                    var value = arg.evaluate(compressor);\n                    params.unshift(value);\n                    return arg !== value;\n                })) try {\n                    return best_of(compressor, self, make_node(AST_RegExp, self, {\n                        value: RegExp.apply(RegExp, params),\n                    }));\n                } catch (ex) {\n                    AST_Node.warn(\"Error converting {this} [{start}]\", self);\n                }\n                break;\n            } else if (exp instanceof AST_Dot) switch (exp.property) {\n              case \"toString\":\n                // x.toString() ---> \"\" + x\n                var expr = exp.expression;\n                if (self.args.length == 0 && !(expr.may_throw_on_access(compressor) || expr instanceof AST_Super)) {\n                    return make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: make_node(AST_String, self, { value: \"\" }),\n                        right: expr,\n                    }).optimize(compressor);\n                }\n                break;\n              case \"join\":\n                if (exp.expression instanceof AST_Array && self.args.length < 2) EXIT: {\n                    var separator = self.args[0];\n                    // [].join() ---> \"\"\n                    // [].join(x) ---> (x, \"\")\n                    if (exp.expression.elements.length == 0 && !(separator instanceof AST_Spread)) {\n                        return separator ? make_sequence(self, [\n                            separator,\n                            make_node(AST_String, self, { value: \"\" }),\n                        ]).optimize(compressor) : make_node(AST_String, self, { value: \"\" });\n                    }\n                    if (separator) {\n                        separator = separator.evaluate(compressor);\n                        if (separator instanceof AST_Node) break EXIT; // not a constant\n                    }\n                    var elements = [];\n                    var consts = [];\n                    for (var i = 0; i < exp.expression.elements.length; i++) {\n                        var el = exp.expression.elements[i];\n                        var value = el.evaluate(compressor);\n                        if (value !== el) {\n                            consts.push(value);\n                        } else if (el instanceof AST_Spread) {\n                            break EXIT;\n                        } else {\n                            if (consts.length > 0) {\n                                elements.push(make_node(AST_String, self, { value: consts.join(separator) }));\n                                consts.length = 0;\n                            }\n                            elements.push(el);\n                        }\n                    }\n                    if (consts.length > 0) elements.push(make_node(AST_String, self, {\n                        value: consts.join(separator),\n                    }));\n                    // [ x ].join() ---> \"\" + x\n                    // [ x ].join(\".\") ---> \"\" + x\n                    // [ 1, 2, 3 ].join() ---> \"1,2,3\"\n                    // [ 1, 2, 3 ].join(\".\") ---> \"1.2.3\"\n                    if (elements.length == 1) {\n                        if (elements[0].is_string(compressor)) return elements[0];\n                        return make_node(AST_Binary, elements[0], {\n                            operator: \"+\",\n                            left: make_node(AST_String, self, { value: \"\" }),\n                            right: elements[0],\n                        });\n                    }\n                    // [ 1, 2, a, 3 ].join(\"\") ---> \"12\" + a + \"3\"\n                    if (separator == \"\") {\n                        var first;\n                        if (elements[0].is_string(compressor) || elements[1].is_string(compressor)) {\n                            first = elements.shift();\n                        } else {\n                            first = make_node(AST_String, self, { value: \"\" });\n                        }\n                        return elements.reduce(function(prev, el) {\n                            return make_node(AST_Binary, el, {\n                                operator: \"+\",\n                                left: prev,\n                                right: el,\n                            });\n                        }, first).optimize(compressor);\n                    }\n                    // [ x, \"foo\", \"bar\", y ].join() ---> [ x, \"foo,bar\", y ].join()\n                    // [ x, \"foo\", \"bar\", y ].join(\"-\") ---> [ x, \"foo-bar\", y ].join(\"-\")\n                    // need this awkward cloning to not affect original element\n                    // best_of will decide which one to get through.\n                    var node = self.clone();\n                    node.expression = node.expression.clone();\n                    node.expression.expression = node.expression.expression.clone();\n                    node.expression.expression.elements = elements;\n                    return best_of(compressor, self, node);\n                }\n                break;\n              case \"charAt\":\n                if (self.args.length < 2) {\n                    var node = make_node(AST_Binary, self, {\n                        operator: \"||\",\n                        left: make_node(AST_Sub, self, {\n                            expression: exp.expression,\n                            property: self.args.length ? make_node(AST_Binary, self.args[0], {\n                                operator: \"|\",\n                                left: make_node(AST_Number, self, { value: 0 }),\n                                right: self.args[0],\n                            }) : make_node(AST_Number, self, { value: 0 }),\n                        }).optimize(compressor),\n                        right: make_node(AST_String, self, { value: \"\" }),\n                    });\n                    node.is_string = return_true;\n                    return node.optimize(compressor);\n                }\n                break;\n              case \"apply\":\n                if (self.args.length == 2 && self.args[1] instanceof AST_Array) {\n                    var args = self.args[1].elements.slice();\n                    args.unshift(self.args[0]);\n                    return make_node(AST_Call, self, {\n                        expression: make_node(AST_Dot, exp, {\n                            expression: exp.expression,\n                            property: \"call\",\n                        }),\n                        args: args,\n                    }).optimize(compressor);\n                }\n                break;\n              case \"call\":\n                var func = exp.expression;\n                if (func instanceof AST_SymbolRef) {\n                    func = func.fixed_value();\n                }\n                if (func instanceof AST_Lambda && !func.contains_this()) {\n                    return (self.args.length ? make_sequence(self, [\n                        self.args[0],\n                        make_node(AST_Call, self, {\n                            expression: exp.expression,\n                            args: self.args.slice(1),\n                        }),\n                    ]) : make_node(AST_Call, self, {\n                        expression: exp.expression,\n                        args: [],\n                    })).optimize(compressor);\n                }\n                break;\n            } else if (compressor.option(\"side_effects\")\n                && exp instanceof AST_Call\n                && exp.args.length == 1\n                && is_undeclared_ref(exp.expression)\n                && exp.expression.name == \"Object\") {\n                var call = self.clone();\n                call.expression = maintain_this_binding(self, exp, exp.args[0]);\n                return call.optimize(compressor);\n            }\n        }\n        if (compressor.option(\"unsafe_Function\")\n            && is_undeclared_ref(exp)\n            && exp.name == \"Function\") {\n            // new Function() ---> function(){}\n            if (self.args.length == 0) return make_node(AST_Function, self, {\n                argnames: [],\n                body: [],\n            }).init_vars(exp.scope);\n            if (all(self.args, function(x) {\n                return x instanceof AST_String;\n            })) {\n                // quite a corner-case, but we can handle it:\n                //   https://github.com/mishoo/UglifyJS/issues/203\n                // if the code argument is a constant, then we can minify it.\n                try {\n                    var code = \"n(function(\" + self.args.slice(0, -1).map(function(arg) {\n                        return arg.value;\n                    }).join() + \"){\" + self.args[self.args.length - 1].value + \"})\";\n                    var ast = parse(code);\n                    var mangle = { ie: compressor.option(\"ie\") };\n                    ast.figure_out_scope(mangle);\n                    var comp = new Compressor(compressor.options);\n                    ast = ast.transform(comp);\n                    ast.figure_out_scope(mangle);\n                    ast.compute_char_frequency(mangle);\n                    ast.mangle_names(mangle);\n                    var fun;\n                    ast.walk(new TreeWalker(function(node) {\n                        if (fun) return true;\n                        if (node instanceof AST_Lambda) {\n                            fun = node;\n                            return true;\n                        }\n                    }));\n                    var code = OutputStream();\n                    AST_BlockStatement.prototype._codegen.call(fun, code);\n                    self.args = [\n                        make_node(AST_String, self, {\n                            value: fun.argnames.map(function(arg) {\n                                return arg.print_to_string();\n                            }).join(),\n                        }),\n                        make_node(AST_String, self.args[self.args.length - 1], {\n                            value: code.get().replace(/^\\{|\\}$/g, \"\")\n                        }),\n                    ];\n                    return self;\n                } catch (ex) {\n                    if (ex instanceof JS_Parse_Error) {\n                        AST_Node.warn(\"Error parsing code passed to new Function [{start}]\", self.args[self.args.length - 1]);\n                        AST_Node.warn(ex.toString());\n                    } else {\n                        throw ex;\n                    }\n                }\n            }\n        }\n        var fn = exp instanceof AST_SymbolRef ? exp.fixed_value() : exp;\n        var parent = compressor.parent(), current = compressor.self();\n        var is_func = fn instanceof AST_Lambda\n            && (!is_async(fn) || compressor.option(\"awaits\") && parent instanceof AST_Await)\n            && (!is_generator(fn) || compressor.option(\"yields\") && current instanceof AST_Yield && current.nested);\n        var stat = is_func && fn.first_statement();\n        var has_default = 0, has_destructured = false;\n        var has_spread = !all(self.args, function(arg) {\n            return !(arg instanceof AST_Spread);\n        });\n        var can_drop = is_func && all(fn.argnames, function(argname, index) {\n            if (has_default == 1 && self.args[index] instanceof AST_Spread) has_default = 2;\n            if (argname instanceof AST_DefaultValue) {\n                if (!has_default) has_default = 1;\n                var arg = has_default == 1 && self.args[index];\n                if (!is_undefined(arg)) has_default = 2;\n                if (has_arg_refs(fn, argname.value)) return false;\n                argname = argname.name;\n            }\n            if (argname instanceof AST_Destructured) {\n                has_destructured = true;\n                if (has_arg_refs(fn, argname)) return false;\n            }\n            return true;\n        }) && !(fn.rest instanceof AST_Destructured && has_arg_refs(fn, fn.rest));\n        var can_inline = can_drop\n            && compressor.option(\"inline\")\n            && !self.is_expr_pure(compressor)\n            && (exp === fn || safe_from_strict_mode(fn, compressor));\n        if (can_inline && stat instanceof AST_Return) {\n            var value = stat.value;\n            if (exp === fn\n                && !fn.name\n                && (!value || value.is_constant_expression())\n                && safe_from_await_yield(fn, avoid_await_yield(compressor))) {\n                return make_sequence(self, convert_args(value)).optimize(compressor);\n            }\n        }\n        if (is_func && !fn.contains_this()) {\n            var def, value, var_assigned = false;\n            if (can_inline\n                && !fn.uses_arguments\n                && !fn.pinned()\n                && !(fn.name && fn instanceof AST_LambdaExpression)\n                && (exp === fn || !recursive_ref(compressor, def = exp.definition(), fn)\n                    && fn.is_constant_expression(find_scope(compressor)))\n                && (value = can_flatten_body(stat))) {\n                var replacing = exp === fn || def.single_use && def.references.length - def.replaced == 1;\n                if (can_substitute_directly()) {\n                    self._optimized = true;\n                    var retValue = value.optimize(compressor).clone(true);\n                    var args = self.args.slice();\n                    var refs = [];\n                    retValue = retValue.transform(new TreeTransformer(function(node) {\n                        if (node instanceof AST_SymbolRef) {\n                            var def = node.definition();\n                            if (fn.variables.get(node.name) !== def) {\n                                refs.push(node);\n                                return node;\n                            }\n                            var index = resolve_index(def);\n                            var arg = args[index];\n                            if (!arg) return make_node(AST_Undefined, self);\n                            args[index] = null;\n                            var parent = this.parent();\n                            return parent ? maintain_this_binding(parent, node, arg) : arg;\n                        }\n                    }));\n                    var save_inlined = fn.inlined;\n                    if (exp !== fn) fn.inlined = true;\n                    var exprs = [];\n                    args.forEach(function(arg) {\n                        if (!arg) return;\n                        arg = arg.clone(true);\n                        arg.walk(new TreeWalker(function(node) {\n                            if (node instanceof AST_SymbolRef) refs.push(node);\n                        }));\n                        exprs.push(arg);\n                    }, []);\n                    exprs.push(retValue);\n                    var node = make_sequence(self, exprs).optimize(compressor);\n                    fn.inlined = save_inlined;\n                    node = maintain_this_binding(parent, current, node);\n                    self.inlined_node = node;\n                    if (replacing || best_of_expression(node, self) === node) {\n                        refs.forEach(function(ref) {\n                            ref.scope = exp === fn ? fn.parent_scope : exp.scope;\n                            ref.reference();\n                            var def = ref.definition();\n                            if (replacing) def.replaced++;\n                            def.single_use = false;\n                        });\n                        return node;\n                    } else if (!node.has_side_effects(compressor)) {\n                        self.drop_side_effect_free = function(compressor, first_in_statement) {\n                            var self = this;\n                            var exprs = self.args.slice();\n                            exprs.unshift(self.expression);\n                            return make_sequence(self, exprs).drop_side_effect_free(compressor, first_in_statement);\n                        };\n                        self.has_side_effects = function(compressor) {\n                            var self = this;\n                            var exprs = self.args.slice();\n                            exprs.unshift(self.expression);\n                            return make_sequence(self, exprs).has_side_effects(compressor);\n                        };\n                    }\n                }\n                var arg_used, insert, in_loop, scope;\n                if (replacing && can_inject_symbols()) {\n                    fn._squeezed = true;\n                    if (exp !== fn) fn.parent_scope = exp.scope;\n                    var node = make_sequence(self, flatten_fn()).optimize(compressor);\n                    return maintain_this_binding(parent, current, node);\n                }\n            }\n            if (compressor.option(\"side_effects\")\n                && can_drop\n                && all(fn.body, is_empty)\n                && (fn === exp ? fn_name_unused(fn, compressor) : !has_default && !has_destructured && !fn.rest)\n                && !(is_arrow(fn) && fn.value)\n                && safe_from_await_yield(fn, avoid_await_yield(compressor))) {\n                return make_sequence(self, convert_args()).optimize(compressor);\n            }\n        }\n        if (compressor.option(\"arrows\")\n            && compressor.option(\"module\")\n            && (exp instanceof AST_AsyncFunction || exp instanceof AST_Function)\n            && !exp.name\n            && !exp.uses_arguments\n            && !exp.pinned()\n            && !exp.contains_this()) {\n            var arrow = make_node(is_async(exp) ? AST_AsyncArrow : AST_Arrow, exp, exp);\n            arrow.init_vars(exp.parent_scope, exp);\n            arrow.variables.del(\"arguments\");\n            self.expression = arrow.transform(compressor);\n            return self;\n        }\n        if (compressor.option(\"drop_console\")) {\n            if (exp instanceof AST_PropAccess) {\n                var name = exp.expression;\n                while (name.expression) {\n                    name = name.expression;\n                }\n                if (is_undeclared_ref(name) && name.name == \"console\") {\n                    return make_node(AST_Undefined, self).optimize(compressor);\n                }\n            }\n        }\n        if (compressor.option(\"negate_iife\") && parent instanceof AST_SimpleStatement && is_iife_call(current)) {\n            return self.negate(compressor, true);\n        }\n        return try_evaluate(compressor, self);\n\n        function make_void_lhs(orig) {\n            return make_node(AST_Sub, orig, {\n                expression: make_node(AST_Array, orig, { elements: [] }),\n                property: make_node(AST_Number, orig, { value: 0 }),\n            });\n        }\n\n        function convert_args(value) {\n            var args = self.args.slice();\n            var destructured = has_default > 1 || has_destructured || fn.rest;\n            if (destructured || has_spread) args = [ make_node(AST_Array, self, { elements: args }) ];\n            if (destructured) {\n                var tt = new TreeTransformer(function(node, descend) {\n                    if (node instanceof AST_DefaultValue) return make_node(AST_DefaultValue, node, {\n                        name: node.name.transform(tt) || make_void_lhs(node),\n                        value: node.value,\n                    });\n                    if (node instanceof AST_DestructuredArray) {\n                        var elements = [];\n                        node.elements.forEach(function(node, index) {\n                            node = node.transform(tt);\n                            if (node) elements[index] = node;\n                        });\n                        fill_holes(node, elements);\n                        return make_node(AST_DestructuredArray, node, { elements: elements });\n                    }\n                    if (node instanceof AST_DestructuredObject) {\n                        var properties = [], side_effects = [];\n                        node.properties.forEach(function(prop) {\n                            var key = prop.key;\n                            var value = prop.value.transform(tt);\n                            if (value) {\n                                if (side_effects.length) {\n                                    if (!(key instanceof AST_Node)) key = make_node_from_constant(key, prop);\n                                    side_effects.push(key);\n                                    key = make_sequence(node, side_effects);\n                                    side_effects = [];\n                                }\n                                properties.push(make_node(AST_DestructuredKeyVal, prop, {\n                                    key: key,\n                                    value: value,\n                                }));\n                            } else if (key instanceof AST_Node) {\n                                side_effects.push(key);\n                            }\n                        });\n                        if (side_effects.length) properties.push(make_node(AST_DestructuredKeyVal, node, {\n                            key: make_sequence(node, side_effects),\n                            value: make_void_lhs(node),\n                        }));\n                        return make_node(AST_DestructuredObject, node, { properties: properties });\n                    }\n                    if (node instanceof AST_SymbolFunarg) return null;\n                });\n                var lhs = [];\n                fn.argnames.forEach(function(argname, index) {\n                    argname = argname.transform(tt);\n                    if (argname) lhs[index] = argname;\n                });\n                var rest = fn.rest && fn.rest.transform(tt);\n                if (rest) lhs.length = fn.argnames.length;\n                fill_holes(fn, lhs);\n                args[0] = make_node(AST_Assign, self, {\n                    operator: \"=\",\n                    left: make_node(AST_DestructuredArray, fn, {\n                        elements: lhs,\n                        rest: rest,\n                    }),\n                    right: args[0],\n                });\n            } else fn.argnames.forEach(function(argname) {\n                if (argname instanceof AST_DefaultValue) args.push(argname.value);\n            });\n            args.push(value || make_node(AST_Undefined, self));\n            return args;\n        }\n\n        function noop_value() {\n            return self.call_only ? make_node(AST_Number, self, { value: 0 }) : make_node(AST_Undefined, self);\n        }\n\n        function return_value(stat) {\n            if (!stat) return noop_value();\n            if (stat instanceof AST_Return) return stat.value || noop_value();\n            if (stat instanceof AST_SimpleStatement) {\n                return self.call_only ? stat.body : make_node(AST_UnaryPrefix, stat, {\n                    operator: \"void\",\n                    expression: stat.body,\n                });\n            }\n        }\n\n        function can_flatten_body(stat) {\n            var len = fn.body.length;\n            if (len < 2) {\n                stat = return_value(stat);\n                if (stat) return stat;\n            }\n            if (compressor.option(\"inline\") < 3) return false;\n            stat = null;\n            for (var i = 0; i < len; i++) {\n                var line = fn.body[i];\n                if (line instanceof AST_Var) {\n                    if (var_assigned) {\n                        if (!stat) continue;\n                        if (!(stat instanceof AST_SimpleStatement)) return false;\n                        if (!declarations_only(line)) stat = null;\n                    } else if (!declarations_only(line)) {\n                        if (stat && !(stat instanceof AST_SimpleStatement)) return false;\n                        stat = null;\n                        var_assigned = true;\n                    }\n                } else if (line instanceof AST_AsyncDefun\n                    || line instanceof AST_Defun\n                    || line instanceof AST_EmptyStatement) {\n                    continue;\n                } else if (stat) {\n                    return false;\n                } else {\n                    stat = line;\n                }\n            }\n            return return_value(stat);\n        }\n\n        function resolve_index(def) {\n            for (var i = fn.argnames.length; --i >= 0;) {\n                if (fn.argnames[i].definition() === def) return i;\n            }\n        }\n\n        function can_substitute_directly() {\n            if (has_default || has_destructured || has_spread || var_assigned || fn.rest) return;\n            if (compressor.option(\"inline\") < 2 && fn.argnames.length) return;\n            if (!fn.variables.all(function(def) {\n                return def.references.length - def.replaced < 2 && def.orig[0] instanceof AST_SymbolFunarg;\n            })) return;\n            var scope = compressor.find_parent(AST_Scope);\n            var abort = false;\n            var avoid = avoid_await_yield(compressor, scope);\n            var begin;\n            var in_order = [];\n            var side_effects = false;\n            var tw = new TreeWalker(function(node, descend) {\n                if (abort) return true;\n                if (node instanceof AST_Binary && lazy_op[node.operator]\n                    || node instanceof AST_Conditional) {\n                    in_order = null;\n                    return;\n                }\n                if (node instanceof AST_Class) return abort = true;\n                if (node instanceof AST_Destructured) {\n                    side_effects = true;\n                    return;\n                }\n                if (node instanceof AST_Scope) return abort = true;\n                if (avoid && node instanceof AST_Symbol && avoid[node.name]) return abort = true;\n                if (node instanceof AST_SymbolRef) {\n                    var def = node.definition();\n                    if (fn.variables.get(node.name) !== def) {\n                        in_order = null;\n                        return;\n                    }\n                    if (def.init instanceof AST_LambdaDefinition) return abort = true;\n                    if (is_lhs(node, tw.parent())) return abort = true;\n                    var index = resolve_index(def);\n                    if (!(begin < index)) begin = index;\n                    if (!in_order) return;\n                    if (side_effects) {\n                        in_order = null;\n                    } else {\n                        in_order.push(fn.argnames[index]);\n                    }\n                    return;\n                }\n                if (side_effects) return;\n                if (node instanceof AST_Assign && node.left instanceof AST_PropAccess) {\n                    node.left.expression.walk(tw);\n                    if (node.left instanceof AST_Sub) node.left.property.walk(tw);\n                    node.right.walk(tw);\n                    side_effects = true;\n                    return true;\n                }\n                if (node.has_side_effects(compressor)) {\n                    descend();\n                    side_effects = true;\n                    return true;\n                }\n            });\n            value.walk(tw);\n            if (abort) return;\n            var end = self.args.length;\n            if (in_order && fn.argnames.length >= end) {\n                end = fn.argnames.length;\n                while (end-- > begin && fn.argnames[end] === in_order.pop());\n                end++;\n            }\n            return end <= begin || all(self.args.slice(begin, end), side_effects && !in_order ? function(funarg) {\n                return funarg.is_constant_expression(scope);\n            } : function(funarg) {\n                return !funarg.has_side_effects(compressor);\n            });\n        }\n\n        function var_exists(defined, name) {\n            return defined.has(name) || identifier_atom[name] || scope.var_names().has(name);\n        }\n\n        function can_inject_args(defined, safe_to_inject) {\n            var abort = false;\n            fn.each_argname(function(arg) {\n                if (abort) return;\n                if (arg.unused) return;\n                if (!safe_to_inject || var_exists(defined, arg.name)) return abort = true;\n                arg_used.set(arg.name, true);\n                if (in_loop) in_loop.push(arg.definition());\n            });\n            return !abort;\n        }\n\n        function can_inject_vars(defined, safe_to_inject) {\n            for (var i = 0; i < fn.body.length; i++) {\n                var stat = fn.body[i];\n                if (stat instanceof AST_LambdaDefinition) {\n                    var name = stat.name;\n                    if (!safe_to_inject) return false;\n                    if (arg_used.has(name.name)) return false;\n                    if (var_exists(defined, name.name)) return false;\n                    if (!all(stat.enclosed, function(def) {\n                        return def.scope === scope || def.scope === stat || !defined.has(def.name);\n                    })) return false;\n                    if (in_loop) in_loop.push(name.definition());\n                    continue;\n                }\n                if (!(stat instanceof AST_Var)) continue;\n                if (!safe_to_inject) return false;\n                for (var j = stat.definitions.length; --j >= 0;) {\n                    var name = stat.definitions[j].name;\n                    if (var_exists(defined, name.name)) return false;\n                    if (in_loop) in_loop.push(name.definition());\n                }\n            }\n            return true;\n        }\n\n        function can_inject_symbols() {\n            var defined = new Dictionary();\n            var level = 0, child;\n            scope = current;\n            do {\n                if (scope.variables) scope.variables.each(function(def) {\n                    defined.set(def.name, true);\n                });\n                child = scope;\n                scope = compressor.parent(level++);\n                if (scope instanceof AST_ClassField) {\n                    if (!scope.static) return false;\n                } else if (scope instanceof AST_DWLoop) {\n                    in_loop = [];\n                } else if (scope instanceof AST_For) {\n                    if (scope.init === child) continue;\n                    in_loop = [];\n                } else if (scope instanceof AST_ForEnumeration) {\n                    if (scope.init === child) continue;\n                    if (scope.object === child) continue;\n                    in_loop = [];\n                }\n            } while (!(scope instanceof AST_Scope));\n            insert = scope.body.indexOf(child) + 1;\n            if (!insert) return false;\n            if (!safe_from_await_yield(fn, avoid_await_yield(compressor, scope))) return false;\n            var safe_to_inject = (exp !== fn || fn.parent_scope.resolve() === scope) && !scope.pinned();\n            if (scope instanceof AST_Toplevel) {\n                if (compressor.toplevel.vars) {\n                    defined.set(\"arguments\", true);\n                } else {\n                    safe_to_inject = false;\n                }\n            }\n            arg_used = new Dictionary();\n            var inline = compressor.option(\"inline\");\n            if (!can_inject_args(defined, inline >= 2 && safe_to_inject)) return false;\n            if (!can_inject_vars(defined, inline >= 3 && safe_to_inject)) return false;\n            return !in_loop || in_loop.length == 0 || !is_reachable(fn, in_loop);\n        }\n\n        function append_var(decls, expressions, name, value) {\n            var def = name.definition();\n            if (!scope.var_names().has(name.name)) {\n                def.first_decl = null;\n                scope.var_names().set(name.name, true);\n                decls.push(make_node(AST_VarDef, name, {\n                    name: name,\n                    value: null,\n                }));\n            }\n            scope.variables.set(name.name, def);\n            scope.enclosed.push(def);\n            if (!value) return;\n            var sym = make_node(AST_SymbolRef, name);\n            def.assignments++;\n            def.references.push(sym);\n            expressions.push(make_node(AST_Assign, self, {\n                operator: \"=\",\n                left: sym,\n                right: value,\n            }));\n        }\n\n        function flatten_args(decls, expressions) {\n            var len = fn.argnames.length;\n            for (var i = self.args.length; --i >= len;) {\n                expressions.push(self.args[i]);\n            }\n            var default_args = [];\n            for (i = len; --i >= 0;) {\n                var argname = fn.argnames[i];\n                var name;\n                if (argname instanceof AST_DefaultValue) {\n                    default_args.push(argname);\n                    name = argname.name;\n                } else {\n                    name = argname;\n                }\n                var value = self.args[i];\n                if (name.unused || scope.var_names().has(name.name)) {\n                    if (value) expressions.push(value);\n                } else {\n                    var symbol = make_node(AST_SymbolVar, name);\n                    var def = name.definition();\n                    def.orig.push(symbol);\n                    def.eliminated++;\n                    if (name.unused !== undefined) {\n                        append_var(decls, expressions, symbol);\n                        if (value) expressions.push(value);\n                    } else {\n                        if (!value && argname === name && (in_loop\n                            || name.name == \"arguments\" && !is_arrow(fn) && is_arrow(scope))) {\n                            value = make_node(AST_Undefined, self);\n                        }\n                        append_var(decls, expressions, symbol, value);\n                    }\n                }\n            }\n            decls.reverse();\n            expressions.reverse();\n            for (i = default_args.length; --i >= 0;) {\n                var node = default_args[i];\n                if (node.name.unused !== undefined) {\n                    expressions.push(node.value);\n                } else {\n                    var sym = make_node(AST_SymbolRef, node.name);\n                    node.name.definition().references.push(sym);\n                    expressions.push(make_node(AST_Assign, node, {\n                        operator: \"=\",\n                        left: sym,\n                        right: node.value,\n                    }));\n                }\n            }\n        }\n\n        function flatten_destructured(decls, expressions) {\n            expressions.push(make_node(AST_Assign, self, {\n                operator: \"=\",\n                left: make_node(AST_DestructuredArray, self, {\n                    elements: fn.argnames.map(function(argname) {\n                        if (argname.unused) return make_node(AST_Hole, argname);\n                        return argname.convert_symbol(AST_SymbolRef, process);\n                    }),\n                    rest: fn.rest && fn.rest.convert_symbol(AST_SymbolRef, process),\n                }),\n                right: make_node(AST_Array, self, { elements: self.args.slice() }),\n            }));\n\n            function process(ref, name) {\n                if (name.unused) return make_void_lhs(name);\n                var def = name.definition();\n                def.assignments++;\n                def.references.push(ref);\n                var symbol = make_node(AST_SymbolVar, name);\n                def.orig.push(symbol);\n                def.eliminated++;\n                append_var(decls, expressions, symbol);\n            }\n        }\n\n        function flatten_vars(decls, expressions) {\n            var args = [ insert, 0 ];\n            var decl_var = [], expr_fn = [], expr_var = [], expr_loop = [], exprs = [];\n            fn.body.filter(in_loop ? function(stat) {\n                if (!(stat instanceof AST_LambdaDefinition)) return true;\n                var name = make_node(AST_SymbolVar, flatten_var(stat.name));\n                var def = name.definition();\n                def.fixed = false;\n                def.orig.push(name);\n                def.eliminated++;\n                append_var(decls, expr_fn, name, to_func_expr(stat, true));\n                return false;\n            } : function(stat) {\n                if (!(stat instanceof AST_LambdaDefinition)) return true;\n                var def = stat.name.definition();\n                scope.functions.set(def.name, def);\n                scope.variables.set(def.name, def);\n                scope.enclosed.push(def);\n                scope.var_names().set(def.name, true);\n                args.push(stat);\n                return false;\n            }).forEach(function(stat) {\n                if (!(stat instanceof AST_Var)) {\n                    if (stat instanceof AST_SimpleStatement) exprs.push(stat.body);\n                    return;\n                }\n                for (var j = 0; j < stat.definitions.length; j++) {\n                    var var_def = stat.definitions[j];\n                    var name = flatten_var(var_def.name);\n                    var value = var_def.value;\n                    if (value && exprs.length > 0) {\n                        exprs.push(value);\n                        value = make_sequence(var_def, exprs);\n                        exprs = [];\n                    }\n                    append_var(decl_var, expr_var, name, value);\n                    if (!in_loop) continue;\n                    if (arg_used.has(name.name)) continue;\n                    if (name.definition().orig.length == 1 && fn.functions.has(name.name)) continue;\n                    expr_loop.push(init_ref(compressor, name));\n                }\n            });\n            [].push.apply(decls, decl_var);\n            [].push.apply(expressions, expr_loop);\n            [].push.apply(expressions, expr_fn);\n            [].push.apply(expressions, expr_var);\n            return args;\n        }\n\n        function flatten_fn() {\n            var decls = [];\n            var expressions = [];\n            if (has_default > 1 || has_destructured || has_spread || fn.rest) {\n                flatten_destructured(decls, expressions);\n            } else {\n                flatten_args(decls, expressions);\n            }\n            var args = flatten_vars(decls, expressions);\n            expressions.push(value);\n            if (decls.length) args.push(make_node(AST_Var, fn, { definitions: decls }));\n            [].splice.apply(scope.body, args);\n            fn.enclosed.forEach(function(def) {\n                if (scope.var_names().has(def.name)) return;\n                scope.enclosed.push(def);\n                scope.var_names().set(def.name, true);\n            });\n            return expressions;\n        }\n    });\n\n    OPT(AST_New, function(self, compressor) {\n        if (compressor.option(\"unsafe\")) {\n            var exp = self.expression;\n            if (is_undeclared_ref(exp)) switch (exp.name) {\n              case \"Array\":\n              case \"Error\":\n              case \"Function\":\n              case \"Object\":\n              case \"RegExp\":\n                return make_node(AST_Call, self).transform(compressor);\n            }\n        }\n        if (compressor.option(\"sequences\")) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        if (compressor.option(\"unused\")) drop_unused_call_args(self, compressor);\n        return self;\n    });\n\n    // (a = b, x && a = c) ---> a = x ? c : b\n    // (a = b, x || a = c) ---> a = x ? b : c\n    function to_conditional_assignment(compressor, def, value, node) {\n        if (!(node instanceof AST_Binary)) return;\n        if (!(node.operator == \"&&\" || node.operator == \"||\")) return;\n        if (!(node.right instanceof AST_Assign)) return;\n        if (node.right.operator != \"=\") return;\n        if (!(node.right.left instanceof AST_SymbolRef)) return;\n        if (node.right.left.definition() !== def) return;\n        if (value.has_side_effects(compressor)) return;\n        if (!safe_from_assignment(node.left)) return;\n        if (!safe_from_assignment(node.right.right)) return;\n        def.replaced++;\n        return node.operator == \"&&\" ? make_node(AST_Conditional, node, {\n            condition: node.left,\n            consequent: node.right.right,\n            alternative: value,\n        }) : make_node(AST_Conditional, node, {\n            condition: node.left,\n            consequent: value,\n            alternative: node.right.right,\n        });\n\n        function safe_from_assignment(node) {\n            if (node.has_side_effects(compressor)) return;\n            var hit = false;\n            node.walk(new TreeWalker(function(node) {\n                if (hit) return true;\n                if (node instanceof AST_SymbolRef && node.definition() === def) return hit = true;\n            }));\n            return !hit;\n        }\n    }\n\n    OPT(AST_Sequence, function(self, compressor) {\n        var expressions = filter_for_side_effects();\n        var end = expressions.length - 1;\n        merge_assignments();\n        trim_right_for_undefined();\n        if (end == 0) {\n            self = maintain_this_binding(compressor.parent(), compressor.self(), expressions[0]);\n            if (!(self instanceof AST_Sequence)) self = self.optimize(compressor);\n            return self;\n        }\n        self.expressions = expressions;\n        return self;\n\n        function filter_for_side_effects() {\n            if (!compressor.option(\"side_effects\")) return self.expressions;\n            var expressions = [];\n            var first = first_in_statement(compressor);\n            var last = self.expressions.length - 1;\n            self.expressions.forEach(function(expr, index) {\n                if (index < last) expr = expr.drop_side_effect_free(compressor, first);\n                if (expr) {\n                    merge_sequence(expressions, expr);\n                    first = false;\n                }\n            });\n            return expressions;\n        }\n\n        function trim_right_for_undefined() {\n            if (!compressor.option(\"side_effects\")) return;\n            while (end > 0 && is_undefined(expressions[end], compressor)) end--;\n            if (end < expressions.length - 1) {\n                expressions[end] = make_node(AST_UnaryPrefix, self, {\n                    operator: \"void\",\n                    expression: expressions[end],\n                });\n                expressions.length = end + 1;\n            }\n        }\n\n        function is_simple_assign(node) {\n            return node instanceof AST_Assign\n                && node.operator == \"=\"\n                && node.left instanceof AST_SymbolRef\n                && node.left.definition();\n        }\n\n        function merge_assignments() {\n            for (var i = 1; i < end; i++) {\n                var prev = expressions[i - 1];\n                var def = is_simple_assign(prev);\n                if (!def) continue;\n                var expr = expressions[i];\n                if (compressor.option(\"conditionals\")) {\n                    var cond = to_conditional_assignment(compressor, def, prev.right, expr);\n                    if (cond) {\n                        prev.right = cond;\n                        expressions.splice(i--, 1);\n                        end--;\n                        continue;\n                    }\n                }\n                if (compressor.option(\"dead_code\")\n                    && is_simple_assign(expr) === def\n                    && expr.right.is_constant_expression(def.scope.resolve())) {\n                    expressions[--i] = prev.right;\n                }\n            }\n        }\n    });\n\n    OPT(AST_UnaryPostfix, function(self, compressor) {\n        if (compressor.option(\"sequences\")) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        return try_evaluate(compressor, self);\n    });\n\n    var SIGN_OPS = makePredicate(\"+ -\");\n    var MULTIPLICATIVE_OPS = makePredicate(\"* / %\");\n    OPT(AST_UnaryPrefix, function(self, compressor) {\n        var op = self.operator;\n        var exp = self.expression;\n        if (compressor.option(\"sequences\") && can_lift()) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        switch (op) {\n          case \"+\":\n            if (!compressor.option(\"evaluate\")) break;\n            if (!exp.is_number(compressor, true)) break;\n            var parent = compressor.parent();\n            if (parent instanceof AST_UnaryPrefix && parent.operator == \"delete\") break;\n            return exp;\n          case \"-\":\n            if (exp instanceof AST_Infinity) exp = exp.transform(compressor);\n            // avoids infinite recursion of numerals\n            if (exp instanceof AST_Number || exp instanceof AST_Infinity) return self;\n            break;\n          case \"!\":\n            if (!compressor.option(\"booleans\")) break;\n            if (exp.is_truthy()) return make_sequence(self, [ exp, make_node(AST_False, self) ]).optimize(compressor);\n            if (compressor.in_boolean_context()) {\n                // !!foo ---> foo, if we're in boolean context\n                if (exp instanceof AST_UnaryPrefix && exp.operator == \"!\") return exp.expression;\n                if (exp instanceof AST_Binary) {\n                    var first = first_in_statement(compressor);\n                    self = (first ? best_of_statement : best_of_expression)(self, exp.negate(compressor, first));\n                }\n            }\n            break;\n          case \"delete\":\n            if (!compressor.option(\"evaluate\")) break;\n            if (may_not_delete(exp)) break;\n            return make_sequence(self, [ exp, make_node(AST_True, self) ]).optimize(compressor);\n          case \"typeof\":\n            if (!compressor.option(\"booleans\")) break;\n            if (!compressor.in_boolean_context()) break;\n            // typeof always returns a non-empty string, thus always truthy\n            AST_Node.warn(\"Boolean expression always true [{start}]\", self);\n            var exprs = [ make_node(AST_True, self) ];\n            if (!(exp instanceof AST_SymbolRef && can_drop_symbol(exp, compressor))) exprs.unshift(exp);\n            return make_sequence(self, exprs).optimize(compressor);\n          case \"void\":\n            if (!compressor.option(\"side_effects\")) break;\n            exp = exp.drop_side_effect_free(compressor);\n            if (!exp) return make_node(AST_Undefined, self).optimize(compressor);\n            self.expression = exp;\n            return self;\n        }\n        if (compressor.option(\"evaluate\")\n            && exp instanceof AST_Binary\n            && SIGN_OPS[op]\n            && MULTIPLICATIVE_OPS[exp.operator]\n            && (exp.left.is_constant() || !exp.right.has_side_effects(compressor))) {\n            return make_node(AST_Binary, self, {\n                operator: exp.operator,\n                left: make_node(AST_UnaryPrefix, exp.left, {\n                    operator: op,\n                    expression: exp.left,\n                }),\n                right: exp.right,\n            });\n        }\n        return try_evaluate(compressor, self);\n\n        function may_not_delete(node) {\n            return node instanceof AST_Infinity\n                || node instanceof AST_NaN\n                || node instanceof AST_NewTarget\n                || node instanceof AST_PropAccess\n                || node instanceof AST_SymbolRef\n                || node instanceof AST_Undefined;\n        }\n\n        function can_lift() {\n            switch (op) {\n              case \"delete\":\n                return !may_not_delete(exp.tail_node());\n              case \"typeof\":\n                return !is_undeclared_ref(exp.tail_node());\n              default:\n                return true;\n            }\n        }\n    });\n\n    OPT(AST_Await, function(self, compressor) {\n        if (!compressor.option(\"awaits\")) return self;\n        if (compressor.option(\"sequences\")) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        if (compressor.option(\"side_effects\")) {\n            var exp = self.expression;\n            if (exp instanceof AST_Await) return exp.optimize(compressor);\n            if (exp instanceof AST_UnaryPrefix && exp.expression instanceof AST_Await) return exp.optimize(compressor);\n            for (var level = 0, node = self, parent; parent = compressor.parent(level++); node = parent) {\n                if (is_arrow(parent)) {\n                    if (parent.value === node) return exp.optimize(compressor);\n                } else if (parent instanceof AST_Return) {\n                    var drop = true;\n                    do {\n                        node = parent;\n                        parent = compressor.parent(level++);\n                        if (parent instanceof AST_Try && (parent.bfinally || parent.bcatch) !== node) {\n                            drop = false;\n                            break;\n                        }\n                    } while (parent && !(parent instanceof AST_Scope));\n                    if (drop) return exp.optimize(compressor);\n                } else if (parent instanceof AST_Sequence) {\n                    if (parent.tail_node() === node) continue;\n                }\n                break;\n            }\n        }\n        return self;\n    });\n\n    OPT(AST_Yield, function(self, compressor) {\n        if (!compressor.option(\"yields\")) return self;\n        if (compressor.option(\"sequences\")) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        var exp = self.expression;\n        if (self.nested && exp.TYPE == \"Call\") {\n            var inlined = exp.clone().optimize(compressor);\n            if (inlined.TYPE != \"Call\") return inlined;\n        }\n        return self;\n    });\n\n    AST_Binary.DEFMETHOD(\"lift_sequences\", function(compressor) {\n        if (this.left instanceof AST_PropAccess) {\n            if (!(this.left.expression instanceof AST_Sequence)) return this;\n            var x = this.left.expression.expressions.slice();\n            var e = this.clone();\n            e.left = e.left.clone();\n            e.left.expression = x.pop();\n            x.push(e);\n            return make_sequence(this, x);\n        }\n        if (this.left instanceof AST_Sequence) {\n            var x = this.left.expressions.slice();\n            var e = this.clone();\n            e.left = x.pop();\n            x.push(e);\n            return make_sequence(this, x);\n        }\n        if (this.right instanceof AST_Sequence) {\n            if (this.left.has_side_effects(compressor)) return this;\n            var assign = this.operator == \"=\" && this.left instanceof AST_SymbolRef;\n            var x = this.right.expressions;\n            var last = x.length - 1;\n            for (var i = 0; i < last; i++) {\n                if (!assign && x[i].has_side_effects(compressor)) break;\n            }\n            if (i == last) {\n                x = x.slice();\n                var e = this.clone();\n                e.right = x.pop();\n                x.push(e);\n                return make_sequence(this, x);\n            }\n            if (i > 0) {\n                var e = this.clone();\n                e.right = make_sequence(this.right, x.slice(i));\n                x = x.slice(0, i);\n                x.push(e);\n                return make_sequence(this, x);\n            }\n        }\n        return this;\n    });\n\n    var indexFns = makePredicate(\"indexOf lastIndexOf\");\n    var commutativeOperators = makePredicate(\"== === != !== * & | ^\");\n    function is_object(node, plain) {\n        if (node instanceof AST_Assign) return !plain && node.operator == \"=\" && is_object(node.right);\n        if (node instanceof AST_New) return !plain;\n        if (node instanceof AST_Sequence) return is_object(node.tail_node(), plain);\n        if (node instanceof AST_SymbolRef) return !plain && is_object(node.fixed_value());\n        return node instanceof AST_Array\n            || node instanceof AST_Class\n            || node instanceof AST_Lambda\n            || node instanceof AST_Object;\n    }\n\n    function can_drop_op(node, compressor) {\n        var rhs = node.right;\n        switch (node.operator) {\n          case \"in\":\n            return is_object(rhs) || compressor && compressor.option(\"unsafe_comps\");\n          case \"instanceof\":\n            if (rhs instanceof AST_SymbolRef) rhs = rhs.fixed_value();\n            if (rhs instanceof AST_Defun || rhs instanceof AST_Function || is_generator(rhs)) return true;\n            if (is_lambda(rhs) && node.left.is_constant()) return true;\n            return compressor && compressor.option(\"unsafe_comps\");\n          default:\n            return true;\n        }\n    }\n\n    function needs_enqueuing(compressor, node) {\n        if (node.is_constant()) return true;\n        if (node instanceof AST_Assign) return node.operator != \"=\" || needs_enqueuing(compressor, node.right);\n        if (node instanceof AST_Binary) {\n            return !lazy_op[node.operator]\n                || needs_enqueuing(compressor, node.left) && needs_enqueuing(compressor, node.right);\n        }\n        if (node instanceof AST_Call) {\n            if (!is_async(node.expression)) return false;\n            var has_await = false;\n            walk_body(node.expression, new TreeWalker(function(expr) {\n                if (has_await) return true;\n                if (expr instanceof AST_Await) return has_await = true;\n                if (expr !== node && expr instanceof AST_Scope) return true;\n            }));\n            return !has_await;\n        }\n        if (node instanceof AST_Conditional) {\n            return needs_enqueuing(compressor, node.consequent) && needs_enqueuing(compressor, node.alternative);\n        }\n        if (node instanceof AST_Sequence) return needs_enqueuing(compressor, node.tail_node());\n        if (node instanceof AST_SymbolRef) {\n            var fixed = node.fixed_value();\n            return fixed && needs_enqueuing(compressor, fixed);\n        }\n        if (node instanceof AST_Template) return !node.tag || is_raw_tag(compressor, node.tag);\n        if (node instanceof AST_Unary) return true;\n    }\n\n    function extract_lhs(node, compressor) {\n        if (node instanceof AST_Assign) return is_lhs_read_only(node.left, compressor) ? node : node.left;\n        if (node instanceof AST_Sequence) return extract_lhs(node.tail_node(), compressor);\n        if (node instanceof AST_UnaryPrefix && UNARY_POSTFIX[node.operator]) {\n            return is_lhs_read_only(node.expression, compressor) ? node : node.expression;\n        }\n        return node;\n    }\n\n    function repeatable(compressor, node) {\n        if (node instanceof AST_Dot) return repeatable(compressor, node.expression);\n        if (node instanceof AST_Sub) {\n            return repeatable(compressor, node.expression) && repeatable(compressor, node.property);\n        }\n        if (node instanceof AST_Symbol) return true;\n        return !node.has_side_effects(compressor);\n    }\n\n    function swap_chain(self, compressor) {\n        var rhs = self.right.tail_node();\n        if (rhs !== self.right) {\n            var exprs = self.right.expressions.slice(0, -1);\n            exprs.push(rhs.left);\n            rhs = rhs.clone();\n            rhs.left = make_sequence(self.right, exprs);\n            self.right = rhs;\n        }\n        self.left = make_node(AST_Binary, self, {\n            operator: self.operator,\n            left: self.left,\n            right: rhs.left,\n            start: self.left.start,\n            end: rhs.left.end,\n        });\n        self.right = rhs.right;\n        if (compressor) {\n            var left = self.left.transform(compressor);\n            if (left !== self.left) {\n                self = self.clone();\n                self.left = left;\n            }\n            return self;\n        }\n        if (self.operator == rhs.left.operator) swap_chain(self.left);\n    }\n\n    OPT(AST_Binary, function(self, compressor) {\n        if (commutativeOperators[self.operator]\n            && self.right.is_constant()\n            && !self.left.is_constant()\n            && !(self.left instanceof AST_Binary\n                && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {\n            // if right is a constant, whatever side effects the\n            // left side might have could not influence the\n            // result.  hence, force switch.\n            reverse();\n        }\n        if (compressor.option(\"sequences\")) {\n            var seq = self.lift_sequences(compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        if (compressor.option(\"assignments\") && lazy_op[self.operator]) {\n            var lhs = extract_lhs(self.left, compressor);\n            var right = self.right;\n            // a || (a = x) ---> a = a || x\n            // (a = x) && (a = y) ---> a = (a = x) && y\n            if (lhs instanceof AST_SymbolRef\n                && right instanceof AST_Assign\n                && right.operator == \"=\"\n                && lhs.equals(right.left)) {\n                lhs = lhs.clone();\n                var assign = make_node(AST_Assign, self, {\n                    operator: \"=\",\n                    left: lhs,\n                    right: make_node(AST_Binary, self, {\n                        operator: self.operator,\n                        left: self.left,\n                        right: right.right,\n                    }),\n                });\n                if (lhs.fixed) {\n                    lhs.fixed = function() {\n                        return assign.right;\n                    };\n                    lhs.fixed.assigns = [ assign ];\n                }\n                var def = lhs.definition();\n                def.references.push(lhs);\n                def.replaced++;\n                return assign.optimize(compressor);\n            }\n        }\n        if (compressor.option(\"comparisons\")) switch (self.operator) {\n          case \"===\":\n          case \"!==\":\n            if (is_undefined(self.left, compressor) && self.right.is_defined(compressor)) {\n                AST_Node.warn(\"Expression always defined [{start}]\", self);\n                return make_sequence(self, [\n                    self.right,\n                    make_node(self.operator == \"===\" ? AST_False : AST_True, self),\n                ]).optimize(compressor);\n            }\n            var is_strict_comparison = true;\n            if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||\n                (self.left.is_number(compressor) && self.right.is_number(compressor)) ||\n                (self.left.is_boolean(compressor) && self.right.is_boolean(compressor)) ||\n                repeatable(compressor, self.left) && self.left.equals(self.right)) {\n                self.operator = self.operator.slice(0, 2);\n            }\n            // XXX: intentionally falling down to the next case\n          case \"==\":\n          case \"!=\":\n            // void 0 == x ---> null == x\n            if (!is_strict_comparison && is_undefined(self.left, compressor)) {\n                self.left = make_node(AST_Null, self.left);\n            }\n            // \"undefined\" == typeof x ---> undefined === x\n            else if (compressor.option(\"typeofs\")\n                && self.left instanceof AST_String\n                && self.left.value == \"undefined\"\n                && self.right instanceof AST_UnaryPrefix\n                && self.right.operator == \"typeof\") {\n                var expr = self.right.expression;\n                if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)\n                    : !(expr instanceof AST_PropAccess && compressor.option(\"ie\"))) {\n                    self.right = expr;\n                    self.left = make_node(AST_Undefined, self.left).optimize(compressor);\n                    if (self.operator.length == 2) self.operator += \"=\";\n                }\n            }\n            // obj !== obj ---> false\n            else if (self.left instanceof AST_SymbolRef\n                && self.right instanceof AST_SymbolRef\n                && self.left.definition() === self.right.definition()\n                && is_object(self.left)) {\n                return make_node(self.operator[0] == \"=\" ? AST_True : AST_False, self).optimize(compressor);\n            }\n            break;\n          case \"&&\":\n          case \"||\":\n            // void 0 !== x && null !== x ---> null != x\n            // void 0 === x.a || null === x.a ---> null == x.a\n            var left = self.left;\n            if (left.inlined_node) left = left.inlined_node;\n            if (!(left instanceof AST_Binary)) break;\n            if (left.operator != (self.operator == \"&&\" ? \"!==\" : \"===\")) break;\n            var right = self.right;\n            if (right.inlined_node) right = right.inlined_node;\n            if (!(right instanceof AST_Binary)) break;\n            if (left.operator != right.operator) break;\n            if (is_undefined(left.left, compressor) && right.left instanceof AST_Null\n                || left.left instanceof AST_Null && is_undefined(right.left, compressor)) {\n                var expr = extract_lhs(left.right, compressor);\n                if (!repeatable(compressor, expr)) break;\n                if (!expr.equals(right.right)) break;\n                left.operator = left.operator.slice(0, -1);\n                left.left = make_node(AST_Null, self);\n                return left;\n            }\n            break;\n        }\n        var in_bool = false;\n        var parent = compressor.parent();\n        if (compressor.option(\"booleans\")) {\n            var lhs = extract_lhs(self.left, compressor);\n            if (lazy_op[self.operator] && repeatable(compressor, lhs)) {\n                // a || a ---> a\n                // (a = x) && a --> a = x\n                if (lhs.equals(self.right)) {\n                    return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);\n                }\n                mark_duplicate_condition(compressor, lhs);\n            }\n            in_bool = compressor.in_boolean_context();\n        }\n        if (in_bool) switch (self.operator) {\n          case \"+\":\n            var ev = self.left.evaluate(compressor, true);\n            if (ev && typeof ev == \"string\" || (ev = self.right.evaluate(compressor, true)) && typeof ev == \"string\") {\n                AST_Node.warn(\"+ in boolean context always true [{start}]\", self);\n                var exprs = [];\n                if (self.left.evaluate(compressor) instanceof AST_Node) exprs.push(self.left);\n                if (self.right.evaluate(compressor) instanceof AST_Node) exprs.push(self.right);\n                switch (exprs.length) {\n                  case 0:\n                    return make_node(AST_True, self).optimize(compressor);\n                  case 1:\n                    exprs[0] = exprs[0].clone();\n                    exprs.push(make_node(AST_True, self));\n                    return make_sequence(self, exprs).optimize(compressor);\n                }\n                self.truthy = true;\n            }\n            break;\n          case \"==\":\n            if (self.left instanceof AST_String && self.left.value == \"\" && self.right.is_string(compressor)) {\n                return make_node(AST_UnaryPrefix, self, {\n                    operator: \"!\",\n                    expression: self.right,\n                }).optimize(compressor);\n            }\n            break;\n          case \"!=\":\n            if (self.left instanceof AST_String && self.left.value == \"\" && self.right.is_string(compressor)) {\n                return self.right.optimize(compressor);\n            }\n            break;\n        }\n        if (compressor.option(\"comparisons\") && self.is_boolean(compressor)) {\n            if (parent.TYPE != \"Binary\") {\n                var negated = make_node(AST_UnaryPrefix, self, {\n                    operator: \"!\",\n                    expression: self.negate(compressor),\n                });\n                if (best_of(compressor, self, negated) === negated) return negated;\n            }\n            switch (self.operator) {\n              case \">\": reverse(\"<\"); break;\n              case \">=\": reverse(\"<=\"); break;\n            }\n        }\n        if (compressor.option(\"conditionals\") && lazy_op[self.operator]) {\n            if (self.left instanceof AST_Binary && self.operator == self.left.operator) {\n                var before = make_node(AST_Binary, self, {\n                    operator: self.operator,\n                    left: self.left.right,\n                    right: self.right,\n                });\n                var after = before.transform(compressor);\n                if (before !== after) {\n                    self.left = self.left.left;\n                    self.right = after;\n                }\n            }\n            // x && (y && z) ---> x && y && z\n            // w || (x, y || z) ---> w || (x, y) || z\n            var rhs = self.right.tail_node();\n            if (rhs instanceof AST_Binary && self.operator == rhs.operator) self = swap_chain(self, compressor);\n        }\n        if (compressor.option(\"strings\") && self.operator == \"+\") {\n            // \"foo\" + 42 + \"\" ---> \"foo\" + 42\n            if (self.right instanceof AST_String\n                && self.right.value == \"\"\n                && self.left.is_string(compressor)) {\n                return self.left.optimize(compressor);\n            }\n            // \"\" + (\"foo\" + 42) ---> \"foo\" + 42\n            if (self.left instanceof AST_String\n                && self.left.value == \"\"\n                && self.right.is_string(compressor)) {\n                return self.right.optimize(compressor);\n            }\n            // \"\" + 42 + \"foo\" ---> 42 + \"foo\"\n            if (self.left instanceof AST_Binary\n                && self.left.operator == \"+\"\n                && self.left.left instanceof AST_String\n                && self.left.left.value == \"\"\n                && self.right.is_string(compressor)\n                && (self.left.right.is_constant() || !self.right.has_side_effects(compressor))) {\n                self.left = self.left.right;\n                return self.optimize(compressor);\n            }\n            // \"x\" + (y + \"z\") ---> \"x\" + y + \"z\"\n            // w + (x, \"y\" + z) ---> w + (x, \"y\") + z\n            var rhs = self.right.tail_node();\n            if (rhs instanceof AST_Binary\n                && self.operator == rhs.operator\n                && (self.left.is_string(compressor) && rhs.is_string(compressor)\n                    || rhs.left.is_string(compressor)\n                        && (self.left.is_constant() || !rhs.right.has_side_effects(compressor)))) {\n                self = swap_chain(self, compressor);\n            }\n        }\n        if (compressor.option(\"evaluate\")) {\n            var associative = true;\n            switch (self.operator) {\n              case \"&&\":\n                var ll = fuzzy_eval(compressor, self.left);\n                if (!ll) {\n                    AST_Node.warn(\"Condition left of && always false [{start}]\", self);\n                    return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);\n                } else if (!(ll instanceof AST_Node)) {\n                    AST_Node.warn(\"Condition left of && always true [{start}]\", self);\n                    return make_sequence(self, [ self.left.clone(), self.right ]).optimize(compressor);\n                }\n                if (!self.right.evaluate(compressor, true)) {\n                    if (in_bool && !(self.right.evaluate(compressor) instanceof AST_Node)) {\n                        AST_Node.warn(\"Boolean && always false [{start}]\", self);\n                        return make_sequence(self, [ self.left, make_node(AST_False, self) ]).optimize(compressor);\n                    } else self.falsy = true;\n                } else if ((in_bool || parent.operator == \"&&\" && parent.left === compressor.self())\n                    && !(self.right.evaluate(compressor) instanceof AST_Node)) {\n                    AST_Node.warn(\"Dropping side-effect-free && [{start}]\", self);\n                    return self.left.optimize(compressor);\n                }\n                // (x || false) && y ---> x ? y : false\n                if (self.left.operator == \"||\") {\n                    var lr = fuzzy_eval(compressor, self.left.right);\n                    if (!lr) return make_node(AST_Conditional, self, {\n                        condition: self.left.left,\n                        consequent: self.right,\n                        alternative: self.left.right,\n                    }).optimize(compressor);\n                }\n                break;\n              case \"??\":\n                var nullish = true;\n              case \"||\":\n                var ll = fuzzy_eval(compressor, self.left, nullish);\n                if (nullish ? ll == null : !ll) {\n                    AST_Node.warn(\"Condition left of {operator} always {value} [{start}]\", {\n                        operator: self.operator,\n                        value: nullish ? \"nullish\" : \"false\",\n                        start: self.start,\n                    });\n                    return make_sequence(self, [ self.left, self.right ]).optimize(compressor);\n                } else if (!(ll instanceof AST_Node)) {\n                    AST_Node.warn(\"Condition left of {operator} always {value} [{start}]\", {\n                        operator: self.operator,\n                        value: nullish ? \"defined\" : \"true\",\n                        start: self.start,\n                    });\n                    return maintain_this_binding(parent, compressor.self(), self.left).optimize(compressor);\n                }\n                var rr;\n                if (!nullish && (rr = self.right.evaluate(compressor, true)) && !(rr instanceof AST_Node)) {\n                    if (in_bool && !(self.right.evaluate(compressor) instanceof AST_Node)) {\n                        AST_Node.warn(\"Boolean || always true [{start}]\", self);\n                        return make_sequence(self, [ self.left, make_node(AST_True, self) ]).optimize(compressor);\n                    } else self.truthy = true;\n                } else if ((in_bool || parent.operator == \"||\" && parent.left === compressor.self())\n                    && !self.right.evaluate(compressor)) {\n                    AST_Node.warn(\"Dropping side-effect-free {operator} [{start}]\", self);\n                    return self.left.optimize(compressor);\n                }\n                // x && true || y ---> x ? true : y\n                if (!nullish && self.left.operator == \"&&\") {\n                    var lr = fuzzy_eval(compressor, self.left.right);\n                    if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, {\n                        condition: self.left.left,\n                        consequent: self.left.right,\n                        alternative: self.right,\n                    }).optimize(compressor);\n                }\n                break;\n              case \"+\":\n                // \"foo\" + (\"bar\" + x) ---> \"foobar\" + x\n                if (self.left instanceof AST_Constant\n                    && self.right instanceof AST_Binary\n                    && self.right.operator == \"+\"\n                    && self.right.left instanceof AST_Constant\n                    && self.right.is_string(compressor)) {\n                    self = make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: make_node(AST_String, self.left, {\n                            value: \"\" + self.left.value + self.right.left.value,\n                            start: self.left.start,\n                            end: self.right.left.end,\n                        }),\n                        right: self.right.right,\n                    });\n                }\n                // (x + \"foo\") + \"bar\" ---> x + \"foobar\"\n                if (self.right instanceof AST_Constant\n                    && self.left instanceof AST_Binary\n                    && self.left.operator == \"+\"\n                    && self.left.right instanceof AST_Constant\n                    && self.left.is_string(compressor)) {\n                    self = make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: self.left.left,\n                        right: make_node(AST_String, self.right, {\n                            value: \"\" + self.left.right.value + self.right.value,\n                            start: self.left.right.start,\n                            end: self.right.end,\n                        }),\n                    });\n                }\n                // a + -b ---> a - b\n                if (self.right instanceof AST_UnaryPrefix\n                    && self.right.operator == \"-\"\n                    && self.left.is_number(compressor)) {\n                    self = make_node(AST_Binary, self, {\n                        operator: \"-\",\n                        left: self.left,\n                        right: self.right.expression,\n                    });\n                    break;\n                }\n                // -a + b ---> b - a\n                if (self.left instanceof AST_UnaryPrefix\n                    && self.left.operator == \"-\"\n                    && reversible()\n                    && self.right.is_number(compressor)) {\n                    self = make_node(AST_Binary, self, {\n                        operator: \"-\",\n                        left: self.right,\n                        right: self.left.expression,\n                    });\n                    break;\n                }\n                // (a + b) + 3 ---> 3 + (a + b)\n                if (compressor.option(\"unsafe_math\")\n                    && self.left instanceof AST_Binary\n                    && PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]\n                    && self.right.is_constant()\n                    && (self.right.is_boolean(compressor) || self.right.is_number(compressor))\n                    && self.left.is_number(compressor)\n                    && !self.left.right.is_constant()\n                    && (self.left.left.is_boolean(compressor) || self.left.left.is_number(compressor))) {\n                    self = make_node(AST_Binary, self, {\n                        operator: self.left.operator,\n                        left: make_node(AST_Binary, self, {\n                            operator: self.operator,\n                            left: self.right,\n                            right: self.left.left,\n                        }),\n                        right: self.left.right,\n                    });\n                    break;\n                }\n              case \"-\":\n                // a - -b ---> a + b\n                if (self.right instanceof AST_UnaryPrefix\n                    && self.right.operator == \"-\"\n                    && self.left.is_number(compressor)\n                    && self.right.expression.is_number(compressor)) {\n                    self = make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: self.left,\n                        right: self.right.expression,\n                    });\n                    break;\n                }\n              case \"*\":\n              case \"/\":\n                associative = compressor.option(\"unsafe_math\");\n                // +a - b ---> a - b\n                // a - +b ---> a - b\n                if (self.operator != \"+\") [ \"left\", \"right\" ].forEach(function(operand) {\n                    var node = self[operand];\n                    if (node instanceof AST_UnaryPrefix && node.operator == \"+\") {\n                        var exp = node.expression;\n                        if (exp.is_boolean(compressor) || exp.is_number(compressor) || exp.is_string(compressor)) {\n                            self[operand] = exp;\n                        }\n                    }\n                });\n              case \"&\":\n              case \"|\":\n              case \"^\":\n                // a + +b ---> +b + a\n                if (self.operator != \"-\"\n                    && self.operator != \"/\"\n                    && (self.left.is_boolean(compressor) || self.left.is_number(compressor))\n                    && (self.right.is_boolean(compressor) || self.right.is_number(compressor))\n                    && reversible()\n                    && !(self.left instanceof AST_Binary\n                        && self.left.operator != self.operator\n                        && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {\n                    self = best_of(compressor, self, make_node(AST_Binary, self, {\n                        operator: self.operator,\n                        left: self.right,\n                        right: self.left,\n                    }), self.right instanceof AST_Constant && !(self.left instanceof AST_Constant));\n                }\n                if (!associative || !self.is_number(compressor)) break;\n                // a + (b + c) ---> (a + b) + c\n                if (self.right instanceof AST_Binary\n                    && self.right.operator != \"%\"\n                    && PRECEDENCE[self.right.operator] == PRECEDENCE[self.operator]\n                    && self.right.is_number(compressor)\n                    && (self.operator != \"+\"\n                        || self.right.left.is_boolean(compressor)\n                        || self.right.left.is_number(compressor))\n                    && (self.operator != \"-\" || !self.left.is_negative_zero())\n                    && (self.right.left.is_constant_expression()\n                        || !self.right.right.has_side_effects(compressor))\n                    && !is_modify_array(self.right.right)) {\n                    self = make_node(AST_Binary, self, {\n                        operator: align(self.operator, self.right.operator),\n                        left: make_node(AST_Binary, self.left, {\n                            operator: self.operator,\n                            left: self.left,\n                            right: self.right.left,\n                            start: self.left.start,\n                            end: self.right.left.end,\n                        }),\n                        right: self.right.right,\n                    });\n                    if (self.operator == \"+\"\n                        && !self.right.is_boolean(compressor)\n                        && !self.right.is_number(compressor)) {\n                        self.right = make_node(AST_UnaryPrefix, self.right, {\n                            operator: \"+\",\n                            expression: self.right,\n                        });\n                    }\n                }\n                // (2 * n) * 3 ---> 6 * n\n                // (n + 2) + 3 ---> n + 5\n                if (self.right instanceof AST_Constant\n                    && self.left instanceof AST_Binary\n                    && self.left.operator != \"%\"\n                    && PRECEDENCE[self.left.operator] == PRECEDENCE[self.operator]\n                    && self.left.is_number(compressor)) {\n                    if (self.left.left instanceof AST_Constant) {\n                        var lhs = make_binary(self.operator, self.left.left, self.right, {\n                            start: self.left.left.start,\n                            end: self.right.end,\n                        });\n                        self = make_binary(self.left.operator, try_evaluate(compressor, lhs), self.left.right, self);\n                    } else if (self.left.right instanceof AST_Constant) {\n                        var op = align(self.left.operator, self.operator);\n                        var rhs = try_evaluate(compressor, make_binary(op, self.left.right, self.right, self.left));\n                        if (rhs.is_constant()\n                            && !(self.left.operator == \"-\"\n                                && self.right.value != 0\n                                && +rhs.value == 0\n                                && self.left.left.is_negative_zero())) {\n                            self = make_binary(self.left.operator, self.left.left, rhs, self);\n                        }\n                    }\n                }\n                break;\n              case \"instanceof\":\n                if (!can_drop_op(self, compressor)) break;\n                if (is_lambda(self.right)) return make_sequence(self, [\n                    self.left,\n                    self.right,\n                    make_node(AST_False, self),\n                ]).optimize(compressor);\n                break;\n            }\n            if (!(parent instanceof AST_UnaryPrefix && parent.operator == \"delete\")) {\n                if (self.left instanceof AST_Number && !self.right.is_constant()) switch (self.operator) {\n                  // 0 + n ---> n\n                  case \"+\":\n                    if (self.left.value == 0) {\n                        if (self.right.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, {\n                            operator: \"+\",\n                            expression: self.right,\n                        }).optimize(compressor);\n                        if (self.right.is_number(compressor) && !self.right.is_negative_zero()) return self.right;\n                    }\n                    break;\n                  // 1 * n ---> n\n                  case \"*\":\n                    if (self.left.value == 1) return make_node(AST_UnaryPrefix, self, {\n                        operator: \"+\",\n                        expression: self.right,\n                    }).optimize(compressor);\n                    break;\n                }\n                if (self.right instanceof AST_Number && !self.left.is_constant()) switch (self.operator) {\n                  // n + 0 ---> n\n                  case \"+\":\n                    if (self.right.value == 0) {\n                        if (self.left.is_boolean(compressor)) return make_node(AST_UnaryPrefix, self, {\n                            operator: \"+\",\n                            expression: self.left,\n                        }).optimize(compressor);\n                        if (self.left.is_number(compressor) && !self.left.is_negative_zero()) return self.left;\n                    }\n                    break;\n                  // n - 0 ---> n\n                  case \"-\":\n                    if (self.right.value == 0) return make_node(AST_UnaryPrefix, self, {\n                        operator: \"+\",\n                        expression: self.left,\n                    }).optimize(compressor);\n                    break;\n                  // n / 1 ---> n\n                  case \"/\":\n                    if (self.right.value == 1) return make_node(AST_UnaryPrefix, self, {\n                        operator: \"+\",\n                        expression: self.left,\n                    }).optimize(compressor);\n                    break;\n                }\n            }\n        }\n        if (compressor.option(\"typeofs\")) switch (self.operator) {\n          case \"&&\":\n            mark_locally_defined(self.left, self.right, null);\n            break;\n          case \"||\":\n            mark_locally_defined(self.left, null, self.right);\n            break;\n        }\n        if (compressor.option(\"unsafe\")) {\n            var indexRight = is_indexFn(self.right);\n            if (in_bool\n                && indexRight\n                && (self.operator == \"==\" || self.operator == \"!=\")\n                && self.left instanceof AST_Number\n                && self.left.value == 0) {\n                return (self.operator == \"==\" ? make_node(AST_UnaryPrefix, self, {\n                    operator: \"!\",\n                    expression: self.right,\n                }) : self.right).optimize(compressor);\n            }\n            var indexLeft = is_indexFn(self.left);\n            if (compressor.option(\"comparisons\") && is_indexOf_match_pattern()) {\n                var node = make_node(AST_UnaryPrefix, self, {\n                    operator: \"!\",\n                    expression: make_node(AST_UnaryPrefix, self, {\n                        operator: \"~\",\n                        expression: indexLeft ? self.left : self.right,\n                    }),\n                });\n                switch (self.operator) {\n                  case \"<\":\n                    if (indexLeft) break;\n                  case \"<=\":\n                  case \"!=\":\n                    node = make_node(AST_UnaryPrefix, self, {\n                        operator: \"!\",\n                        expression: node,\n                    });\n                    break;\n                }\n                return node.optimize(compressor);\n            }\n        }\n        return try_evaluate(compressor, self);\n\n        function is_modify_array(node) {\n            var found = false;\n            node.walk(new TreeWalker(function(node) {\n                if (found) return true;\n                if (node instanceof AST_Assign) {\n                    if (node.left instanceof AST_PropAccess) return found = true;\n                } else if (node instanceof AST_Unary) {\n                    if (unary_side_effects[node.operator] && node.expression instanceof AST_PropAccess) {\n                        return found = true;\n                    }\n                }\n            }));\n            return found;\n        }\n\n        function align(ref, op) {\n            switch (ref) {\n              case \"-\":\n                return op == \"+\" ? \"-\" : \"+\";\n              case \"/\":\n                return op == \"*\" ? \"/\" : \"*\";\n              default:\n                return op;\n            }\n        }\n\n        function make_binary(op, left, right, orig) {\n            if (op == \"+\") {\n                if (!left.is_boolean(compressor) && !left.is_number(compressor)) {\n                    left = make_node(AST_UnaryPrefix, left, {\n                        operator: \"+\",\n                        expression: left,\n                    });\n                }\n                if (!right.is_boolean(compressor) && !right.is_number(compressor)) {\n                    right = make_node(AST_UnaryPrefix, right, {\n                        operator: \"+\",\n                        expression: right,\n                    });\n                }\n            }\n            return make_node(AST_Binary, orig, {\n                operator: op,\n                left: left,\n                right: right,\n            });\n        }\n\n        function is_indexFn(node) {\n            while (node instanceof AST_Assign && node.operator == \"=\") node = node.right;\n            return node.TYPE == \"Call\"\n                && node.expression instanceof AST_Dot\n                && indexFns[node.expression.property];\n        }\n\n        function is_indexOf_match_pattern() {\n            switch (self.operator) {\n              case \"<=\":\n                // 0 <= array.indexOf(string) ---> !!~array.indexOf(string)\n                return indexRight && self.left instanceof AST_Number && self.left.value == 0;\n              case \"<\":\n                // array.indexOf(string) < 0 ---> !~array.indexOf(string)\n                if (indexLeft && self.right instanceof AST_Number && self.right.value == 0) return true;\n                // -1 < array.indexOf(string) ---> !!~array.indexOf(string)\n              case \"==\":\n              case \"!=\":\n                // -1 == array.indexOf(string) ---> !~array.indexOf(string)\n                // -1 != array.indexOf(string) ---> !!~array.indexOf(string)\n                if (!indexRight) return false;\n                return self.left instanceof AST_Number && self.left.value == -1\n                    || self.left instanceof AST_UnaryPrefix && self.left.operator == \"-\"\n                        && self.left.expression instanceof AST_Number && self.left.expression.value == 1;\n            }\n        }\n\n        function reversible() {\n            return self.left.is_constant()\n                || self.right.is_constant()\n                || !self.left.has_side_effects(compressor)\n                    && !self.right.has_side_effects(compressor);\n        }\n\n        function reverse(op) {\n            if (reversible()) {\n                if (op) self.operator = op;\n                var tmp = self.left;\n                self.left = self.right;\n                self.right = tmp;\n            }\n        }\n    });\n\n    OPT(AST_SymbolExport, function(self) {\n        return self;\n    });\n\n    function recursive_ref(compressor, def, fn) {\n        var level = 0, node = compressor.self();\n        do {\n            if (node === fn) return node;\n            if (is_lambda(node) && node.name && node.name.definition() === def) return node;\n        } while (node = compressor.parent(level++));\n    }\n\n    function same_scope(def) {\n        var scope = def.scope.resolve();\n        return all(def.references, function(ref) {\n            return scope === ref.scope.resolve();\n        });\n    }\n\n    OPT(AST_SymbolRef, function(self, compressor) {\n        if (!compressor.option(\"ie\")\n            && is_undeclared_ref(self)\n            // testing against `self.scope.uses_with` is an optimization\n            && !(self.scope.resolve().uses_with && compressor.find_parent(AST_With))) {\n            switch (self.name) {\n              case \"undefined\":\n                return make_node(AST_Undefined, self).optimize(compressor);\n              case \"NaN\":\n                return make_node(AST_NaN, self).optimize(compressor);\n              case \"Infinity\":\n                return make_node(AST_Infinity, self).optimize(compressor);\n            }\n        }\n        var parent = compressor.parent();\n        if (compressor.option(\"reduce_vars\") && is_lhs(compressor.self(), parent) !== compressor.self()) {\n            var def = self.definition();\n            var fixed = self.fixed_value();\n            var single_use = def.single_use && !(parent instanceof AST_Call && parent.is_expr_pure(compressor));\n            if (single_use) {\n                if (is_lambda(fixed)) {\n                    if ((def.scope !== self.scope.resolve(true) || def.in_loop)\n                        && (!compressor.option(\"reduce_funcs\") || def.escaped.depth == 1 || fixed.inlined)) {\n                        single_use = false;\n                    } else if (def.redefined()) {\n                        single_use = false;\n                    } else if (recursive_ref(compressor, def, fixed)) {\n                        single_use = false;\n                    } else if (fixed.name && fixed.name.definition() !== def) {\n                        single_use = false;\n                    } else if (fixed.parent_scope !== self.scope || is_funarg(def)) {\n                        if (!safe_from_strict_mode(fixed, compressor)) {\n                            single_use = false;\n                        } else if ((single_use = fixed.is_constant_expression(self.scope)) == \"f\") {\n                            var scope = self.scope;\n                            do {\n                                if (scope instanceof AST_LambdaDefinition || scope instanceof AST_LambdaExpression) {\n                                    scope.inlined = true;\n                                }\n                            } while (scope = scope.parent_scope);\n                        }\n                    } else if (fixed.name && (fixed.name.name == \"await\" && is_async(fixed)\n                        || fixed.name.name == \"yield\" && is_generator(fixed))) {\n                        single_use = false;\n                    } else if (fixed.has_side_effects(compressor)) {\n                        single_use = false;\n                    } else if (fixed instanceof AST_Class\n                        && (compressor.option(\"ie\") || !fixed.is_constant_expression(self.scope))) {\n                        single_use = false;\n                    }\n                    if (single_use) fixed.parent_scope = self.scope;\n                } else if (!fixed\n                    || def.recursive_refs > 0\n                    || !fixed.is_constant_expression()\n                    || fixed.drop_side_effect_free(compressor)) {\n                    single_use = false;\n                }\n            }\n            if (single_use) {\n                def.single_use = false;\n                fixed._squeezed = true;\n                fixed.single_use = true;\n                if (fixed instanceof AST_DefClass) fixed = to_class_expr(fixed);\n                if (fixed instanceof AST_LambdaDefinition) fixed = to_func_expr(fixed);\n                if (is_lambda(fixed)) {\n                    var scopes = [];\n                    var scope = self.scope;\n                    do {\n                        scopes.push(scope);\n                        if (scope === def.scope) break;\n                    } while (scope = scope.parent_scope);\n                    fixed.enclosed.forEach(function(def) {\n                        if (fixed.variables.has(def.name)) return;\n                        for (var i = 0; i < scopes.length; i++) {\n                            var scope = scopes[i];\n                            if (!push_uniq(scope.enclosed, def)) return;\n                            scope.var_names().set(def.name, true);\n                        }\n                    });\n                }\n                var value;\n                if (def.recursive_refs > 0) {\n                    value = fixed.clone(true);\n                    var defun_def = value.name.definition();\n                    var lambda_def = value.variables.get(value.name.name);\n                    var name = lambda_def && lambda_def.orig[0];\n                    var def_fn_name, symbol_type;\n                    if (value instanceof AST_Class) {\n                        def_fn_name = \"def_function\";\n                        symbol_type = AST_SymbolClass;\n                    } else {\n                        def_fn_name = \"def_variable\";\n                        symbol_type = AST_SymbolLambda;\n                    }\n                    if (!(name instanceof symbol_type)) {\n                        name = make_node(symbol_type, value.name);\n                        name.scope = value;\n                        value.name = name;\n                        lambda_def = value[def_fn_name](name);\n                        lambda_def.recursive_refs = def.recursive_refs;\n                    }\n                    value.walk(new TreeWalker(function(node) {\n                        if (node instanceof AST_SymbolDeclaration) {\n                            if (node !== name) {\n                                var def = node.definition();\n                                def.orig.push(node);\n                                def.eliminated++;\n                            }\n                            return;\n                        }\n                        if (!(node instanceof AST_SymbolRef)) return;\n                        var def = node.definition();\n                        if (def === defun_def) {\n                            node.thedef = def = lambda_def;\n                        } else {\n                            def.single_use = false;\n                            var fn = node.fixed_value();\n                            if (is_lambda(fn)\n                                && fn.name\n                                && fn.name.definition() === def\n                                && def.scope === fn.name.scope\n                                && fixed.variables.get(fn.name.name) === def) {\n                                fn.name = fn.name.clone();\n                                node.thedef = def = value.variables.get(fn.name.name) || value[def_fn_name](fn.name);\n                            }\n                        }\n                        def.references.push(node);\n                    }));\n                } else {\n                    if (fixed instanceof AST_Scope) {\n                        compressor.push(fixed);\n                        value = fixed.optimize(compressor);\n                        compressor.pop();\n                    } else {\n                        value = fixed.optimize(compressor);\n                    }\n                    value = value.transform(new TreeTransformer(function(node, descend) {\n                        if (node instanceof AST_Scope) return node;\n                        node = node.clone();\n                        descend(node, this);\n                        return node;\n                    }));\n                }\n                def.replaced++;\n                return value;\n            }\n            var state;\n            if (fixed && (state = self.fixed || def.fixed).should_replace !== false) {\n                var ev, init;\n                if (fixed instanceof AST_This) {\n                    if (!is_funarg(def) && same_scope(def) && !cross_class(def)) init = fixed;\n                } else if ((ev = fixed.evaluate(compressor, true)) !== fixed\n                    && typeof ev != \"function\"\n                    && (ev === null\n                        || typeof ev != \"object\"\n                        || compressor.option(\"unsafe_regexp\")\n                            && ev instanceof RegExp && !def.cross_loop && same_scope(def))) {\n                    init = make_node_from_constant(ev, fixed);\n                }\n                if (init) {\n                    if (state.should_replace === undefined) {\n                        var value_length = init.optimize(compressor).print_to_string().length;\n                        if (!has_symbol_ref(fixed)) {\n                            value_length = Math.min(value_length, fixed.print_to_string().length);\n                        }\n                        var name_length = def.name.length;\n                        if (compressor.option(\"unused\") && !compressor.exposed(def)) {\n                            var refs = def.references.length - def.replaced - def.assignments;\n                            refs = Math.min(refs, def.references.filter(function(ref) {\n                                return ref.fixed === state;\n                            }).length);\n                            name_length += (name_length + 2 + value_length) / Math.max(1, refs);\n                        }\n                        state.should_replace = value_length - Math.floor(name_length) < compressor.eval_threshold;\n                    }\n                    if (state.should_replace) {\n                        var value;\n                        if (has_symbol_ref(fixed)) {\n                            value = init.optimize(compressor);\n                            if (value === init) value = value.clone(true);\n                        } else {\n                            value = best_of_expression(init.optimize(compressor), fixed);\n                            if (value === init || value === fixed) value = value.clone(true);\n                        }\n                        def.replaced++;\n                        return value;\n                    }\n                }\n            }\n        }\n        return self;\n\n        function cross_class(def) {\n            var scope = self.scope;\n            while (scope !== def.scope) {\n                if (scope instanceof AST_Class) return true;\n                scope = scope.parent_scope;\n            }\n        }\n\n        function has_symbol_ref(value) {\n            var found;\n            value.walk(new TreeWalker(function(node) {\n                if (node instanceof AST_SymbolRef) found = true;\n                if (found) return true;\n            }));\n            return found;\n        }\n    });\n\n    function is_raw_tag(compressor, tag) {\n        return compressor.option(\"unsafe\")\n            && tag instanceof AST_Dot\n            && tag.property == \"raw\"\n            && is_undeclared_ref(tag.expression)\n            && tag.expression.name == \"String\";\n    }\n\n    function decode_template(str) {\n        var malformed = false;\n        str = str.replace(/\\\\(u\\{[^{}]*\\}?|u[\\s\\S]{0,4}|x[\\s\\S]{0,2}|[0-9]+|[\\s\\S])/g, function(match, seq) {\n            var ch = decode_escape_sequence(seq);\n            if (typeof ch == \"string\") return ch;\n            malformed = true;\n        });\n        if (!malformed) return str;\n    }\n\n    OPT(AST_Template, function(self, compressor) {\n        if (!compressor.option(\"templates\")) return self;\n        var tag = self.tag;\n        if (!tag || is_raw_tag(compressor, tag)) {\n            var exprs = [];\n            var strs = [];\n            for (var i = 0, status; i < self.strings.length; i++) {\n                var str = self.strings[i];\n                if (!tag) {\n                    var trimmed = decode_template(str);\n                    if (trimmed) str = escape_literal(trimmed);\n                }\n                if (i > 0) {\n                    var node = self.expressions[i - 1];\n                    var value = should_join(node);\n                    if (value) {\n                        var prev = strs[strs.length - 1];\n                        var joined = prev + value + str;\n                        var decoded;\n                        if (tag || typeof (decoded = decode_template(joined)) == status) {\n                            strs[strs.length - 1] = decoded ? escape_literal(decoded) : joined;\n                            continue;\n                        }\n                    }\n                    exprs.push(node);\n                }\n                strs.push(str);\n                if (!tag) status = typeof trimmed;\n            }\n            if (!tag && strs.length > 1) {\n                if (strs[strs.length - 1] == \"\") return make_node(AST_Binary, self, {\n                    operator: \"+\",\n                    left: make_node(AST_Template, self, {\n                        expressions: exprs.slice(0, -1),\n                        strings: strs.slice(0, -1),\n                    }).transform(compressor),\n                    right: exprs[exprs.length - 1],\n                }).optimize(compressor);\n                if (strs[0] == \"\") {\n                    var left = make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: make_node(AST_String, self, { value: \"\" }),\n                        right: exprs[0],\n                    });\n                    for (var i = 1; strs[i] == \"\" && i < exprs.length; i++) {\n                        left = make_node(AST_Binary, self, {\n                            operator: \"+\",\n                            left: left,\n                            right: exprs[i],\n                        });\n                    }\n                    return best_of(compressor, self, make_node(AST_Binary, self, {\n                        operator: \"+\",\n                        left: left.transform(compressor),\n                        right: make_node(AST_Template, self, {\n                            expressions: exprs.slice(i),\n                            strings: strs.slice(i),\n                        }).transform(compressor),\n                    }).optimize(compressor));\n                }\n            }\n            self.expressions = exprs;\n            self.strings = strs;\n        }\n        return try_evaluate(compressor, self);\n\n        function escape_literal(str) {\n            return str.replace(/\\r|\\\\|`|\\${/g, function(s) {\n                return \"\\\\\" + (s == \"\\r\" ? \"r\" : s);\n            });\n        }\n\n        function should_join(node) {\n            var ev = node.evaluate(compressor);\n            if (ev === node) return;\n            if (tag && /\\r|\\\\|`/.test(ev)) return;\n            ev = escape_literal(\"\" + ev);\n            if (ev.length > node.print_to_string().length + \"${}\".length) return;\n            return ev;\n        }\n    });\n\n    function is_atomic(lhs, self) {\n        return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;\n    }\n\n    OPT(AST_Undefined, function(self, compressor) {\n        if (compressor.option(\"unsafe_undefined\")) {\n            var undef = find_scope(compressor).find_variable(\"undefined\");\n            if (undef) {\n                var ref = make_node(AST_SymbolRef, self, {\n                    name: \"undefined\",\n                    scope: undef.scope,\n                    thedef: undef,\n                });\n                ref.is_undefined = true;\n                return ref;\n            }\n        }\n        var lhs = is_lhs(compressor.self(), compressor.parent());\n        if (lhs && is_atomic(lhs, self)) return self;\n        return make_node(AST_UnaryPrefix, self, {\n            operator: \"void\",\n            expression: make_node(AST_Number, self, { value: 0 }),\n        });\n    });\n\n    OPT(AST_Infinity, function(self, compressor) {\n        var lhs = is_lhs(compressor.self(), compressor.parent());\n        if (lhs && is_atomic(lhs, self)) return self;\n        if (compressor.option(\"keep_infinity\") && !lhs && !find_scope(compressor).find_variable(\"Infinity\")) {\n            return self;\n        }\n        return make_node(AST_Binary, self, {\n            operator: \"/\",\n            left: make_node(AST_Number, self, { value: 1 }),\n            right: make_node(AST_Number, self, { value: 0 }),\n        });\n    });\n\n    OPT(AST_NaN, function(self, compressor) {\n        var lhs = is_lhs(compressor.self(), compressor.parent());\n        if (lhs && is_atomic(lhs, self)) return self;\n        if (!lhs && !find_scope(compressor).find_variable(\"NaN\")) return self;\n        return make_node(AST_Binary, self, {\n            operator: \"/\",\n            left: make_node(AST_Number, self, { value: 0 }),\n            right: make_node(AST_Number, self, { value: 0 }),\n        });\n    });\n\n    function is_reachable(self, defs) {\n        var reachable = false;\n        var find_ref = new TreeWalker(function(node) {\n            if (reachable) return true;\n            if (node instanceof AST_SymbolRef && member(node.definition(), defs)) return reachable = true;\n        });\n        var scan_scope = new TreeWalker(function(node) {\n            if (reachable) return true;\n            if (node instanceof AST_Lambda && node !== self) {\n                if (!(node.name || is_async(node) || is_generator(node))) {\n                    var parent = scan_scope.parent();\n                    if (parent instanceof AST_Call && parent.expression === node) return;\n                }\n                node.walk(find_ref);\n                return true;\n            }\n        });\n        self.walk(scan_scope);\n        return reachable;\n    }\n\n    var ASSIGN_OPS = makePredicate(\"+ - * / % >> << >>> | ^ &\");\n    var ASSIGN_OPS_COMMUTATIVE = makePredicate(\"* | ^ &\");\n    OPT(AST_Assign, function(self, compressor) {\n        if (compressor.option(\"dead_code\")) {\n            if (self.left instanceof AST_PropAccess) {\n                if (self.operator == \"=\") {\n                    var exp = self.left.expression;\n                    if (self.left.equals(self.right)) {\n                        var defined = exp.defined;\n                        exp.defined = false;\n                        var drop_lhs = !self.left.has_side_effects(compressor);\n                        exp.defined = defined;\n                        if (drop_lhs) return self.right;\n                    }\n                    if (exp instanceof AST_Lambda\n                        || !compressor.has_directive(\"use strict\")\n                            && exp instanceof AST_Constant\n                            && !exp.may_throw_on_access(compressor)) {\n                        var value = self.left instanceof AST_Dot ? self.right : make_sequence(self, [\n                            self.left.property,\n                            self.right,\n                        ]);\n                        return maintain_this_binding(compressor.parent(), self, value).optimize(compressor);\n                    }\n                }\n            } else if (self.left instanceof AST_SymbolRef && can_drop_symbol(self.left, compressor)) {\n                var parent;\n                if (self.operator == \"=\" && self.left.equals(self.right)\n                    && !((parent = compressor.parent()) instanceof AST_UnaryPrefix && parent.operator == \"delete\")) {\n                    return self.right;\n                }\n                if (self.left.is_immutable()) return strip_assignment();\n                var def = self.left.definition();\n                var scope = def.scope.resolve();\n                var local = scope === compressor.find_parent(AST_Lambda);\n                var level = 0, node;\n                parent = compressor.self();\n                if (!(scope.uses_arguments && is_funarg(def)) || compressor.has_directive(\"use strict\")) do {\n                    node = parent;\n                    parent = compressor.parent(level++);\n                    if (parent instanceof AST_Assign) {\n                        if (parent.right === node\n                            && parent.left instanceof AST_SymbolRef\n                            && parent.left.definition() === def) {\n                            if (in_try(level, parent, !local)) break;\n                            return strip_assignment(def);\n                        }\n                        if (parent.left.match_symbol(function(node) {\n                            if (node instanceof AST_PropAccess) return true;\n                        })) break;\n                        continue;\n                    }\n                    if (parent instanceof AST_Exit) {\n                        if (!local) break;\n                        if (in_try(level, parent)) break;\n                        if (is_reachable(scope, [ def ])) break;\n                        return strip_assignment(def);\n                    }\n                    if (parent instanceof AST_SimpleStatement) {\n                        if (!local) break;\n                        if (is_reachable(scope, [ def ])) break;\n                        var stat;\n                        do {\n                            stat = parent;\n                            parent = compressor.parent(level++);\n                            if (parent === scope && is_last_statement(parent.body, stat)) return strip_assignment(def);\n                        } while (is_tail_block(stat, parent));\n                        break;\n                    }\n                    if (parent instanceof AST_VarDef) {\n                        if (!(parent.name instanceof AST_SymbolDeclaration)) continue;\n                        if (parent.name.definition() !== def) continue;\n                        if (in_try(level, parent)) break;\n                        return strip_assignment(def);\n                    }\n                } while (is_tail(node, parent));\n            }\n        }\n        if (compressor.option(\"sequences\")) {\n            var seq = self.lift_sequences(compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        if (compressor.option(\"assignments\")) {\n            if (self.operator == \"=\" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {\n                // x = expr1 OP expr2\n                if (self.right.left instanceof AST_SymbolRef\n                    && self.right.left.name == self.left.name\n                    && ASSIGN_OPS[self.right.operator]) {\n                    // x = x - 2 ---> x -= 2\n                    return make_compound(self.right.right);\n                }\n                if (self.right.right instanceof AST_SymbolRef\n                    && self.right.right.name == self.left.name\n                    && ASSIGN_OPS_COMMUTATIVE[self.right.operator]\n                    && !self.right.left.has_side_effects(compressor)) {\n                    // x = 2 & x ---> x &= 2\n                    return make_compound(self.right.left);\n                }\n            }\n            if ((self.operator == \"-=\" || self.operator == \"+=\"\n                    && (self.left.is_boolean(compressor) || self.left.is_number(compressor)))\n                && self.right instanceof AST_Number\n                && self.right.value == 1) {\n                var op = self.operator.slice(0, -1);\n                return make_node(AST_UnaryPrefix, self, {\n                    operator: op + op,\n                    expression: self.left,\n                });\n            }\n        }\n        return try_evaluate(compressor, self);\n\n        function is_tail(node, parent) {\n            if (parent instanceof AST_Binary) switch (node) {\n              case parent.left:\n                return parent.right.is_constant_expression(scope);\n              case parent.right:\n                return true;\n              default:\n                return false;\n            }\n            if (parent instanceof AST_Conditional) switch (node) {\n              case parent.condition:\n                return parent.consequent.is_constant_expression(scope)\n                    && parent.alternative.is_constant_expression(scope);\n              case parent.consequent:\n              case parent.alternative:\n                return true;\n              default:\n                return false;\n            }\n            if (parent instanceof AST_Sequence) {\n                var exprs = parent.expressions;\n                var stop = exprs.indexOf(node);\n                if (stop < 0) return false;\n                for (var i = exprs.length; --i > stop;) {\n                    if (!exprs[i].is_constant_expression(scope)) return false;\n                }\n                return true;\n            }\n            return parent instanceof AST_UnaryPrefix;\n        }\n\n        function is_tail_block(stat, parent) {\n            if (parent instanceof AST_BlockStatement) return is_last_statement(parent.body, stat);\n            if (parent instanceof AST_Catch) return is_last_statement(parent.body, stat);\n            if (parent instanceof AST_Finally) return is_last_statement(parent.body, stat);\n            if (parent instanceof AST_If) return parent.body === stat || parent.alternative === stat;\n            if (parent instanceof AST_Try) return parent.bfinally ? parent.bfinally === stat : parent.bcatch === stat;\n        }\n\n        function in_try(level, node, sync) {\n            var right = self.right;\n            self.right = make_node(AST_Null, right);\n            var may_throw = node.may_throw(compressor);\n            self.right = right;\n            return find_try(compressor, level, node, scope, may_throw, sync);\n        }\n\n        function make_compound(rhs) {\n            var fixed = self.left.fixed;\n            if (fixed) fixed.to_binary = replace_ref(function(node) {\n                return node.left;\n            }, fixed);\n            return make_node(AST_Assign, self, {\n                operator: self.right.operator + \"=\",\n                left: self.left,\n                right: rhs,\n            });\n        }\n\n        function strip_assignment(def) {\n            if (def) def.fixed = false;\n            return (self.operator != \"=\" ? make_node(AST_Binary, self, {\n                operator: self.operator.slice(0, -1),\n                left: self.left,\n                right: self.right,\n            }) : maintain_this_binding(compressor.parent(), self, self.right)).optimize(compressor);\n        }\n    });\n\n    OPT(AST_Conditional, function(self, compressor) {\n        if (compressor.option(\"sequences\") && self.condition instanceof AST_Sequence) {\n            var expressions = self.condition.expressions.slice();\n            var node = self.clone();\n            node.condition = expressions.pop();\n            expressions.push(node);\n            return make_sequence(self, expressions).optimize(compressor);\n        }\n        if (!compressor.option(\"conditionals\")) return self;\n        var condition = self.condition;\n        if (compressor.option(\"booleans\") && !condition.has_side_effects(compressor)) {\n            mark_duplicate_condition(compressor, condition);\n        }\n        condition = fuzzy_eval(compressor, condition);\n        if (!condition) {\n            AST_Node.warn(\"Condition always false [{start}]\", self);\n            return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor);\n        } else if (!(condition instanceof AST_Node)) {\n            AST_Node.warn(\"Condition always true [{start}]\", self);\n            return make_sequence(self, [ self.condition, self.consequent ]).optimize(compressor);\n        }\n        var first = first_in_statement(compressor);\n        var negated = condition.negate(compressor, first);\n        if ((first ? best_of_statement : best_of_expression)(condition, negated) === negated) {\n            self = make_node(AST_Conditional, self, {\n                condition: negated,\n                consequent: self.alternative,\n                alternative: self.consequent,\n            });\n            negated = condition;\n            condition = self.condition;\n        }\n        var consequent = self.consequent;\n        var alternative = self.alternative;\n        var cond_lhs = extract_lhs(condition, compressor);\n        if (repeatable(compressor, cond_lhs)) {\n            // x ? x : y ---> x || y\n            if (cond_lhs.equals(consequent)) return make_node(AST_Binary, self, {\n                operator: \"||\",\n                left: condition,\n                right: alternative,\n            }).optimize(compressor);\n            // x ? y : x ---> x && y\n            if (cond_lhs.equals(alternative)) return make_node(AST_Binary, self, {\n                operator: \"&&\",\n                left: condition,\n                right: consequent,\n            }).optimize(compressor);\n        }\n        // if (foo) exp = something; else exp = something_else;\n        //                   |\n        //                   v\n        // exp = foo ? something : something_else;\n        var seq_tail = consequent.tail_node();\n        if (seq_tail instanceof AST_Assign) {\n            var is_eq = seq_tail.operator == \"=\";\n            var alt_tail = is_eq ? alternative.tail_node() : alternative;\n            if ((is_eq || consequent === seq_tail)\n                && alt_tail instanceof AST_Assign\n                && seq_tail.operator == alt_tail.operator\n                && seq_tail.left.equals(alt_tail.left)\n                && (is_eq && seq_tail.left instanceof AST_SymbolRef\n                    || !condition.has_side_effects(compressor)\n                        && can_shift_lhs_of_tail(consequent)\n                        && can_shift_lhs_of_tail(alternative))) {\n                return make_node(AST_Assign, self, {\n                    operator: seq_tail.operator,\n                    left: seq_tail.left,\n                    right: make_node(AST_Conditional, self, {\n                        condition: condition,\n                        consequent: pop_lhs(consequent),\n                        alternative: pop_lhs(alternative),\n                    }),\n                });\n            }\n        }\n        var alt_tail = alternative.tail_node();\n        // x ? y : y ---> x, y\n        // x ? (a, c) : (b, c) ---> x ? a : b, c\n        if (seq_tail.equals(alt_tail)) return make_sequence(self, consequent.equals(alternative) ? [\n            condition,\n            consequent,\n        ] : [\n            make_node(AST_Conditional, self, {\n                condition: condition,\n                consequent: pop_seq(consequent),\n                alternative: pop_seq(alternative),\n            }),\n            alt_tail,\n        ]).optimize(compressor);\n        // x ? y.p : z.p ---> (x ? y : z).p\n        // x ? y(a) : z(a) ---> (x ? y : z)(a)\n        // x ? y.f(a) : z.f(a) ---> (x ? y : z).f(a)\n        var combined = combine_tail(consequent, alternative, true);\n        if (combined) return combined;\n        // x ? y(a) : y(b) ---> y(x ? a : b)\n        var arg_index;\n        if (consequent instanceof AST_Call\n            && alternative.TYPE == consequent.TYPE\n            && (arg_index = arg_diff(consequent, alternative)) >= 0\n            && consequent.expression.equals(alternative.expression)\n            && !condition.has_side_effects(compressor)\n            && !consequent.expression.has_side_effects(compressor)) {\n            var node = consequent.clone();\n            var arg = consequent.args[arg_index];\n            node.args[arg_index] = arg instanceof AST_Spread ? make_node(AST_Spread, self, {\n                expression: make_node(AST_Conditional, self, {\n                    condition: condition,\n                    consequent: arg.expression,\n                    alternative: alternative.args[arg_index].expression,\n                }),\n            }) : make_node(AST_Conditional, self, {\n                condition: condition,\n                consequent: arg,\n                alternative: alternative.args[arg_index],\n            });\n            return node;\n        }\n        // x ? (y ? a : b) : b ---> x && y ? a : b\n        if (seq_tail instanceof AST_Conditional\n            && seq_tail.alternative.equals(alternative)) {\n            return make_node(AST_Conditional, self, {\n                condition: make_node(AST_Binary, self, {\n                    left: condition,\n                    operator: \"&&\",\n                    right: fuse(consequent, seq_tail, \"condition\"),\n                }),\n                consequent: seq_tail.consequent,\n                alternative: merge_expression(seq_tail.alternative, alternative),\n            });\n        }\n        // x ? (y ? a : b) : a ---> !x || y ? a : b\n        if (seq_tail instanceof AST_Conditional\n            && seq_tail.consequent.equals(alternative)) {\n            return make_node(AST_Conditional, self, {\n                condition: make_node(AST_Binary, self, {\n                    left: negated,\n                    operator: \"||\",\n                    right: fuse(consequent, seq_tail, \"condition\"),\n                }),\n                consequent: merge_expression(seq_tail.consequent, alternative),\n                alternative: seq_tail.alternative,\n            });\n        }\n        // x ? a : (y ? a : b) ---> x || y ? a : b\n        if (alt_tail instanceof AST_Conditional\n            && consequent.equals(alt_tail.consequent)) {\n            return make_node(AST_Conditional, self, {\n                condition: make_node(AST_Binary, self, {\n                    left: condition,\n                    operator: \"||\",\n                    right: fuse(alternative, alt_tail, \"condition\"),\n                }),\n                consequent: merge_expression(consequent, alt_tail.consequent),\n                alternative: alt_tail.alternative,\n            });\n        }\n        // x ? b : (y ? a : b) ---> !x && y ? a : b\n        if (alt_tail instanceof AST_Conditional\n            && consequent.equals(alt_tail.alternative)) {\n            return make_node(AST_Conditional, self, {\n                condition: make_node(AST_Binary, self, {\n                    left: negated,\n                    operator: \"&&\",\n                    right: fuse(alternative, alt_tail, \"condition\"),\n                }),\n                consequent: alt_tail.consequent,\n                alternative: merge_expression(consequent, alt_tail.alternative),\n            });\n        }\n        // x ? y && a : a ---> (!x || y) && a\n        if (seq_tail instanceof AST_Binary\n            && seq_tail.operator == \"&&\"\n            && seq_tail.right.equals(alternative)) {\n            return make_node(AST_Binary, self, {\n                operator: \"&&\",\n                left: make_node(AST_Binary, self, {\n                    operator: \"||\",\n                    left: negated,\n                    right: fuse(consequent, seq_tail, \"left\"),\n                }),\n                right: merge_expression(seq_tail.right, alternative),\n            }).optimize(compressor);\n        }\n        // x ? y || a : a ---> x && y || a\n        if (seq_tail instanceof AST_Binary\n            && seq_tail.operator == \"||\"\n            && seq_tail.right.equals(alternative)) {\n            return make_node(AST_Binary, self, {\n                operator: \"||\",\n                left: make_node(AST_Binary, self, {\n                    operator: \"&&\",\n                    left: condition,\n                    right: fuse(consequent, seq_tail, \"left\"),\n                }),\n                right: merge_expression(seq_tail.right, alternative),\n            }).optimize(compressor);\n        }\n        // x ? a : y && a ---> (x || y) && a\n        if (alt_tail instanceof AST_Binary\n            && alt_tail.operator == \"&&\"\n            && alt_tail.right.equals(consequent)) {\n            return make_node(AST_Binary, self, {\n                operator: \"&&\",\n                left: make_node(AST_Binary, self, {\n                    operator: \"||\",\n                    left: condition,\n                    right: fuse(alternative, alt_tail, \"left\"),\n                }),\n                right: merge_expression(consequent, alt_tail.right),\n            }).optimize(compressor);\n        }\n        // x ? a : y || a ---> !x && y || a\n        if (alt_tail instanceof AST_Binary\n            && alt_tail.operator == \"||\"\n            && alt_tail.right.equals(consequent)) {\n            return make_node(AST_Binary, self, {\n                operator: \"||\",\n                left: make_node(AST_Binary, self, {\n                    operator: \"&&\",\n                    left: negated,\n                    right: fuse(alternative, alt_tail, \"left\"),\n                }),\n                right: merge_expression(consequent, alt_tail.right),\n            }).optimize(compressor);\n        }\n        var in_bool = compressor.option(\"booleans\") && compressor.in_boolean_context();\n        if (is_true(consequent)) {\n            // c ? true : false ---> !!c\n            if (is_false(alternative)) return booleanize(condition);\n            // c ? true : x ---> !!c || x\n            return make_node(AST_Binary, self, {\n                operator: \"||\",\n                left: booleanize(condition),\n                right: alternative,\n            }).optimize(compressor);\n        }\n        if (is_false(consequent)) {\n            // c ? false : true ---> !c\n            if (is_true(alternative)) return booleanize(condition.negate(compressor));\n            // c ? false : x ---> !c && x\n            return make_node(AST_Binary, self, {\n                operator: \"&&\",\n                left: booleanize(condition.negate(compressor)),\n                right: alternative,\n            }).optimize(compressor);\n        }\n        // c ? x : true ---> !c || x\n        if (is_true(alternative)) return make_node(AST_Binary, self, {\n            operator: \"||\",\n            left: booleanize(condition.negate(compressor)),\n            right: consequent,\n        }).optimize(compressor);\n        // c ? x : false ---> !!c && x\n        if (is_false(alternative)) return make_node(AST_Binary, self, {\n            operator: \"&&\",\n            left: booleanize(condition),\n            right: consequent,\n        }).optimize(compressor);\n        if (compressor.option(\"typeofs\")) mark_locally_defined(condition, consequent, alternative);\n        return self;\n\n        function booleanize(node) {\n            if (node.is_boolean(compressor)) return node;\n            // !!expression\n            return make_node(AST_UnaryPrefix, node, {\n                operator: \"!\",\n                expression: node.negate(compressor),\n            });\n        }\n\n        // AST_True or !0\n        function is_true(node) {\n            return node instanceof AST_True\n                || in_bool\n                    && node instanceof AST_Constant\n                    && node.value\n                || (node instanceof AST_UnaryPrefix\n                    && node.operator == \"!\"\n                    && node.expression instanceof AST_Constant\n                    && !node.expression.value);\n        }\n        // AST_False or !1 or void 0\n        function is_false(node) {\n            return node instanceof AST_False\n                || in_bool\n                    && (node instanceof AST_Constant\n                            && !node.value\n                        || node instanceof AST_UnaryPrefix\n                            && node.operator == \"void\"\n                            && !node.expression.has_side_effects(compressor))\n                || (node instanceof AST_UnaryPrefix\n                    && node.operator == \"!\"\n                    && node.expression instanceof AST_Constant\n                    && node.expression.value);\n        }\n\n        function arg_diff(consequent, alternative) {\n            var a = consequent.args;\n            var b = alternative.args;\n            var len = a.length;\n            if (len != b.length) return -2;\n            for (var i = 0; i < len; i++) {\n                if (!a[i].equals(b[i])) {\n                    if (a[i] instanceof AST_Spread !== b[i] instanceof AST_Spread) return -3;\n                    for (var j = i + 1; j < len; j++) {\n                        if (!a[j].equals(b[j])) return -2;\n                    }\n                    return i;\n                }\n            }\n            return -1;\n        }\n\n        function fuse(node, tail, prop) {\n            if (node === tail) return tail[prop];\n            var exprs = node.expressions.slice(0, -1);\n            exprs.push(tail[prop]);\n            return make_sequence(node, exprs);\n        }\n\n        function is_tail_equivalent(consequent, alternative) {\n            if (consequent.TYPE != alternative.TYPE) return;\n            if (consequent.optional != alternative.optional) return;\n            if (consequent instanceof AST_Call) {\n                if (arg_diff(consequent, alternative) != -1) return;\n                return consequent.TYPE != \"Call\"\n                    || !(consequent.expression instanceof AST_PropAccess\n                        || alternative.expression instanceof AST_PropAccess)\n                    || is_tail_equivalent(consequent.expression, alternative.expression);\n            }\n            if (!(consequent instanceof AST_PropAccess)) return;\n            var p = consequent.property;\n            var q = alternative.property;\n            return (p instanceof AST_Node ? p.equals(q) : p == q)\n                && !(consequent.expression instanceof AST_Super || alternative.expression instanceof AST_Super);\n        }\n\n        function combine_tail(consequent, alternative, top) {\n            var seq_tail = consequent.tail_node();\n            var alt_tail = alternative.tail_node();\n            if (!is_tail_equivalent(seq_tail, alt_tail)) return !top && make_node(AST_Conditional, self, {\n                condition: condition,\n                consequent: consequent,\n                alternative: alternative,\n            });\n            var node = seq_tail.clone();\n            var seq_expr = fuse(consequent, seq_tail, \"expression\");\n            var alt_expr = fuse(alternative, alt_tail, \"expression\");\n            var combined = combine_tail(seq_expr, alt_expr);\n            if (seq_tail.expression instanceof AST_Sequence) {\n                combined = maintain_this_binding(seq_tail, seq_tail.expression, combined);\n            }\n            node.expression = combined;\n            return node;\n        }\n\n        function can_shift_lhs_of_tail(node) {\n            return node === node.tail_node() || all(node.expressions.slice(0, -1), function(expr) {\n                return !expr.has_side_effects(compressor);\n            });\n        }\n\n        function pop_lhs(node) {\n            if (!(node instanceof AST_Sequence)) return node.right;\n            var exprs = node.expressions.slice();\n            exprs.push(exprs.pop().right);\n            return make_sequence(node, exprs);\n        }\n\n        function pop_seq(node) {\n            if (!(node instanceof AST_Sequence)) return make_node(AST_Number, node, { value: 0 });\n            return make_sequence(node, node.expressions.slice(0, -1));\n        }\n    });\n\n    OPT(AST_Boolean, function(self, compressor) {\n        if (!compressor.option(\"booleans\")) return self;\n        if (compressor.in_boolean_context()) return make_node(AST_Number, self, { value: +self.value });\n        var p = compressor.parent();\n        if (p instanceof AST_Binary && (p.operator == \"==\" || p.operator == \"!=\")) {\n            AST_Node.warn(\"Non-strict equality against boolean: {operator} {value} [{start}]\", {\n                operator: p.operator,\n                value: self.value,\n                start: p.start,\n            });\n            return make_node(AST_Number, self, { value: +self.value });\n        }\n        return make_node(AST_UnaryPrefix, self, {\n            operator: \"!\",\n            expression: make_node(AST_Number, self, { value: 1 - self.value }),\n        });\n    });\n\n    OPT(AST_Spread, function(self, compressor) {\n        var exp = self.expression;\n        if (compressor.option(\"spreads\") && exp instanceof AST_Array && !(compressor.parent() instanceof AST_Object)) {\n            return List.splice(exp.elements.map(function(node) {\n                return node instanceof AST_Hole ? make_node(AST_Undefined, node).optimize(compressor) : node;\n            }));\n        }\n        return self;\n    });\n\n    function safe_to_flatten(value, compressor) {\n        if (!value) return false;\n        var parent = compressor.parent();\n        if (parent.TYPE != \"Call\") return true;\n        if (parent.expression !== compressor.self()) return true;\n        if (value instanceof AST_SymbolRef) {\n            value = value.fixed_value();\n            if (!value) return false;\n        }\n        return value instanceof AST_Lambda && !value.contains_this();\n    }\n\n    OPT(AST_Sub, function(self, compressor) {\n        var expr = self.expression;\n        var prop = self.property;\n        var terminated = trim_optional_chain(self, compressor);\n        if (terminated) return terminated;\n        if (compressor.option(\"properties\")) {\n            var key = prop.evaluate(compressor);\n            if (key !== prop) {\n                if (typeof key == \"string\") {\n                    if (key == \"undefined\") {\n                        key = undefined;\n                    } else {\n                        var value = parseFloat(key);\n                        if (value.toString() == key) {\n                            key = value;\n                        }\n                    }\n                }\n                prop = self.property = best_of_expression(prop, make_node_from_constant(key, prop).transform(compressor));\n                var property = \"\" + key;\n                if (is_identifier_string(property)\n                    && property.length <= prop.print_to_string().length + 1) {\n                    return make_node(AST_Dot, self, {\n                        optional: self.optional,\n                        expression: expr,\n                        property: property,\n                        quoted: true,\n                    }).optimize(compressor);\n                }\n            }\n        }\n        var parent = compressor.parent();\n        var assigned = is_lhs(compressor.self(), parent);\n        var def, fn, fn_parent, index;\n        if (compressor.option(\"arguments\")\n            && expr instanceof AST_SymbolRef\n            && is_arguments(def = expr.definition())\n            && !expr.in_arg\n            && prop instanceof AST_Number\n            && Math.floor(index = prop.value) == index\n            && (fn = def.scope) === find_lambda()\n            && fn.uses_arguments < (assigned ? 2 : 3)) {\n            if (parent instanceof AST_UnaryPrefix && parent.operator == \"delete\") {\n                if (!def.deleted) def.deleted = [];\n                def.deleted[index] = true;\n            }\n            var argname = fn.argnames[index];\n            if (def.deleted && def.deleted[index]) {\n                argname = null;\n            } else if (argname) {\n                var arg_def;\n                if (!(argname instanceof AST_SymbolFunarg)\n                    || argname.name == \"await\"\n                    || expr.scope.find_variable(argname.name) !== (arg_def = argname.definition())) {\n                    argname = null;\n                } else if (compressor.has_directive(\"use strict\")\n                    || fn.name\n                    || fn.rest\n                    || !(fn_parent instanceof AST_Call\n                        && index < fn_parent.args.length\n                        && all(fn_parent.args.slice(0, index + 1), function(arg) {\n                            return !(arg instanceof AST_Spread);\n                        }))\n                    || !all(fn.argnames, function(argname) {\n                        return argname instanceof AST_SymbolFunarg;\n                    })) {\n                    if (has_reassigned() || arg_def.assignments || arg_def.orig.length > 1) argname = null;\n                }\n            } else if ((assigned || !has_reassigned())\n                && index < fn.argnames.length + 5\n                && compressor.drop_fargs(fn, fn_parent)\n                && !fn.rest) {\n                while (index >= fn.argnames.length) {\n                    argname = fn.make_var(AST_SymbolFunarg, fn, \"argument_\" + fn.argnames.length);\n                    fn.argnames.push(argname);\n                }\n            }\n            if (argname && find_if(function(node) {\n                return node.name === argname.name;\n            }, fn.argnames) === argname) {\n                if (assigned) def.reassigned--;\n                var sym = make_node(AST_SymbolRef, argname);\n                sym.reference();\n                argname.unused = undefined;\n                return sym;\n            }\n        }\n        if (assigned) return self;\n        if (compressor.option(\"sequences\")\n            && parent.TYPE != \"Call\"\n            && !(parent instanceof AST_ForEnumeration && parent.init === self)) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        if (key !== prop) {\n            var sub = self.flatten_object(property, compressor);\n            if (sub) {\n                expr = self.expression = sub.expression;\n                prop = self.property = sub.property;\n            }\n        }\n        var elements;\n        if (compressor.option(\"properties\")\n            && compressor.option(\"side_effects\")\n            && prop instanceof AST_Number\n            && expr instanceof AST_Array\n            && all(elements = expr.elements, function(value) {\n                return !(value instanceof AST_Spread);\n            })) {\n            var index = prop.value;\n            var retValue = elements[index];\n            if (safe_to_flatten(retValue, compressor)) {\n                var is_hole = retValue instanceof AST_Hole;\n                var flatten = !is_hole;\n                var values = [];\n                for (var i = elements.length; --i > index;) {\n                    var value = elements[i].drop_side_effect_free(compressor);\n                    if (value) {\n                        values.unshift(value);\n                        if (flatten && value.has_side_effects(compressor)) flatten = false;\n                    }\n                }\n                if (!flatten) values.unshift(retValue);\n                while (--i >= 0) {\n                    var value = elements[i].drop_side_effect_free(compressor);\n                    if (value) {\n                        values.unshift(value);\n                    } else if (is_hole) {\n                        values.unshift(make_node(AST_Hole, elements[i]));\n                    } else {\n                        index--;\n                    }\n                }\n                if (flatten) {\n                    values.push(retValue);\n                    return make_sequence(self, values).optimize(compressor);\n                }\n                return make_node(AST_Sub, self, {\n                    expression: make_node(AST_Array, expr, { elements: values }),\n                    property: make_node(AST_Number, prop, { value: index }),\n                });\n            }\n        }\n        return try_evaluate(compressor, self);\n\n        function find_lambda() {\n            var i = 0, p;\n            while (p = compressor.parent(i++)) {\n                if (p instanceof AST_Lambda) {\n                    if (p instanceof AST_Accessor) return;\n                    if (is_arrow(p)) continue;\n                    fn_parent = compressor.parent(i);\n                    return p;\n                }\n            }\n        }\n\n        function has_reassigned() {\n            return !compressor.option(\"reduce_vars\") || def.reassigned;\n        }\n    });\n\n    AST_LambdaExpression.DEFMETHOD(\"contains_super\", function() {\n        var result = false;\n        var self = this;\n        self.walk(new TreeWalker(function(node) {\n            if (result) return true;\n            if (node instanceof AST_Super) return result = true;\n            if (node !== self && node instanceof AST_Scope && !is_arrow(node)) return true;\n        }));\n        return result;\n    });\n\n    // contains_this()\n    // returns false only if context bound by the specified scope (or scope\n    // containing the specified expression) is not referenced by `this`\n    (function(def) {\n        // scope of arrow function cannot bind to any context\n        def(AST_Arrow, return_false);\n        def(AST_AsyncArrow, return_false);\n        def(AST_Node, function() {\n            var result = false;\n            var self = this;\n            self.walk(new TreeWalker(function(node) {\n                if (result) return true;\n                if (node instanceof AST_This) return result = true;\n                if (node !== self && node instanceof AST_Scope && !is_arrow(node)) return true;\n            }));\n            return result;\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"contains_this\", func);\n    });\n\n    function can_hoist_property(prop) {\n        return prop instanceof AST_ObjectKeyVal\n            && typeof prop.key == \"string\"\n            && !(prop instanceof AST_ObjectMethod && prop.value.contains_super());\n    }\n\n    AST_PropAccess.DEFMETHOD(\"flatten_object\", function(key, compressor) {\n        if (!compressor.option(\"properties\")) return;\n        if (key === \"__proto__\") return;\n        var self = this;\n        var expr = self.expression;\n        if (!(expr instanceof AST_Object)) return;\n        var props = expr.properties;\n        for (var i = props.length; --i >= 0;) {\n            var prop = props[i];\n            if (prop.key !== key) continue;\n            if (!all(props, can_hoist_property)) return;\n            if (!safe_to_flatten(prop.value, compressor)) return;\n            var call, scope, values = [];\n            for (var j = 0; j < props.length; j++) {\n                var value = props[j].value;\n                if (props[j] instanceof AST_ObjectMethod) {\n                    var arrow = !(value.uses_arguments || is_generator(value) || value.contains_this());\n                    if (arrow) {\n                        if (!scope) scope = compressor.find_parent(AST_Scope);\n                        var avoid = avoid_await_yield(compressor, scope);\n                        value.each_argname(function(argname) {\n                            if (avoid[argname.name]) arrow = false;\n                        });\n                    }\n                    var ctor;\n                    if (arrow) {\n                        ctor = is_async(value) ? AST_AsyncArrow : AST_Arrow;\n                    } else if (i != j\n                        || (call = compressor.parent()) instanceof AST_Call && call.expression === self) {\n                        ctor = value.CTOR;\n                    } else {\n                        return;\n                    }\n                    value = make_node(ctor, value);\n                }\n                values.push(value);\n            }\n            return make_node(AST_Sub, self, {\n                expression: make_node(AST_Array, expr, { elements: values }),\n                property: make_node(AST_Number, self, { value: i }),\n            });\n        }\n    });\n\n    OPT(AST_Dot, function(self, compressor) {\n        if (self.property == \"arguments\" || self.property == \"caller\") {\n            AST_Node.warn(\"Function.prototype.{property} not supported [{start}]\", self);\n        }\n        var parent = compressor.parent();\n        if (is_lhs(compressor.self(), parent)) return self;\n        var terminated = trim_optional_chain(self, compressor);\n        if (terminated) return terminated;\n        if (compressor.option(\"sequences\")\n            && parent.TYPE != \"Call\"\n            && !(parent instanceof AST_ForEnumeration && parent.init === self)) {\n            var seq = lift_sequence_in_expression(self, compressor);\n            if (seq !== self) return seq.optimize(compressor);\n        }\n        if (compressor.option(\"unsafe_proto\")\n            && self.expression instanceof AST_Dot\n            && self.expression.property == \"prototype\") {\n            var exp = self.expression.expression;\n            if (is_undeclared_ref(exp)) switch (exp.name) {\n              case \"Array\":\n                self.expression = make_node(AST_Array, self.expression, { elements: [] });\n                break;\n              case \"Function\":\n                self.expression = make_node(AST_Function, self.expression, {\n                    argnames: [],\n                    body: [],\n                }).init_vars(exp.scope);\n                break;\n              case \"Number\":\n                self.expression = make_node(AST_Number, self.expression, { value: 0 });\n                break;\n              case \"Object\":\n                self.expression = make_node(AST_Object, self.expression, { properties: [] });\n                break;\n              case \"RegExp\":\n                self.expression = make_node(AST_RegExp, self.expression, { value: /t/ });\n                break;\n              case \"String\":\n                self.expression = make_node(AST_String, self.expression, { value: \"\" });\n                break;\n            }\n        }\n        var sub = self.flatten_object(self.property, compressor);\n        if (sub) return sub.optimize(compressor);\n        return try_evaluate(compressor, self);\n    });\n\n    OPT(AST_DestructuredArray, function(self, compressor) {\n        if (compressor.option(\"rests\") && self.rest instanceof AST_DestructuredArray) {\n            return make_node(AST_DestructuredArray, self, {\n                elements: self.elements.concat(self.rest.elements),\n                rest: self.rest.rest,\n            });\n        }\n        return self;\n    });\n\n    OPT(AST_DestructuredKeyVal, function(self, compressor) {\n        if (compressor.option(\"objects\")) {\n            var key = self.key;\n            if (key instanceof AST_Node) {\n                key = key.evaluate(compressor);\n                if (key !== self.key) self.key = \"\" + key;\n            }\n        }\n        return self;\n    });\n\n    OPT(AST_Object, function(self, compressor) {\n        if (!compressor.option(\"objects\")) return self;\n        var changed = false;\n        var found = false;\n        var generated = false;\n        var keep_duplicate = compressor.has_directive(\"use strict\");\n        var keys = [];\n        var map = new Dictionary();\n        var values = [];\n        self.properties.forEach(function(prop) {\n            if (!(prop instanceof AST_Spread)) return process(prop);\n            found = true;\n            var exp = prop.expression;\n            if (compressor.option(\"spreads\") && exp instanceof AST_Object && all(exp.properties, function(prop) {\n                if (prop instanceof AST_ObjectGetter) return false;\n                if (prop instanceof AST_Spread) return false;\n                if (prop.key !== \"__proto__\") return true;\n                if (prop instanceof AST_ObjectSetter) return true;\n                return !prop.value.has_side_effects(compressor);\n            })) {\n                changed = true;\n                exp.properties.forEach(function(prop) {\n                    var key = prop.key;\n                    var setter = prop instanceof AST_ObjectSetter;\n                    if (key === \"__proto__\") {\n                        if (!setter) return;\n                        key = make_node_from_constant(key, prop);\n                    }\n                    process(setter ? make_node(AST_ObjectKeyVal, prop, {\n                        key: key,\n                        value: make_node(AST_Undefined, prop).optimize(compressor),\n                    }) : prop);\n                });\n            } else {\n                generated = true;\n                flush();\n                values.push(prop);\n            }\n        });\n        flush();\n        if (!changed) return self;\n        if (found && generated && values.length == 1) {\n            var value = values[0];\n            if (value instanceof AST_ObjectProperty && value.key instanceof AST_Number) {\n                value.key = \"\" + value.key.value;\n            }\n        }\n        return make_node(AST_Object, self, { properties: values });\n\n        function flush() {\n            keys.forEach(function(key) {\n                var props = map.get(key);\n                switch (props.length) {\n                  case 0:\n                    return;\n                  case 1:\n                    return values.push(props[0]);\n                }\n                changed = true;\n                var tail = keep_duplicate && !generated && props.pop();\n                values.push(props.length == 1 ? props[0] : make_node(AST_ObjectKeyVal, self, {\n                    key: props[0].key,\n                    value: make_sequence(self, props.map(function(prop) {\n                        return prop.value;\n                    })),\n                }));\n                if (tail) values.push(tail);\n                props.length = 0;\n            });\n            keys = [];\n            map = new Dictionary();\n        }\n\n        function process(prop) {\n            var key = prop.key;\n            if (key instanceof AST_Node) {\n                found = true;\n                key = key.evaluate(compressor);\n                if (key === prop.key || key === \"__proto__\") {\n                    generated = true;\n                } else {\n                    key = prop.key = \"\" + key;\n                }\n            }\n            if (can_hoist_property(prop)) {\n                if (prop.value.has_side_effects(compressor)) flush();\n                keys.push(key);\n                map.add(key, prop);\n            } else {\n                flush();\n                values.push(prop);\n            }\n            if (found && !generated && typeof key == \"string\" && RE_POSITIVE_INTEGER.test(key)) {\n                generated = true;\n                if (map.has(key)) prop = map.get(key)[0];\n                prop.key = make_node(AST_Number, prop, { value: +key });\n            }\n        }\n    });\n\n    function flatten_var(name) {\n        var redef = name.definition().redefined();\n        if (redef) {\n            name = name.clone();\n            name.thedef = redef;\n        }\n        return name;\n    }\n\n    function has_arg_refs(fn, node) {\n        var found = false;\n        node.walk(new TreeWalker(function(node) {\n            if (found) return true;\n            if (node instanceof AST_SymbolRef && fn.variables.get(node.name) === node.definition()) {\n                return found = true;\n            }\n        }));\n        return found;\n    }\n\n    function insert_assign(def, assign) {\n        var visited = [];\n        def.references.forEach(function(ref) {\n            var fixed = ref.fixed;\n            if (!fixed || !push_uniq(visited, fixed)) return;\n            if (fixed.assigns) {\n                fixed.assigns.unshift(assign);\n            } else {\n                fixed.assigns = [ assign ];\n            }\n        });\n    }\n\n    function init_ref(compressor, name) {\n        var sym = make_node(AST_SymbolRef, name);\n        var assign = make_node(AST_Assign, name, {\n            operator: \"=\",\n            left: sym,\n            right: make_node(AST_Undefined, name).transform(compressor),\n        });\n        var def = name.definition();\n        if (def.fixed) {\n            sym.fixed = function() {\n                return assign.right;\n            };\n            sym.fixed.assigns = [ assign ];\n            insert_assign(def, assign);\n        }\n        def.assignments++;\n        def.references.push(sym);\n        return assign;\n    }\n\n    (function(def) {\n        def(AST_Node, noop);\n        def(AST_Assign, noop);\n        def(AST_Await, function(compressor, scope, no_return, in_loop) {\n            if (!compressor.option(\"awaits\")) return;\n            var self = this;\n            var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop, true);\n            if (!inlined) return;\n            if (!no_return) scan_local_returns(inlined, function(node) {\n                node.in_bool = false;\n                var value = node.value;\n                if (value instanceof AST_Await) return;\n                node.value = make_node(AST_Await, self, {\n                    expression: value || make_node(AST_Undefined, node).transform(compressor),\n                });\n            });\n            return aborts(inlined) ? inlined : make_node(AST_BlockStatement, self, {\n                body: [ inlined, make_node(AST_SimpleStatement, self, {\n                    body: make_node(AST_Await, self, { expression: make_node(AST_Number, self, { value: 0 })}),\n                }) ],\n            });\n        });\n        def(AST_Binary, function(compressor, scope, no_return, in_loop, in_await) {\n            if (no_return === undefined) return;\n            var self = this;\n            var op = self.operator;\n            if (!lazy_op[op]) return;\n            var inlined = self.right.try_inline(compressor, scope, no_return, in_loop, in_await);\n            if (!inlined) return;\n            return make_node(AST_If, self, {\n                condition: make_condition(self.left),\n                body: inlined,\n                alternative: no_return ? null : make_node(AST_Return, self, {\n                    value: make_node(AST_Undefined, self).transform(compressor),\n                }),\n            });\n\n            function make_condition(cond) {\n                switch (op) {\n                  case \"&&\":\n                    return cond;\n                  case \"||\":\n                    return cond.negate(compressor);\n                  case \"??\":\n                    return make_node(AST_Binary, self, {\n                        operator: \"==\",\n                        left: make_node(AST_Null, self),\n                        right: cond,\n                    });\n                }\n            }\n        });\n        def(AST_BlockStatement, function(compressor, scope, no_return, in_loop) {\n            if (no_return) return;\n            if (!this.variables) return;\n            var body = this.body;\n            var last = body.length - 1;\n            if (last < 0) return;\n            var inlined = body[last].try_inline(compressor, this, no_return, in_loop);\n            if (!inlined) return;\n            body[last] = inlined;\n            return this;\n        });\n        def(AST_Call, function(compressor, scope, no_return, in_loop, in_await) {\n            if (compressor.option(\"inline\") < 4) return;\n            var call = this;\n            if (call.is_expr_pure(compressor)) return;\n            var fn = call.expression;\n            if (!(fn instanceof AST_LambdaExpression)) return;\n            if (fn.name) return;\n            if (fn.single_use) return;\n            if (fn.uses_arguments) return;\n            if (fn.pinned()) return;\n            if (is_generator(fn)) return;\n            var arrow = is_arrow(fn);\n            var fn_body = arrow && fn.value ? [ fn.first_statement() ] : fn.body;\n            if (fn_body[0] instanceof AST_Directive) return;\n            if (fn.contains_this()) return;\n            if (!scope) scope = find_scope(compressor);\n            var defined = new Dictionary();\n            defined.set(\"NaN\", true);\n            while (!(scope instanceof AST_Scope)) {\n                scope.variables.each(function(def) {\n                    defined.set(def.name, true);\n                });\n                scope = scope.parent_scope;\n            }\n            if (!member(scope, compressor.stack)) return;\n            if (scope.pinned() && fn.variables.size() > (arrow ? 0 : 1)) return;\n            if (scope instanceof AST_Toplevel) {\n                if (fn.variables.size() > (arrow ? 0 : 1)) {\n                    if (!compressor.toplevel.vars) return;\n                    if (fn.functions.size() > 0 && !compressor.toplevel.funcs) return;\n                }\n                defined.set(\"arguments\", true);\n            }\n            var async = !in_await && is_async(fn);\n            if (async) {\n                if (!compressor.option(\"awaits\")) return;\n                if (!is_async(scope)) return;\n                if (call.may_throw(compressor)) return;\n            }\n            var names = scope.var_names();\n            if (in_loop) in_loop = [];\n            if (!fn.variables.all(function(def, name) {\n                if (in_loop) in_loop.push(def);\n                if (!defined.has(name) && !names.has(name)) return true;\n                return !arrow && name == \"arguments\" && def.orig.length == 1;\n            })) return;\n            if (in_loop && in_loop.length > 0 && is_reachable(fn, in_loop)) return;\n            var simple_argnames = true;\n            if (!all(fn.argnames, function(argname) {\n                var abort = false;\n                var tw = new TreeWalker(function(node) {\n                    if (abort) return true;\n                    if (node instanceof AST_DefaultValue) {\n                        if (has_arg_refs(fn, node.value)) return abort = true;\n                        node.name.walk(tw);\n                        return true;\n                    }\n                    if (node instanceof AST_DestructuredKeyVal) {\n                        if (node.key instanceof AST_Node && has_arg_refs(fn, node.key)) return abort = true;\n                        node.value.walk(tw);\n                        return true;\n                    }\n                    if (node instanceof AST_SymbolFunarg && !all(node.definition().orig, function(sym) {\n                        return !(sym instanceof AST_SymbolDefun);\n                    })) return abort = true;\n                });\n                argname.walk(tw);\n                if (abort) return false;\n                if (!(argname instanceof AST_SymbolFunarg)) simple_argnames = false;\n                return true;\n            })) return;\n            if (fn.rest) {\n                if (has_arg_refs(fn, fn.rest)) return;\n                simple_argnames = false;\n            }\n            var verify_body;\n            if (no_return) {\n                verify_body = function(stat) {\n                    var abort = false;\n                    stat.walk(new TreeWalker(function(node) {\n                        if (abort) return true;\n                        if (async && (node instanceof AST_Await || node instanceof AST_ForAwaitOf)\n                            || node instanceof AST_Return) {\n                            return abort = true;\n                        }\n                        if (node instanceof AST_Scope) return true;\n                    }));\n                    return !abort;\n                };\n            } else if (in_await || is_async(fn) || in_async_generator(scope)) {\n                verify_body = function(stat) {\n                    var abort = false;\n                    var find_return = new TreeWalker(function(node) {\n                        if (abort) return true;\n                        if (node instanceof AST_Return) return abort = true;\n                        if (node instanceof AST_Scope) return true;\n                    });\n                    var tw = new TreeWalker(function(node) {\n                        if (abort) return true;\n                        if (node instanceof AST_Try) {\n                            if (!node.bfinally) return;\n                            if (all(node.body, function(stat) {\n                                stat.walk(find_return);\n                                return !abort;\n                            })) {\n                                if (node.bcatch) node.bcatch.walk(find_return);\n                                node.bfinally.walk(tw);\n                            }\n                            return true;\n                        }\n                        if (node instanceof AST_Scope) return true;\n                    });\n                    stat.walk(tw);\n                    return !abort;\n                };\n            }\n            if (verify_body && !all(fn_body, verify_body)) return;\n            if (!safe_from_await_yield(fn, avoid_await_yield(compressor, scope))) return;\n            fn.functions.each(function(def, name) {\n                scope.functions.set(name, def);\n            });\n            var body = [];\n            fn.variables.each(function(def, name) {\n                if (!arrow && name == \"arguments\" && def.orig.length == 1) return;\n                names.set(name, true);\n                scope.enclosed.push(def);\n                scope.variables.set(name, def);\n                def.single_use = false;\n                if (!in_loop) return;\n                if (def.references.length == def.replaced) return;\n                switch (def.orig.length - def.eliminated) {\n                  case 0:\n                    return;\n                  case 1:\n                    if (fn.functions.has(name)) return;\n                }\n                if (!all(def.orig, function(sym) {\n                    if (sym instanceof AST_SymbolConst) return false;\n                    if (sym instanceof AST_SymbolFunarg) return !sym.unused && def.scope.resolve() !== fn;\n                    if (sym instanceof AST_SymbolLambda) {\n                        if (!compressor.option(\"ie\")) return true;\n                        if (sym.scope === def.scope) return true;\n                        return !all(def.orig, function(decl) {\n                            return !(decl instanceof AST_SymbolVar);\n                        });\n                    }\n                    if (sym instanceof AST_SymbolLet) return false;\n                    return true;\n                })) return;\n                var sym = def.orig[0];\n                if (sym instanceof AST_SymbolCatch) return;\n                body.push(make_node(AST_SimpleStatement, sym, { body: init_ref(compressor, flatten_var(sym)) }));\n                def.first_decl = null;\n            });\n            var defs = Object.create(null), syms = new Dictionary();\n            if (simple_argnames && all(call.args, function(arg) {\n                return !(arg instanceof AST_Spread);\n            })) {\n                var values = call.args.slice();\n                fn.argnames.forEach(function(argname) {\n                    var value = values.shift();\n                    if (argname.unused) {\n                        if (value) body.push(make_node(AST_SimpleStatement, call, { body: value }));\n                        return;\n                    }\n                    var defn = make_node(AST_VarDef, call, {\n                        name: argname.convert_symbol(AST_SymbolVar, process),\n                        value: value || make_node(AST_Undefined, call).transform(compressor),\n                    });\n                    if (argname instanceof AST_SymbolFunarg) insert_assign(argname.definition(), defn);\n                    body.push(make_node(AST_Var, call, { definitions: [ defn ] }));\n                });\n                if (values.length) body.push(make_node(AST_SimpleStatement, call, {\n                    body: make_sequence(call, values),\n                }));\n            } else {\n                body.push(make_node(AST_Var, call, {\n                    definitions: [ make_node(AST_VarDef, call, {\n                        name: make_node(AST_DestructuredArray, call, {\n                            elements: fn.argnames.map(function(argname) {\n                                if (argname.unused) return make_node(AST_Hole, argname);\n                                return argname.convert_symbol(AST_SymbolVar, process);\n                            }),\n                            rest: fn.rest && fn.rest.convert_symbol(AST_SymbolVar, process),\n                        }),\n                        value: make_node(AST_Array, call, { elements: call.args.slice() }),\n                    }) ],\n                }));\n            }\n            syms.each(function(orig, id) {\n                var def = defs[id];\n                [].unshift.apply(def.orig, orig);\n                def.eliminated += orig.length;\n            });\n            [].push.apply(body, in_loop ? fn_body.filter(function(stat) {\n                if (!(stat instanceof AST_LambdaDefinition)) return true;\n                var name = make_node(AST_SymbolVar, flatten_var(stat.name));\n                var def = name.definition();\n                def.fixed = false;\n                def.orig.push(name);\n                def.eliminated++;\n                body.push(make_node(AST_Var, stat, {\n                    definitions: [ make_node(AST_VarDef, stat, {\n                        name: name,\n                        value: to_func_expr(stat, true),\n                    }) ],\n                }));\n                return false;\n            }) : fn_body);\n            var inlined = make_node(AST_BlockStatement, call, { body: body });\n            if (!no_return) {\n                if (async) scan_local_returns(inlined, function(node) {\n                    var value = node.value;\n                    if (is_undefined(value)) return;\n                    node.value = make_node(AST_Await, call, { expression: value });\n                });\n                body.push(make_node(AST_Return, call, {\n                    value: in_async_generator(scope) ? make_node(AST_Undefined, call).transform(compressor) : null,\n                }));\n            }\n            return inlined;\n\n            function process(sym, argname) {\n                var def = argname.definition();\n                defs[def.id] = def;\n                syms.add(def.id, sym);\n            }\n        });\n        def(AST_Conditional, function(compressor, scope, no_return, in_loop, in_await) {\n            var self = this;\n            var body = self.consequent.try_inline(compressor, scope, no_return, in_loop, in_await);\n            var alt = self.alternative.try_inline(compressor, scope, no_return, in_loop, in_await);\n            if (!body && !alt) return;\n            return make_node(AST_If, self, {\n                condition: self.condition,\n                body: body || make_body(self.consequent),\n                alternative: alt || make_body(self.alternative),\n            });\n\n            function make_body(value) {\n                if (no_return) return make_node(AST_SimpleStatement, value, { body: value });\n                return make_node(AST_Return, value, { value: value });\n            }\n        });\n        def(AST_For, function(compressor, scope, no_return, in_loop) {\n            var body = this.body.try_inline(compressor, scope, true, true);\n            if (body) this.body = body;\n            var inlined = this.init;\n            if (inlined) {\n                inlined = inlined.try_inline(compressor, scope, true, in_loop);\n                if (inlined) {\n                    this.init = null;\n                    if (inlined instanceof AST_BlockStatement) {\n                        inlined.body.push(this);\n                        return inlined;\n                    }\n                    return make_node(AST_BlockStatement, inlined, { body: [ inlined, this ] });\n                }\n            }\n            return body && this;\n        });\n        def(AST_ForEnumeration, function(compressor, scope, no_return, in_loop) {\n            var body = this.body.try_inline(compressor, scope, true, true);\n            if (body) this.body = body;\n            var obj = this.object;\n            if (obj instanceof AST_Sequence) {\n                var inlined = inline_sequence(compressor, scope, true, in_loop, false, obj, 1);\n                if (inlined) {\n                    this.object = obj.tail_node();\n                    inlined.body.push(this);\n                    return inlined;\n                }\n            }\n            return body && this;\n        });\n        def(AST_If, function(compressor, scope, no_return, in_loop) {\n            var body = this.body.try_inline(compressor, scope, no_return, in_loop);\n            if (body) this.body = body;\n            var alt = this.alternative;\n            if (alt) {\n                alt = alt.try_inline(compressor, scope, no_return, in_loop);\n                if (alt) this.alternative = alt;\n            }\n            var cond = this.condition;\n            if (cond instanceof AST_Sequence) {\n                var inlined = inline_sequence(compressor, scope, true, in_loop, false, cond, 1);\n                if (inlined) {\n                    this.condition = cond.tail_node();\n                    inlined.body.push(this);\n                    return inlined;\n                }\n            }\n            return (body || alt) && this;\n        });\n        def(AST_IterationStatement, function(compressor, scope, no_return, in_loop) {\n            var body = this.body.try_inline(compressor, scope, true, true);\n            if (!body) return;\n            this.body = body;\n            return this;\n        });\n        def(AST_LabeledStatement, function(compressor, scope, no_return, in_loop) {\n            var body = this.body.try_inline(compressor, scope, no_return, in_loop);\n            if (!body) return;\n            if (this.body instanceof AST_IterationStatement && body instanceof AST_BlockStatement) {\n                var loop = body.body.pop();\n                this.body = loop;\n                body.body.push(this);\n                return body;\n            }\n            this.body = body;\n            return this;\n        });\n        def(AST_New, noop);\n        def(AST_Return, function(compressor, scope, no_return, in_loop) {\n            var value = this.value;\n            return value && value.try_inline(compressor, scope, undefined, in_loop === \"try\");\n        });\n        function inline_sequence(compressor, scope, no_return, in_loop, in_await, node, skip) {\n            var body = [], exprs = node.expressions, no_ret = no_return;\n            for (var i = exprs.length - (skip || 0), j = i; --i >= 0; no_ret = true, in_await = false) {\n                var inlined = exprs[i].try_inline(compressor, scope, no_ret, in_loop, in_await);\n                if (!inlined) continue;\n                flush();\n                body.push(inlined);\n            }\n            if (body.length == 0) return;\n            flush();\n            if (!no_return && body[0] instanceof AST_SimpleStatement) {\n                body[0] = make_node(AST_Return, node, { value: body[0].body });\n            }\n            return make_node(AST_BlockStatement, node, { body: body.reverse() });\n\n            function flush() {\n                if (j > i + 1) body.push(make_node(AST_SimpleStatement, node, {\n                    body: make_sequence(node, exprs.slice(i + 1, j)),\n                }));\n                j = i;\n            }\n        }\n        def(AST_Sequence, function(compressor, scope, no_return, in_loop, in_await) {\n            return inline_sequence(compressor, scope, no_return, in_loop, in_await, this);\n        });\n        def(AST_SimpleStatement, function(compressor, scope, no_return, in_loop) {\n            var body = this.body;\n            while (body instanceof AST_UnaryPrefix) {\n                var op = body.operator;\n                if (unary_side_effects[op]) break;\n                if (op == \"void\") break;\n                body = body.expression;\n            }\n            if (!no_return && !is_undefined(body)) body = make_node(AST_UnaryPrefix, this, {\n                operator: \"void\",\n                expression: body,\n            });\n            return body.try_inline(compressor, scope, no_return || false, in_loop);\n        });\n        def(AST_UnaryPrefix, function(compressor, scope, no_return, in_loop, in_await) {\n            var self = this;\n            var op = self.operator;\n            if (unary_side_effects[op]) return;\n            if (!no_return && op == \"void\") no_return = false;\n            var inlined = self.expression.try_inline(compressor, scope, no_return, in_loop, in_await);\n            if (!inlined) return;\n            if (!no_return) scan_local_returns(inlined, function(node) {\n                node.in_bool = false;\n                var value = node.value;\n                if (op == \"void\" && is_undefined(value)) return;\n                node.value = make_node(AST_UnaryPrefix, self, {\n                    operator: op,\n                    expression: value || make_node(AST_Undefined, node).transform(compressor),\n                });\n            });\n            return inlined;\n        });\n        def(AST_With, function(compressor, scope, no_return, in_loop) {\n            var body = this.body.try_inline(compressor, scope, no_return, in_loop);\n            if (body) this.body = body;\n            var exp = this.expression;\n            if (exp instanceof AST_Sequence) {\n                var inlined = inline_sequence(compressor, scope, true, in_loop, false, exp, 1);\n                if (inlined) {\n                    this.expression = exp.tail_node();\n                    inlined.body.push(this);\n                    return inlined;\n                }\n            }\n            return body && this;\n        });\n        def(AST_Yield, function(compressor, scope, no_return, in_loop) {\n            if (!compressor.option(\"yields\")) return;\n            if (!this.nested) return;\n            var call = this.expression;\n            if (call.TYPE != \"Call\") return;\n            var fn = call.expression;\n            switch (fn.CTOR) {\n              case AST_AsyncGeneratorFunction:\n                fn = make_node(AST_AsyncFunction, fn);\n                break;\n              case AST_GeneratorFunction:\n                fn = make_node(AST_Function, fn);\n                break;\n              default:\n                return;\n            }\n            call = call.clone();\n            call.expression = fn;\n            return call.try_inline(compressor, scope, no_return, in_loop);\n        });\n    })(function(node, func) {\n        node.DEFMETHOD(\"try_inline\", func);\n    });\n\n    OPT(AST_Return, function(self, compressor) {\n        var value = self.value;\n        if (value && compressor.option(\"side_effects\")\n            && is_undefined(value, compressor)\n            && !in_async_generator(compressor.find_parent(AST_Scope))) {\n            self.value = null;\n        }\n        return self;\n    });\n})(function(node, optimizer) {\n    node.DEFMETHOD(\"optimize\", function(compressor) {\n        var self = this;\n        if (self._optimized) return self;\n        if (compressor.has_directive(\"use asm\")) return self;\n        var opt = optimizer(self, compressor);\n        opt._optimized = true;\n        return opt;\n    });\n});\n"
  },
  {
    "path": "lib/minify.js",
    "content": "\"use strict\";\n\nvar to_ascii, to_base64;\nif (typeof Buffer == \"undefined\") {\n    to_ascii = atob;\n    to_base64 = btoa;\n} else if (typeof Buffer.alloc == \"undefined\") {\n    to_ascii = function(b64) {\n        return new Buffer(b64, \"base64\").toString();\n    };\n    to_base64 = function(str) {\n        return new Buffer(str).toString(\"base64\");\n    };\n} else {\n    to_ascii = function(b64) {\n        return Buffer.from(b64, \"base64\").toString();\n    };\n    to_base64 = function(str) {\n        return Buffer.from(str).toString(\"base64\");\n    };\n}\n\nfunction read_source_map(name, toplevel) {\n    var comments = toplevel.end.comments_after;\n    for (var i = comments.length; --i >= 0;) {\n        var comment = comments[i];\n        if (comment.type != \"comment1\") break;\n        var match = /^# ([^\\s=]+)=(\\S+)\\s*$/.exec(comment.value);\n        if (!match) break;\n        if (match[1] == \"sourceMappingURL\") {\n            match = /^data:application\\/json(;.*?)?;base64,([^,]+)$/.exec(match[2]);\n            if (!match) break;\n            return to_ascii(match[2]);\n        }\n    }\n    AST_Node.warn(\"inline source map not found: {name}\", {\n        name: name,\n    });\n}\n\nfunction parse_source_map(content) {\n    try {\n        return JSON.parse(content);\n    } catch (ex) {\n        throw new Error(\"invalid input source map: \" + content);\n    }\n}\n\nfunction set_shorthand(name, options, keys) {\n    keys.forEach(function(key) {\n        if (options[key]) {\n            var defs = {};\n            defs[name] = options[name];\n            options[key] = defaults(options[key], defs);\n        }\n    });\n}\n\nfunction init_cache(cache) {\n    if (!cache) return;\n    if (!(\"props\" in cache)) {\n        cache.props = new Dictionary();\n    } else if (!(cache.props instanceof Dictionary)) {\n        cache.props = Dictionary.fromObject(cache.props);\n    }\n}\n\nfunction to_json(cache) {\n    return {\n        props: cache.props.toObject()\n    };\n}\n\nfunction minify(files, options) {\n    try {\n        options = defaults(options, {\n            annotations: undefined,\n            compress: {},\n            enclose: false,\n            expression: false,\n            ie: false,\n            ie8: false,\n            keep_fargs: false,\n            keep_fnames: false,\n            mangle: {},\n            module: undefined,\n            nameCache: null,\n            output: {},\n            parse: {},\n            rename: undefined,\n            sourceMap: false,\n            timings: false,\n            toplevel: options && !options[\"expression\"] && options[\"module\"] ? true : undefined,\n            v8: false,\n            validate: false,\n            warnings: false,\n            webkit: false,\n            wrap: false,\n        }, true);\n        if (options.validate) AST_Node.enable_validation();\n        var timings = options.timings && { start: Date.now() };\n        if (options.annotations !== undefined) set_shorthand(\"annotations\", options, [ \"compress\", \"output\" ]);\n        if (options.expression) set_shorthand(\"expression\", options, [ \"compress\", \"parse\" ]);\n        if (options.ie8) options.ie = options.ie || options.ie8;\n        if (options.ie) set_shorthand(\"ie\", options, [ \"compress\", \"mangle\", \"output\", \"rename\" ]);\n        if (options.keep_fargs) set_shorthand(\"keep_fargs\", options, [ \"compress\", \"mangle\", \"rename\" ]);\n        if (options.keep_fnames) set_shorthand(\"keep_fnames\", options, [ \"compress\", \"mangle\", \"rename\" ]);\n        if (options.module === undefined && !options.ie) options.module = true;\n        if (options.module) set_shorthand(\"module\", options, [ \"compress\", \"output\", \"parse\" ]);\n        if (options.toplevel !== undefined) set_shorthand(\"toplevel\", options, [ \"compress\", \"mangle\", \"rename\" ]);\n        if (options.v8) set_shorthand(\"v8\", options, [ \"mangle\", \"output\", \"rename\" ]);\n        if (options.webkit) set_shorthand(\"webkit\", options, [ \"compress\", \"mangle\", \"output\", \"rename\" ]);\n        var quoted_props;\n        if (options.mangle) {\n            options.mangle = defaults(options.mangle, {\n                cache: options.nameCache && (options.nameCache.vars || {}),\n                eval: false,\n                ie: false,\n                keep_fargs: false,\n                keep_fnames: false,\n                properties: false,\n                reserved: [],\n                toplevel: false,\n                v8: false,\n                webkit: false,\n            }, true);\n            if (options.mangle.properties) {\n                if (typeof options.mangle.properties != \"object\") {\n                    options.mangle.properties = {};\n                }\n                if (options.mangle.properties.keep_quoted) {\n                    quoted_props = options.mangle.properties.reserved;\n                    if (!Array.isArray(quoted_props)) quoted_props = [];\n                    options.mangle.properties.reserved = quoted_props;\n                }\n                if (options.nameCache && !(\"cache\" in options.mangle.properties)) {\n                    options.mangle.properties.cache = options.nameCache.props || {};\n                }\n            }\n            init_cache(options.mangle.cache);\n            init_cache(options.mangle.properties.cache);\n        }\n        if (options.rename === undefined) options.rename = options.compress && options.mangle;\n        if (options.sourceMap) {\n            options.sourceMap = defaults(options.sourceMap, {\n                content: null,\n                filename: null,\n                includeSources: false,\n                names: true,\n                root: null,\n                url: null,\n            }, true);\n        }\n        var warnings = [];\n        if (options.warnings) AST_Node.log_function(function(warning) {\n            warnings.push(warning);\n        }, options.warnings == \"verbose\");\n        if (timings) timings.parse = Date.now();\n        var toplevel;\n        options.parse = options.parse || {};\n        if (files instanceof AST_Node) {\n            toplevel = files;\n        } else {\n            if (typeof files == \"string\") files = [ files ];\n            options.parse.toplevel = null;\n            var source_map_content = options.sourceMap && options.sourceMap.content;\n            if (typeof source_map_content == \"string\" && source_map_content != \"inline\") {\n                source_map_content = parse_source_map(source_map_content);\n            }\n            if (source_map_content) options.sourceMap.orig = Object.create(null);\n            for (var name in files) if (HOP(files, name)) {\n                options.parse.filename = name;\n                options.parse.toplevel = toplevel = parse(files[name], options.parse);\n                if (source_map_content == \"inline\") {\n                    var inlined_content = read_source_map(name, toplevel);\n                    if (inlined_content) options.sourceMap.orig[name] = parse_source_map(inlined_content);\n                } else if (source_map_content) {\n                    options.sourceMap.orig[name] = source_map_content;\n                }\n            }\n        }\n        if (options.parse.expression) toplevel = toplevel.wrap_expression();\n        if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);\n        [ \"enclose\", \"wrap\" ].forEach(function(action) {\n            var option = options[action];\n            if (!option) return;\n            var orig = toplevel.print_to_string().slice(0, -1);\n            toplevel = toplevel[action](option);\n            files[toplevel.start.file] = toplevel.print_to_string().replace(orig, \"\");\n        });\n        if (options.validate) toplevel.validate_ast();\n        if (timings) timings.rename = Date.now();\n        if (options.rename) {\n            toplevel.figure_out_scope(options.rename);\n            toplevel.expand_names(options.rename);\n        }\n        if (timings) timings.compress = Date.now();\n        if (options.compress) {\n            toplevel = new Compressor(options.compress).compress(toplevel);\n            if (options.validate) toplevel.validate_ast();\n        }\n        if (timings) timings.scope = Date.now();\n        if (options.mangle) toplevel.figure_out_scope(options.mangle);\n        if (timings) timings.mangle = Date.now();\n        if (options.mangle) {\n            toplevel.compute_char_frequency(options.mangle);\n            toplevel.mangle_names(options.mangle);\n        }\n        if (timings) timings.properties = Date.now();\n        if (quoted_props) reserve_quoted_keys(toplevel, quoted_props);\n        if (options.mangle && options.mangle.properties) mangle_properties(toplevel, options.mangle.properties);\n        if (options.parse.expression) toplevel = toplevel.unwrap_expression();\n        if (timings) timings.output = Date.now();\n        var result = {};\n        var output = defaults(options.output, {\n            ast: false,\n            code: true,\n        });\n        if (output.ast) result.ast = toplevel;\n        if (output.code) {\n            if (options.sourceMap) {\n                output.source_map = SourceMap(options.sourceMap);\n                if (options.sourceMap.includeSources) {\n                    if (files instanceof AST_Toplevel) {\n                        throw new Error(\"original source content unavailable\");\n                    } else for (var name in files) if (HOP(files, name)) {\n                        output.source_map.setSourceContent(name, files[name]);\n                    }\n                }\n            }\n            delete output.ast;\n            delete output.code;\n            var stream = OutputStream(output);\n            toplevel.print(stream);\n            result.code = stream.get();\n            if (options.sourceMap) {\n                result.map = output.source_map.toString();\n                var url = options.sourceMap.url;\n                if (url) {\n                    result.code = result.code.replace(/\\n\\/\\/# sourceMappingURL=\\S+\\s*$/, \"\");\n                    if (url == \"inline\") {\n                        result.code += \"\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,\" + to_base64(result.map);\n                    } else {\n                        result.code += \"\\n//# sourceMappingURL=\" + url;\n                    }\n                }\n            }\n        }\n        if (options.nameCache && options.mangle) {\n            if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);\n            if (options.mangle.properties && options.mangle.properties.cache) {\n                options.nameCache.props = to_json(options.mangle.properties.cache);\n            }\n        }\n        if (timings) {\n            timings.end = Date.now();\n            result.timings = {\n                parse: 1e-3 * (timings.rename - timings.parse),\n                rename: 1e-3 * (timings.compress - timings.rename),\n                compress: 1e-3 * (timings.scope - timings.compress),\n                scope: 1e-3 * (timings.mangle - timings.scope),\n                mangle: 1e-3 * (timings.properties - timings.mangle),\n                properties: 1e-3 * (timings.output - timings.properties),\n                output: 1e-3 * (timings.end - timings.output),\n                total: 1e-3 * (timings.end - timings.start)\n            };\n        }\n        if (warnings.length) {\n            result.warnings = warnings;\n        }\n        return result;\n    } catch (ex) {\n        return { error: ex };\n    } finally {\n        AST_Node.log_function();\n        AST_Node.disable_validation();\n    }\n}\n"
  },
  {
    "path": "lib/mozilla-ast.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\n(function() {\n    var MOZ_TO_ME = {\n        Program: function(M) {\n            return new AST_Toplevel({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                body: normalize_directives(M.body.map(from_moz)),\n            });\n        },\n        ArrowFunctionExpression: function(M) {\n            var argnames = [], rest = null;\n            M.params.forEach(function(param) {\n                if (param.type == \"RestElement\") {\n                    rest = from_moz(param.argument);\n                } else {\n                    argnames.push(from_moz(param));\n                }\n            });\n            var fn = new (M.async ? AST_AsyncArrow : AST_Arrow)({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                argnames: argnames,\n                rest: rest,\n            });\n            var node = from_moz(M.body);\n            if (node instanceof AST_BlockStatement) {\n                fn.body = normalize_directives(node.body);\n                fn.value = null;\n            } else {\n                fn.body = [];\n                fn.value = node;\n            }\n            return fn;\n        },\n        FunctionDeclaration: function(M) {\n            var ctor;\n            if (M.async) {\n                ctor = M.generator ? AST_AsyncGeneratorDefun : AST_AsyncDefun;\n            } else {\n                ctor = M.generator ? AST_GeneratorDefun : AST_Defun;\n            }\n            var argnames = [], rest = null;\n            M.params.forEach(function(param) {\n                if (param.type == \"RestElement\") {\n                    rest = from_moz(param.argument);\n                } else {\n                    argnames.push(from_moz(param));\n                }\n            });\n            return new ctor({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: from_moz(M.id),\n                argnames: argnames,\n                rest: rest,\n                body: normalize_directives(from_moz(M.body).body),\n            });\n        },\n        FunctionExpression: function(M) {\n            var ctor;\n            if (M.async) {\n                ctor = M.generator ? AST_AsyncGeneratorFunction : AST_AsyncFunction;\n            } else {\n                ctor = M.generator ? AST_GeneratorFunction : AST_Function;\n            }\n            var argnames = [], rest = null;\n            M.params.forEach(function(param) {\n                if (param.type == \"RestElement\") {\n                    rest = from_moz(param.argument);\n                } else {\n                    argnames.push(from_moz(param));\n                }\n            });\n            return new ctor({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: from_moz(M.id),\n                argnames: argnames,\n                rest: rest,\n                body: normalize_directives(from_moz(M.body).body),\n            });\n        },\n        CallExpression: function(M) {\n            return new AST_Call({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                expression: from_moz(M.callee),\n                args: M.arguments.map(from_moz),\n                optional: M.optional,\n                pure: M.pure,\n            });\n        },\n        ClassDeclaration: function(M) {\n            return new AST_DefClass({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: from_moz(M.id),\n                extends: from_moz(M.superClass),\n                properties: M.body.body.map(from_moz),\n            });\n        },\n        ClassExpression: function(M) {\n            return new AST_ClassExpression({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: from_moz(M.id),\n                extends: from_moz(M.superClass),\n                properties: M.body.body.map(from_moz),\n            });\n        },\n        MethodDefinition: function(M) {\n            var key = M.key, internal = false;\n            if (M.computed) {\n                key = from_moz(key);\n            } else if (key.type == \"PrivateIdentifier\") {\n                internal = true;\n                key = \"#\" + key.name;\n            } else {\n                key = read_name(key);\n            }\n            var ctor = AST_ClassMethod, value = from_moz(M.value);\n            switch (M.kind) {\n              case \"get\":\n                ctor = AST_ClassGetter;\n                value = new AST_Accessor(value);\n                break;\n              case \"set\":\n                ctor = AST_ClassSetter;\n                value = new AST_Accessor(value);\n                break;\n            }\n            return new ctor({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                key: key,\n                private: internal,\n                static: M.static,\n                value: value,\n            });\n        },\n        PropertyDefinition: function(M) {\n            var key = M.key, internal = false;\n            if (M.computed) {\n                key = from_moz(key);\n            } else if (key.type == \"PrivateIdentifier\") {\n                internal = true;\n                key = \"#\" + key.name;\n            } else {\n                key = read_name(key);\n            }\n            return new AST_ClassField({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                key: key,\n                private: internal,\n                static: M.static,\n                value: from_moz(M.value),\n            });\n        },\n        StaticBlock: function(M) {\n            var start = my_start_token(M);\n            var end = my_end_token(M);\n            return new AST_ClassInit({\n                start: start,\n                end: end,\n                value: new AST_ClassInitBlock({\n                    start: start,\n                    end: end,\n                    body: normalize_directives(M.body.map(from_moz)),\n                }),\n            });\n        },\n        ForOfStatement: function(M) {\n            return new (M.await ? AST_ForAwaitOf : AST_ForOf)({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                init: from_moz(M.left),\n                object: from_moz(M.right),\n                body: from_moz(M.body),\n            });\n        },\n        TryStatement: function(M) {\n            var handlers = M.handlers || [M.handler];\n            if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {\n                throw new Error(\"Multiple catch clauses are not supported.\");\n            }\n            return new AST_Try({\n                start    : my_start_token(M),\n                end      : my_end_token(M),\n                body     : from_moz(M.block).body,\n                bcatch   : from_moz(handlers[0]),\n                bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null,\n            });\n        },\n        Property: function(M) {\n            var key = M.computed ? from_moz(M.key) : read_name(M.key);\n            var args = {\n                start: my_start_token(M),\n                end: my_end_token(M),\n                key: key,\n                value: from_moz(M.value),\n            };\n            if (M.kind == \"init\") return new (M.method ? AST_ObjectMethod : AST_ObjectKeyVal)(args);\n            args.value = new AST_Accessor(args.value);\n            if (M.kind == \"get\") return new AST_ObjectGetter(args);\n            if (M.kind == \"set\") return new AST_ObjectSetter(args);\n        },\n        ArrayExpression: function(M) {\n            return new AST_Array({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                elements: M.elements.map(function(elem) {\n                    return elem === null ? new AST_Hole() : from_moz(elem);\n                }),\n            });\n        },\n        ArrayPattern: function(M) {\n            var elements = [], rest = null;\n            M.elements.forEach(function(el) {\n                if (el === null) {\n                    elements.push(new AST_Hole());\n                } else if (el.type == \"RestElement\") {\n                    rest = from_moz(el.argument);\n                } else {\n                    elements.push(from_moz(el));\n                }\n            });\n            return new AST_DestructuredArray({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                elements: elements,\n                rest: rest,\n            });\n        },\n        ObjectPattern: function(M) {\n            var props = [], rest = null;\n            M.properties.forEach(function(prop) {\n                if (prop.type == \"RestElement\") {\n                    rest = from_moz(prop.argument);\n                } else {\n                    props.push(new AST_DestructuredKeyVal(from_moz(prop)));\n                }\n            });\n            return new AST_DestructuredObject({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                properties: props,\n                rest: rest,\n            });\n        },\n        MemberExpression: function(M) {\n            return new (M.computed ? AST_Sub : AST_Dot)({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                optional: M.optional,\n                expression: from_moz(M.object),\n                property: M.computed ? from_moz(M.property) : M.property.name,\n            });\n        },\n        MetaProperty: function(M) {\n            var expr = from_moz(M.meta);\n            var prop = read_name(M.property);\n            if (expr.name == \"new\" && prop == \"target\") return new AST_NewTarget({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: \"new.target\",\n            });\n            return new AST_Dot({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                expression: expr,\n                property: prop,\n            });\n        },\n        SwitchCase: function(M) {\n            return new (M.test ? AST_Case : AST_Default)({\n                start      : my_start_token(M),\n                end        : my_end_token(M),\n                expression : from_moz(M.test),\n                body       : M.consequent.map(from_moz),\n            });\n        },\n        ExportAllDeclaration: function(M) {\n            var start = my_start_token(M);\n            var end = my_end_token(M);\n            return new AST_ExportForeign({\n                start: start,\n                end: end,\n                aliases: [ M.exported ? from_moz_alias(M.exported) : new AST_String({\n                    start: start,\n                    value: \"*\",\n                    end: end,\n                }) ],\n                keys: [ new AST_String({\n                    start: start,\n                    value: \"*\",\n                    end: end,\n                }) ],\n                path: from_moz(M.source),\n            });\n        },\n        ExportDefaultDeclaration: function(M) {\n            var decl = from_moz(M.declaration);\n            if (!decl.name) switch (decl.CTOR) {\n              case AST_AsyncDefun:\n                decl = new AST_AsyncFunction(decl);\n                break;\n              case AST_AsyncGeneratorDefun:\n                decl = new AST_AsyncGeneratorFunction(decl);\n                break;\n              case AST_DefClass:\n                decl = new AST_ClassExpression(decl);\n                break;\n              case AST_Defun:\n                decl = new AST_Function(decl);\n                break;\n              case AST_GeneratorDefun:\n                decl = new AST_GeneratorFunction(decl);\n                break;\n            }\n            return new AST_ExportDefault({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                body: decl,\n            });\n        },\n        ExportNamedDeclaration: function(M) {\n            if (M.declaration) return new AST_ExportDeclaration({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                body: from_moz(M.declaration),\n            });\n            if (M.source) {\n                var aliases = [], keys = [];\n                M.specifiers.forEach(function(prop) {\n                    aliases.push(from_moz_alias(prop.exported));\n                    keys.push(from_moz_alias(prop.local));\n                });\n                return new AST_ExportForeign({\n                    start: my_start_token(M),\n                    end: my_end_token(M),\n                    aliases: aliases,\n                    keys: keys,\n                    path: from_moz(M.source),\n                });\n            }\n            return new AST_ExportReferences({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                properties: M.specifiers.map(function(prop) {\n                    var sym = new AST_SymbolExport(from_moz(prop.local));\n                    sym.alias = from_moz_alias(prop.exported);\n                    return sym;\n                }),\n            });\n        },\n        ImportDeclaration: function(M) {\n            var start = my_start_token(M);\n            var end = my_end_token(M);\n            var all = null, def = null, props = null;\n            M.specifiers.forEach(function(prop) {\n                var sym = new AST_SymbolImport(from_moz(prop.local));\n                switch (prop.type) {\n                  case \"ImportDefaultSpecifier\":\n                    def = sym;\n                    def.key = new AST_String({\n                        start: start,\n                        value: \"\",\n                        end: end,\n                    });\n                    break;\n                  case \"ImportNamespaceSpecifier\":\n                    all = sym;\n                    all.key = new AST_String({\n                        start: start,\n                        value: \"*\",\n                        end: end,\n                    });\n                    break;\n                  default:\n                    sym.key = from_moz_alias(prop.imported);\n                    if (!props) props = [];\n                    props.push(sym);\n                    break;\n                }\n            });\n            return new AST_Import({\n                start: start,\n                end: end,\n                all: all,\n                default: def,\n                properties: props,\n                path: from_moz(M.source),\n            });\n        },\n        ImportExpression: function(M) {\n            var start = my_start_token(M);\n            var arg = from_moz(M.source);\n            return new AST_Call({\n                start: start,\n                end: my_end_token(M),\n                expression: new AST_SymbolRef({\n                    start: start,\n                    end: arg.start,\n                    name: \"import\",\n                }),\n                args: [ arg ],\n            });\n        },\n        VariableDeclaration: function(M) {\n            return new ({\n                const: AST_Const,\n                let: AST_Let,\n            }[M.kind] || AST_Var)({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                definitions: M.declarations.map(from_moz),\n            });\n        },\n        Literal: function(M) {\n            var args = {\n                start: my_start_token(M),\n                end: my_end_token(M),\n            };\n            if (M.bigint) {\n                args.value = M.bigint.toLowerCase();\n                return new AST_BigInt(args);\n            }\n            var val = M.value;\n            if (val === null) return new AST_Null(args);\n            var rx = M.regex;\n            if (rx && rx.pattern) {\n                // RegExpLiteral as per ESTree AST spec\n                args.value = new RegExp(rx.pattern, rx.flags);\n                args.value.raw_source = rx.pattern;\n                return new AST_RegExp(args);\n            } else if (rx) {\n                // support legacy RegExp\n                args.value = M.regex && M.raw ? M.raw : val;\n                return new AST_RegExp(args);\n            }\n            switch (typeof val) {\n              case \"string\":\n                args.value = val;\n                return new AST_String(args);\n              case \"number\":\n                if (isNaN(val)) return new AST_NaN(args);\n                var negate, node;\n                if (isFinite(val)) {\n                    negate = 1 / val < 0;\n                    args.value = negate ? -val : val;\n                    node = new AST_Number(args);\n                } else {\n                    negate = val < 0;\n                    node = new AST_Infinity(args);\n                }\n                return negate ? new AST_UnaryPrefix({\n                    start: args.start,\n                    end: args.end,\n                    operator: \"-\",\n                    expression: node,\n                }) : node;\n              case \"boolean\":\n                return new (val ? AST_True : AST_False)(args);\n            }\n        },\n        TemplateLiteral: function(M) {\n            return new AST_Template({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                expressions: M.expressions.map(from_moz),\n                strings: M.quasis.map(function(el) {\n                    return el.value.raw;\n                }),\n            });\n        },\n        TaggedTemplateExpression: function(M) {\n            var tmpl = from_moz(M.quasi);\n            tmpl.start = my_start_token(M);\n            tmpl.end = my_end_token(M);\n            tmpl.tag = from_moz(M.tag);\n            return tmpl;\n        },\n        Identifier: function(M) {\n            var p, level = FROM_MOZ_STACK.length - 1;\n            do {\n                p = FROM_MOZ_STACK[--level];\n            } while (p.type == \"ArrayPattern\"\n                || p.type == \"AssignmentPattern\" && p.left === FROM_MOZ_STACK[level + 1]\n                || p.type == \"ObjectPattern\"\n                || p.type == \"Property\" && p.value === FROM_MOZ_STACK[level + 1]\n                || p.type == \"VariableDeclarator\" && p.id === FROM_MOZ_STACK[level + 1]);\n            var ctor = AST_SymbolRef;\n            switch (p.type) {\n              case \"ArrowFunctionExpression\":\n                if (p.body !== FROM_MOZ_STACK[level + 1]) ctor = AST_SymbolFunarg;\n                break;\n              case \"BreakStatement\":\n              case \"ContinueStatement\":\n                ctor = AST_LabelRef;\n                break;\n              case \"CatchClause\":\n                ctor = AST_SymbolCatch;\n                break;\n              case \"ClassDeclaration\":\n                if (p.id === FROM_MOZ_STACK[level + 1]) ctor = AST_SymbolDefClass;\n                break;\n              case \"ClassExpression\":\n                if (p.id === FROM_MOZ_STACK[level + 1]) ctor = AST_SymbolClass;\n                break;\n              case \"FunctionDeclaration\":\n                ctor = p.id === FROM_MOZ_STACK[level + 1] ? AST_SymbolDefun : AST_SymbolFunarg;\n                break;\n              case \"FunctionExpression\":\n                ctor = p.id === FROM_MOZ_STACK[level + 1] ? AST_SymbolLambda : AST_SymbolFunarg;\n                break;\n              case \"LabeledStatement\":\n                ctor = AST_Label;\n                break;\n              case \"VariableDeclaration\":\n                ctor = {\n                    const: AST_SymbolConst,\n                    let: AST_SymbolLet,\n                }[p.kind] || AST_SymbolVar;\n                break;\n            }\n            return new ctor({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: M.name,\n            });\n        },\n        Super: function(M) {\n            return new AST_Super({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: \"super\",\n            });\n        },\n        ThisExpression: function(M) {\n            return new AST_This({\n                start: my_start_token(M),\n                end: my_end_token(M),\n                name: \"this\",\n            });\n        },\n        ParenthesizedExpression: function(M) {\n            var node = from_moz(M.expression);\n            if (!node.start.parens) node.start.parens = [];\n            node.start.parens.push(my_start_token(M));\n            if (!node.end.parens) node.end.parens = [];\n            node.end.parens.push(my_end_token(M));\n            return node;\n        },\n        ChainExpression: function(M) {\n            var node = from_moz(M.expression);\n            node.terminal = true;\n            return node;\n        },\n    };\n\n    MOZ_TO_ME.UpdateExpression =\n    MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {\n        var prefix = \"prefix\" in M ? M.prefix\n            : M.type == \"UnaryExpression\" ? true : false;\n        return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({\n            start      : my_start_token(M),\n            end        : my_end_token(M),\n            operator   : M.operator,\n            expression : from_moz(M.argument)\n        });\n    };\n\n    map(\"EmptyStatement\", AST_EmptyStatement);\n    map(\"ExpressionStatement\", AST_SimpleStatement, \"expression>body\");\n    map(\"BlockStatement\", AST_BlockStatement, \"body@body\");\n    map(\"IfStatement\", AST_If, \"test>condition, consequent>body, alternate>alternative\");\n    map(\"LabeledStatement\", AST_LabeledStatement, \"label>label, body>body\");\n    map(\"BreakStatement\", AST_Break, \"label>label\");\n    map(\"ContinueStatement\", AST_Continue, \"label>label\");\n    map(\"WithStatement\", AST_With, \"object>expression, body>body\");\n    map(\"SwitchStatement\", AST_Switch, \"discriminant>expression, cases@body\");\n    map(\"ReturnStatement\", AST_Return, \"argument>value\");\n    map(\"ThrowStatement\", AST_Throw, \"argument>value\");\n    map(\"WhileStatement\", AST_While, \"test>condition, body>body\");\n    map(\"DoWhileStatement\", AST_Do, \"test>condition, body>body\");\n    map(\"ForStatement\", AST_For, \"init>init, test>condition, update>step, body>body\");\n    map(\"ForInStatement\", AST_ForIn, \"left>init, right>object, body>body\");\n    map(\"DebuggerStatement\", AST_Debugger);\n    map(\"VariableDeclarator\", AST_VarDef, \"id>name, init>value\");\n    map(\"CatchClause\", AST_Catch, \"param>argname, body%body\");\n\n    map(\"BinaryExpression\", AST_Binary, \"operator=operator, left>left, right>right\");\n    map(\"LogicalExpression\", AST_Binary, \"operator=operator, left>left, right>right\");\n    map(\"AssignmentExpression\", AST_Assign, \"operator=operator, left>left, right>right\");\n    map(\"AssignmentPattern\", AST_DefaultValue, \"left>name, right>value\");\n    map(\"ConditionalExpression\", AST_Conditional, \"test>condition, consequent>consequent, alternate>alternative\");\n    map(\"NewExpression\", AST_New, \"callee>expression, arguments@args, pure=pure\");\n    map(\"SequenceExpression\", AST_Sequence, \"expressions@expressions\");\n    map(\"SpreadElement\", AST_Spread, \"argument>expression\");\n    map(\"ObjectExpression\", AST_Object, \"properties@properties\");\n    map(\"AwaitExpression\", AST_Await, \"argument>expression\");\n    map(\"YieldExpression\", AST_Yield, \"argument>expression, delegate=nested\");\n\n    def_to_moz(AST_Toplevel, function To_Moz_Program(M) {\n        return to_moz_scope(\"Program\", M);\n    });\n\n    def_to_moz(AST_LambdaDefinition, function To_Moz_FunctionDeclaration(M) {\n        var params = M.argnames.map(to_moz);\n        if (M.rest) params.push({\n            type: \"RestElement\",\n            argument: to_moz(M.rest),\n        });\n        return {\n            type: \"FunctionDeclaration\",\n            id: to_moz(M.name),\n            async: is_async(M),\n            generator: is_generator(M),\n            params: params,\n            body: to_moz_scope(\"BlockStatement\", M),\n        };\n    });\n\n    def_to_moz(AST_Lambda, function To_Moz_FunctionExpression(M) {\n        var params = M.argnames.map(to_moz);\n        if (M.rest) params.push({\n            type: \"RestElement\",\n            argument: to_moz(M.rest),\n        });\n        if (is_arrow(M)) return {\n            type: \"ArrowFunctionExpression\",\n            async: is_async(M),\n            params: params,\n            expression: !!M.value,\n            body: M.value ? to_moz(M.value) : to_moz_scope(\"BlockStatement\", M),\n        };\n        return {\n            type: \"FunctionExpression\",\n            id: to_moz(M.name),\n            async: is_async(M),\n            generator: is_generator(M),\n            params: params,\n            body: to_moz_scope(\"BlockStatement\", M),\n        };\n    });\n\n    def_to_moz(AST_Call, function To_Moz_CallExpression(M) {\n        var expr = M.expression;\n        if (M.args.length == 1 && expr instanceof AST_SymbolRef && expr.name == \"import\") return {\n            type: \"ImportExpression\",\n            source: to_moz(M.args[0]),\n        };\n        return {\n            type: \"CallExpression\",\n            callee: to_moz(expr),\n            arguments: M.args.map(to_moz),\n            optional: M.optional,\n            pure: M.pure,\n        };\n    });\n\n    def_to_moz(AST_DefClass, function To_Moz_ClassDeclaration(M) {\n        return {\n            type: \"ClassDeclaration\",\n            id: to_moz(M.name),\n            superClass: to_moz(M.extends),\n            body: {\n                type: \"ClassBody\",\n                body: M.properties.map(to_moz),\n            },\n        };\n    });\n\n    def_to_moz(AST_ClassExpression, function To_Moz_ClassExpression(M) {\n        return {\n            type: \"ClassExpression\",\n            id: to_moz(M.name),\n            superClass: to_moz(M.extends),\n            body: {\n                type: \"ClassBody\",\n                body: M.properties.map(to_moz),\n            },\n        };\n    });\n\n    function To_Moz_MethodDefinition(kind) {\n        return function(M) {\n            var computed = M.key instanceof AST_Node;\n            var key = computed ? to_moz(M.key) : M.private ? {\n                type: \"PrivateIdentifier\",\n                name: M.key.slice(1),\n            } : {\n                type: \"Literal\",\n                value: M.key,\n            };\n            return {\n                type: \"MethodDefinition\",\n                kind: kind,\n                computed: computed,\n                key: key,\n                static: M.static,\n                value: to_moz(M.value),\n            };\n        };\n    }\n    def_to_moz(AST_ClassGetter, To_Moz_MethodDefinition(\"get\"));\n    def_to_moz(AST_ClassSetter, To_Moz_MethodDefinition(\"set\"));\n    def_to_moz(AST_ClassMethod, To_Moz_MethodDefinition(\"method\"));\n\n    def_to_moz(AST_ClassField, function To_Moz_PropertyDefinition(M) {\n        var computed = M.key instanceof AST_Node;\n        var key = computed ? to_moz(M.key) : M.private ? {\n            type: \"PrivateIdentifier\",\n            name: M.key.slice(1),\n        } : {\n            type: \"Literal\",\n            value: M.key,\n        };\n        return {\n            type: \"PropertyDefinition\",\n            computed: computed,\n            key: key,\n            static: M.static,\n            value: to_moz(M.value),\n        };\n    });\n\n    def_to_moz(AST_ClassInit, function To_Moz_StaticBlock(M) {\n        return to_moz_scope(\"StaticBlock\", M.value);\n    });\n\n    function To_Moz_ForOfStatement(is_await) {\n        return function(M) {\n            return {\n                type: \"ForOfStatement\",\n                await: is_await,\n                left: to_moz(M.init),\n                right: to_moz(M.object),\n                body: to_moz(M.body),\n            };\n        };\n    }\n    def_to_moz(AST_ForAwaitOf, To_Moz_ForOfStatement(true));\n    def_to_moz(AST_ForOf, To_Moz_ForOfStatement(false));\n\n    def_to_moz(AST_Directive, function To_Moz_Directive(M) {\n        return {\n            type: \"ExpressionStatement\",\n            directive: M.value,\n            expression: set_moz_loc(M, {\n                type: \"Literal\",\n                value: M.value,\n            }),\n        };\n    });\n\n    def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {\n        return {\n            type: \"SwitchCase\",\n            test: to_moz(M.expression),\n            consequent: M.body.map(to_moz),\n        };\n    });\n\n    def_to_moz(AST_Try, function To_Moz_TryStatement(M) {\n        return {\n            type: \"TryStatement\",\n            block: to_moz_block(M),\n            handler: to_moz(M.bcatch),\n            finalizer: to_moz(M.bfinally),\n        };\n    });\n\n    def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {\n        return {\n            type: \"CatchClause\",\n            param: to_moz(M.argname),\n            body: to_moz_block(M),\n        };\n    });\n\n    def_to_moz(AST_ExportDeclaration, function To_Moz_ExportNamedDeclaration_declaration(M) {\n        return {\n            type: \"ExportNamedDeclaration\",\n            declaration: to_moz(M.body),\n            specifiers: [],\n        };\n    });\n\n    def_to_moz(AST_ExportDefault, function To_Moz_ExportDefaultDeclaration(M) {\n        return {\n            type: \"ExportDefaultDeclaration\",\n            declaration: to_moz(M.body),\n        };\n    });\n\n    def_to_moz(AST_ExportForeign, function To_Moz_ExportAllDeclaration_ExportNamedDeclaration(M) {\n        if (M.keys[0].value == \"*\") return {\n            type: \"ExportAllDeclaration\",\n            exported: M.aliases[0].value == \"*\" ? null : to_moz_alias(M.aliases[0]),\n            source: to_moz(M.path),\n        };\n        var specifiers = [];\n        for (var i = 0; i < M.aliases.length; i++) {\n            specifiers.push(set_moz_loc({\n                start: M.keys[i].start,\n                end: M.aliases[i].end,\n            }, {\n                type: \"ExportSpecifier\",\n                local: to_moz_alias(M.keys[i]),\n                exported: to_moz_alias(M.aliases[i]),\n            }));\n        }\n        return {\n            type: \"ExportNamedDeclaration\",\n            specifiers: specifiers,\n            source: to_moz(M.path),\n        };\n    });\n\n    def_to_moz(AST_ExportReferences, function To_Moz_ExportNamedDeclaration_specifiers(M) {\n        return {\n            type: \"ExportNamedDeclaration\",\n            specifiers: M.properties.map(function(prop) {\n                return set_moz_loc({\n                    start: prop.start,\n                    end: prop.alias.end,\n                }, {\n                    type: \"ExportSpecifier\",\n                    local: to_moz(prop),\n                    exported: to_moz_alias(prop.alias),\n                });\n            }),\n        };\n    });\n\n    def_to_moz(AST_Import, function To_Moz_ImportDeclaration(M) {\n        var specifiers = M.properties ? M.properties.map(function(prop) {\n            return set_moz_loc({\n                start: prop.key.start,\n                end: prop.end,\n            }, {\n                type: \"ImportSpecifier\",\n                local: to_moz(prop),\n                imported: to_moz_alias(prop.key),\n            });\n        }) : [];\n        if (M.all) specifiers.unshift(set_moz_loc(M.all, {\n            type: \"ImportNamespaceSpecifier\",\n            local: to_moz(M.all),\n        }));\n        if (M.default) specifiers.unshift(set_moz_loc(M.default, {\n            type: \"ImportDefaultSpecifier\",\n            local: to_moz(M.default),\n        }));\n        return {\n            type: \"ImportDeclaration\",\n            specifiers: specifiers,\n            source: to_moz(M.path),\n        };\n    });\n\n    def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {\n        return {\n            type: \"VariableDeclaration\",\n            kind: M.TYPE.toLowerCase(),\n            declarations: M.definitions.map(to_moz),\n        };\n    });\n\n    def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {\n        var computed = M instanceof AST_Sub;\n        var expr = {\n            type: \"MemberExpression\",\n            object: to_moz(M.expression),\n            computed: computed,\n            optional: M.optional,\n            property: computed ? to_moz(M.property) : {\n                type: \"Identifier\",\n                name: M.property,\n            },\n        };\n        return M.terminal ? {\n            type: \"ChainExpression\",\n            expression: expr,\n        } : expr;\n    });\n\n    def_to_moz(AST_Unary, function To_Moz_Unary(M) {\n        return {\n            type: M.operator == \"++\" || M.operator == \"--\" ? \"UpdateExpression\" : \"UnaryExpression\",\n            operator: M.operator,\n            prefix: M instanceof AST_UnaryPrefix,\n            argument: to_moz(M.expression)\n        };\n    });\n\n    def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {\n        return {\n            type: M.operator == \"&&\" || M.operator == \"||\" ? \"LogicalExpression\" : \"BinaryExpression\",\n            left: to_moz(M.left),\n            operator: M.operator,\n            right: to_moz(M.right)\n        };\n    });\n\n    def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) {\n        return {\n            type: \"ArrayExpression\",\n            elements: M.elements.map(to_moz),\n        };\n    });\n\n    def_to_moz(AST_DestructuredArray, function To_Moz_ArrayPattern(M) {\n        var elements = M.elements.map(to_moz);\n        if (M.rest) elements.push({\n            type: \"RestElement\",\n            argument: to_moz(M.rest),\n        });\n        return {\n            type: \"ArrayPattern\",\n            elements: elements,\n        };\n    });\n\n    def_to_moz(AST_DestructuredKeyVal, function To_Moz_Property(M) {\n        var computed = M.key instanceof AST_Node;\n        var key = computed ? to_moz(M.key) : {\n            type: \"Literal\",\n            value: M.key,\n        };\n        return {\n            type: \"Property\",\n            kind: \"init\",\n            computed: computed,\n            method: false,\n            shorthand: false,\n            key: key,\n            value: to_moz(M.value),\n        };\n    });\n\n    def_to_moz(AST_DestructuredObject, function To_Moz_ObjectPattern(M) {\n        var props = M.properties.map(to_moz);\n        if (M.rest) props.push({\n            type: \"RestElement\",\n            argument: to_moz(M.rest),\n        });\n        return {\n            type: \"ObjectPattern\",\n            properties: props,\n        };\n    });\n\n    def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {\n        var computed = M.key instanceof AST_Node;\n        var key = computed ? to_moz(M.key) : {\n            type: \"Literal\",\n            value: M.key,\n        };\n        var kind;\n        if (M instanceof AST_ObjectKeyVal) {\n            kind = \"init\";\n        } else if (M instanceof AST_ObjectGetter) {\n            kind = \"get\";\n        } else if (M instanceof AST_ObjectSetter) {\n            kind = \"set\";\n        }\n        return {\n            type: \"Property\",\n            kind: kind,\n            computed: computed,\n            method: M instanceof AST_ObjectMethod,\n            shorthand: false,\n            key: key,\n            value: to_moz(M.value),\n        };\n    });\n\n    def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {\n        var def = M.definition();\n        return {\n            type: \"Identifier\",\n            name: def && def.mangled_name || M.name,\n        };\n    });\n\n    def_to_moz(AST_Super, function To_Moz_Super() {\n        return { type: \"Super\" };\n    });\n\n    def_to_moz(AST_This, function To_Moz_ThisExpression() {\n        return { type: \"ThisExpression\" };\n    });\n\n    def_to_moz(AST_NewTarget, function To_Moz_MetaProperty() {\n        return {\n            type: \"MetaProperty\",\n            meta: {\n                type: \"Identifier\",\n                name: \"new\",\n            },\n            property: {\n                type: \"Identifier\",\n                name: \"target\",\n            },\n        };\n    });\n\n    def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {\n        var flags = M.value.toString().match(/\\/([gimuy]*)$/)[1];\n        var value = \"/\" + M.value.raw_source + \"/\" + flags;\n        return {\n            type: \"Literal\",\n            value: value,\n            raw: value,\n            regex: {\n                pattern: M.value.raw_source,\n                flags: flags,\n            },\n        };\n    });\n\n    def_to_moz(AST_BigInt, function To_Moz_BigInt(M) {\n        var value = M.value;\n        return {\n            type: \"Literal\",\n            bigint: value,\n            raw: value + \"n\",\n        };\n    });\n\n    function To_Moz_Literal(M) {\n        var value = M.value;\n        if (typeof value === \"number\" && (value < 0 || (value === 0 && 1 / value < 0))) {\n            return {\n                type: \"UnaryExpression\",\n                operator: \"-\",\n                prefix: true,\n                argument: {\n                    type: \"Literal\",\n                    value: -value,\n                    raw: M.start.raw,\n                },\n            };\n        }\n        return {\n            type: \"Literal\",\n            value: value,\n            raw: M.start.raw,\n        };\n    }\n    def_to_moz(AST_Boolean, To_Moz_Literal);\n    def_to_moz(AST_Constant, To_Moz_Literal);\n    def_to_moz(AST_Null, To_Moz_Literal);\n\n    def_to_moz(AST_Atom, function To_Moz_Atom(M) {\n        return {\n            type: \"Identifier\",\n            name: String(M.value),\n        };\n    });\n\n    def_to_moz(AST_Template, function To_Moz_TemplateLiteral_TaggedTemplateExpression(M) {\n        var last = M.strings.length - 1;\n        var tmpl = {\n            type: \"TemplateLiteral\",\n            expressions: M.expressions.map(to_moz),\n            quasis: M.strings.map(function(str, index) {\n                return {\n                    type: \"TemplateElement\",\n                    tail: index == last,\n                    value: { raw: str },\n                };\n            }),\n        };\n        if (!M.tag) return tmpl;\n        return {\n            type: \"TaggedTemplateExpression\",\n            tag: to_moz(M.tag),\n            quasi: tmpl,\n        };\n    });\n\n    AST_Block.DEFMETHOD(\"to_mozilla_ast\", AST_BlockStatement.prototype.to_mozilla_ast);\n    AST_Hole.DEFMETHOD(\"to_mozilla_ast\", return_null);\n    AST_Node.DEFMETHOD(\"to_mozilla_ast\", function() {\n        throw new Error(\"Cannot convert AST_\" + this.TYPE);\n    });\n\n    /* -----[ tools ]----- */\n\n    function normalize_directives(body) {\n        for (var i = 0; i < body.length; i++) {\n            var stat = body[i];\n            if (!(stat instanceof AST_SimpleStatement)) break;\n            var node = stat.body;\n            if (!(node instanceof AST_String)) break;\n            if (stat.start.pos !== node.start.pos) break;\n            body[i] = new AST_Directive(node);\n        }\n        return body;\n    }\n\n    function raw_token(moznode) {\n        if (moznode.type == \"Literal\") {\n            return moznode.raw != null ? moznode.raw : moznode.value + \"\";\n        }\n    }\n\n    function my_start_token(moznode) {\n        var loc = moznode.loc, start = loc && loc.start;\n        var range = moznode.range;\n        return new AST_Token({\n            file    : loc && loc.source,\n            line    : start && start.line,\n            col     : start && start.column,\n            pos     : range ? range[0] : moznode.start,\n            endline : start && start.line,\n            endcol  : start && start.column,\n            endpos  : range ? range[0] : moznode.start,\n            raw     : raw_token(moznode),\n        });\n    }\n\n    function my_end_token(moznode) {\n        var loc = moznode.loc, end = loc && loc.end;\n        var range = moznode.range;\n        return new AST_Token({\n            file    : loc && loc.source,\n            line    : end && end.line,\n            col     : end && end.column,\n            pos     : range ? range[1] : moznode.end,\n            endline : end && end.line,\n            endcol  : end && end.column,\n            endpos  : range ? range[1] : moznode.end,\n            raw     : raw_token(moznode),\n        });\n    }\n\n    function read_name(M) {\n        return \"\" + M[M.type == \"Identifier\" ? \"name\" : \"value\"];\n    }\n\n    function map(moztype, mytype, propmap) {\n        var moz_to_me = [\n            \"start: my_start_token(M)\",\n            \"end: my_end_token(M)\",\n        ];\n        var me_to_moz = [\n            \"type: \" + JSON.stringify(moztype),\n        ];\n\n        if (propmap) propmap.split(/\\s*,\\s*/).forEach(function(prop) {\n            var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);\n            if (!m) throw new Error(\"Can't understand property map: \" + prop);\n            var moz = m[1], how = m[2], my = m[3];\n            switch (how) {\n              case \"@\":\n                moz_to_me.push(my + \": M.\" + moz + \".map(from_moz)\");\n                me_to_moz.push(moz + \": M.\" +  my + \".map(to_moz)\");\n                break;\n              case \">\":\n                moz_to_me.push(my + \": from_moz(M.\" + moz + \")\");\n                me_to_moz.push(moz + \": to_moz(M.\" + my + \")\");\n                break;\n              case \"=\":\n                moz_to_me.push(my + \": M.\" + moz);\n                me_to_moz.push(moz + \": M.\" + my);\n                break;\n              case \"%\":\n                moz_to_me.push(my + \": from_moz(M.\" + moz + \").body\");\n                me_to_moz.push(moz + \": to_moz_block(M)\");\n                break;\n              default:\n                throw new Error(\"Can't understand operator in propmap: \" + prop);\n            }\n        });\n\n        MOZ_TO_ME[moztype] = new Function(\"U2\", \"my_start_token\", \"my_end_token\", \"from_moz\", [\n            \"return function From_Moz_\" + moztype + \"(M) {\",\n            \"    return new U2.AST_\" + mytype.TYPE + \"({\",\n            moz_to_me.join(\",\\n\"),\n            \"    });\",\n            \"};\",\n        ].join(\"\\n\"))(exports, my_start_token, my_end_token, from_moz);\n        def_to_moz(mytype, new Function(\"to_moz\", \"to_moz_block\", \"to_moz_scope\", [\n            \"return function To_Moz_\" + moztype + \"(M) {\",\n            \"    return {\",\n            me_to_moz.join(\",\\n\"),\n            \"    };\",\n            \"};\",\n        ].join(\"\\n\"))(to_moz, to_moz_block, to_moz_scope));\n    }\n\n    var FROM_MOZ_STACK = null;\n\n    function from_moz(moz) {\n        FROM_MOZ_STACK.push(moz);\n        var node = null;\n        if (moz) {\n            if (!HOP(MOZ_TO_ME, moz.type)) throw new Error(\"Unsupported type: \" + moz.type);\n            node = MOZ_TO_ME[moz.type](moz);\n        }\n        FROM_MOZ_STACK.pop();\n        return node;\n    }\n\n    function from_moz_alias(moz) {\n        return new AST_String({\n            start: my_start_token(moz),\n            value: read_name(moz),\n            end: my_end_token(moz),\n        });\n    }\n\n    AST_Node.from_mozilla_ast = function(node) {\n        var save_stack = FROM_MOZ_STACK;\n        FROM_MOZ_STACK = [];\n        var ast = from_moz(node);\n        FROM_MOZ_STACK = save_stack;\n        ast.walk(new TreeWalker(function(node) {\n            if (node instanceof AST_LabelRef) {\n                for (var level = 0, parent; parent = this.parent(level); level++) {\n                    if (parent instanceof AST_Scope) break;\n                    if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {\n                        node.thedef = parent.label;\n                        break;\n                    }\n                }\n                if (!node.thedef) {\n                    var s = node.start;\n                    js_error(\"Undefined label \" + node.name, s.file, s.line, s.col, s.pos);\n                }\n            }\n        }));\n        return ast;\n    };\n\n    function set_moz_loc(mynode, moznode) {\n        var start = mynode.start;\n        var end = mynode.end;\n        if (start.pos != null && end.endpos != null) {\n            moznode.range = [start.pos, end.endpos];\n        }\n        if (start.line) {\n            moznode.loc = {\n                start: {line: start.line, column: start.col},\n                end: end.endline ? {line: end.endline, column: end.endcol} : null,\n            };\n            if (start.file) {\n                moznode.loc.source = start.file;\n            }\n        }\n        return moznode;\n    }\n\n    function def_to_moz(mytype, handler) {\n        mytype.DEFMETHOD(\"to_mozilla_ast\", function() {\n            return set_moz_loc(this, handler(this));\n        });\n    }\n\n    function to_moz(node) {\n        return node != null ? node.to_mozilla_ast() : null;\n    }\n\n    function to_moz_alias(alias) {\n        return is_identifier_string(alias.value) ? set_moz_loc(alias, {\n            type: \"Identifier\",\n            name: alias.value,\n        }) : to_moz(alias);\n    }\n\n    function to_moz_block(node) {\n        return {\n            type: \"BlockStatement\",\n            body: node.body.map(to_moz),\n        };\n    }\n\n    function to_moz_scope(type, node) {\n        var body = node.body.map(to_moz);\n        if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) {\n            body.unshift(to_moz(new AST_EmptyStatement(node.body[0])));\n        }\n        return {\n            type: type,\n            body: body,\n        };\n    }\n})();\n"
  },
  {
    "path": "lib/output.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction is_some_comments(comment) {\n    // multiline comment\n    return comment.type == \"comment2\" && /@preserve|@license|@cc_on/i.test(comment.value);\n}\n\nfunction OutputStream(options) {\n    options = defaults(options, {\n        annotations      : false,\n        ascii_only       : false,\n        beautify         : false,\n        braces           : false,\n        comments         : false,\n        extendscript     : false,\n        galio            : false,\n        ie               : false,\n        indent_level     : 4,\n        indent_start     : 0,\n        inline_script    : true,\n        keep_quoted_props: false,\n        max_line_len     : false,\n        module           : false,\n        preamble         : null,\n        preserve_line    : false,\n        quote_keys       : false,\n        quote_style      : 0,\n        semicolons       : true,\n        shebang          : true,\n        source_map       : null,\n        v8               : false,\n        webkit           : false,\n        width            : 80,\n        wrap_iife        : false,\n    }, true);\n\n    // Convert comment option to RegExp if necessary and set up comments filter\n    var comment_filter = return_false; // Default case, throw all comments away\n    if (options.comments) {\n        var comments = options.comments;\n        if (typeof options.comments === \"string\" && /^\\/.*\\/[a-zA-Z]*$/.test(options.comments)) {\n            var regex_pos = options.comments.lastIndexOf(\"/\");\n            comments = new RegExp(\n                options.comments.substr(1, regex_pos - 1),\n                options.comments.substr(regex_pos + 1)\n            );\n        }\n        if (comments instanceof RegExp) {\n            comment_filter = function(comment) {\n                return comment.type != \"comment5\" && comments.test(comment.value);\n            };\n        } else if (typeof comments === \"function\") {\n            comment_filter = function(comment) {\n                return comment.type != \"comment5\" && comments(this, comment);\n            };\n        } else if (comments === \"some\") {\n            comment_filter = is_some_comments;\n        } else { // NOTE includes \"all\" option\n            comment_filter = return_true;\n        }\n    }\n\n    function make_indent(value) {\n        if (typeof value == \"number\") return new Array(value + 1).join(\" \");\n        if (!value) return \"\";\n        if (!/^\\s*$/.test(value)) throw new Error(\"unsupported indentation: \" + JSON.stringify(\"\" + value));\n        return value;\n    }\n\n    var current_col = 0;\n    var current_line = 1;\n    var current_indent = make_indent(options.indent_start);\n    var full_indent = make_indent(options.indent_level);\n    var half_indent = full_indent.length + 1 >> 1;\n    var last;\n    var line_end = 0;\n    var line_fixed = true;\n    var mappings = options.source_map && [];\n    var mapping_name;\n    var mapping_token;\n    var might_need_space;\n    var might_need_semicolon;\n    var need_newline_indented = false;\n    var need_space = false;\n    var output;\n    var stack;\n    var stored = \"\";\n\n    function reset() {\n        last = \"\";\n        might_need_space = false;\n        might_need_semicolon = false;\n        stack = [];\n        var str = output;\n        output = \"\";\n        return str;\n    }\n\n    reset();\n    var to_utf8 = options.ascii_only ? function(str, identifier) {\n        if (identifier || options.module) str = str.replace(/[\\ud800-\\udbff][\\udc00-\\udfff]/g, function(ch) {\n            return \"\\\\u{\" + (ch.charCodeAt(0) - 0xd7c0 << 10 | ch.charCodeAt(1) - 0xdc00).toString(16) + \"}\";\n        });\n        return str.replace(/[\\u0000-\\u001f\\u007f-\\uffff]/g, function(s, i) {\n            var code = s.charCodeAt(0).toString(16);\n            if (code.length <= 2 && !identifier) {\n                switch (s) {\n                  case \"\\n\": return \"\\\\n\";\n                  case \"\\r\": return \"\\\\r\";\n                  case \"\\t\": return \"\\\\t\";\n                  case \"\\b\": return \"\\\\b\";\n                  case \"\\f\": return \"\\\\f\";\n                  case \"\\x0B\": return options.ie ? \"\\\\x0B\" : \"\\\\v\";\n                  case \"\\0\":\n                    return /[0-9]/.test(str.charAt(i+1)) ? \"\\\\x00\" : \"\\\\0\";\n                }\n                while (code.length < 2) code = \"0\" + code;\n                return \"\\\\x\" + code;\n            } else {\n                while (code.length < 4) code = \"0\" + code;\n                return \"\\\\u\" + code;\n            }\n        });\n    } : function(str) {\n        var s = \"\";\n        for (var i = 0, j = 0; i < str.length; i++) {\n            var code = str.charCodeAt(i);\n            if (is_surrogate_pair_head(code)) {\n                if (is_surrogate_pair_tail(str.charCodeAt(i + 1))) {\n                    i++;\n                    continue;\n                }\n            } else if (!is_surrogate_pair_tail(code)) {\n                continue;\n            }\n            s += str.slice(j, i) + \"\\\\u\" + code.toString(16);\n            j = i + 1;\n        }\n        return j == 0 ? str : s + str.slice(j);\n    };\n\n    function quote_single(str) {\n        return \"'\" + str.replace(/\\x27/g, \"\\\\'\") + \"'\";\n    }\n\n    function quote_double(str) {\n        return '\"' + str.replace(/\\x22/g, '\\\\\"') + '\"';\n    }\n\n    var quote_string = [\n        null,\n        quote_single,\n        quote_double,\n        function(str, quote) {\n            return quote == \"'\" ? quote_single(str) : quote_double(str);\n        },\n    ][options.quote_style] || function(str, quote, dq, sq) {\n        return dq > sq ? quote_single(str) : quote_double(str);\n    };\n\n    function make_string(str, quote) {\n        var dq = 0, sq = 0;\n        str = str.replace(/[\\\\\\b\\f\\n\\r\\v\\t\\x22\\x27\\u2028\\u2029\\0\\ufeff]/g, function(s, i) {\n            switch (s) {\n              case '\"': ++dq; return '\"';\n              case \"'\": ++sq; return \"'\";\n              case \"\\\\\": return \"\\\\\\\\\";\n              case \"\\n\": return \"\\\\n\";\n              case \"\\r\": return \"\\\\r\";\n              case \"\\t\": return \"\\\\t\";\n              case \"\\b\": return \"\\\\b\";\n              case \"\\f\": return \"\\\\f\";\n              case \"\\x0B\": return options.ie ? \"\\\\x0B\" : \"\\\\v\";\n              case \"\\u2028\": return \"\\\\u2028\";\n              case \"\\u2029\": return \"\\\\u2029\";\n              case \"\\ufeff\": return \"\\\\ufeff\";\n              case \"\\0\":\n                  return /[0-9]/.test(str.charAt(i+1)) ? \"\\\\x00\" : \"\\\\0\";\n            }\n            return s;\n        });\n        return quote_string(to_utf8(str), quote, dq, sq);\n    }\n\n    /* -----[ beautification/minification ]----- */\n\n    var adjust_mappings = mappings ? function(line, col) {\n        mappings.forEach(function(mapping) {\n            mapping.line += line;\n            mapping.col += col;\n        });\n    } : noop;\n\n    var flush_mappings = mappings ? function() {\n        mappings.forEach(function(mapping) {\n            options.source_map.add(\n                mapping.token.file,\n                mapping.line, mapping.col,\n                mapping.token.line, mapping.token.col,\n                !mapping.name && mapping.token.type == \"name\" ? mapping.token.value : mapping.name\n            );\n        });\n        mappings = [];\n    } : noop;\n\n    function insert_newlines(count) {\n        stored += output.slice(0, line_end);\n        output = output.slice(line_end);\n        var new_col = output.length;\n        adjust_mappings(count, new_col - current_col);\n        current_line += count;\n        current_col = new_col;\n        while (count--) stored += \"\\n\";\n    }\n\n    var fix_line = options.max_line_len ? function(flush) {\n        if (line_fixed) {\n            if (current_col > options.max_line_len) {\n                AST_Node.warn(\"Output exceeds {max_line_len} characters\", options);\n            }\n            return;\n        }\n        if (current_col > options.max_line_len) {\n            insert_newlines(1);\n            line_fixed = true;\n        }\n        if (line_fixed || flush) flush_mappings();\n    } : noop;\n\n    var stat_end_chars = makePredicate(\"; }\");\n    var asi_skip_chars = makePredicate(\"( [ + * / - , . `\");\n    var asi_skip_words = makePredicate(\"in instanceof\");\n\n    function require_space(prev, ch, str) {\n        return is_identifier_char(prev) && (is_identifier_char(ch) || ch == \"\\\\\")\n            || (ch == \"/\" && ch == prev)\n            || ((ch == \"+\" || ch == \"-\") && ch == last)\n            || last == \"--\" && ch == \">\"\n            || last == \"!\" && str == \"--\"\n            || prev == \"/\" && (str == \"in\" || str == \"instanceof\");\n    }\n\n    var print = options.beautify\n        || options.comments\n        || options.max_line_len\n        || options.preserve_line\n        || options.shebang\n        || !options.semicolons\n        || options.source_map\n        || options.width ? function(str) {\n        var ch = str.charAt(0);\n        if (need_newline_indented && ch) {\n            need_newline_indented = false;\n            if (ch != \"\\n\") {\n                print(\"\\n\");\n                indent();\n            }\n        }\n        if (need_space && ch) {\n            need_space = false;\n            if (!/[\\s;})]/.test(ch)) {\n                space();\n            }\n        }\n        var prev = last.slice(-1);\n        if (might_need_semicolon) {\n            might_need_semicolon = false;\n            if (prev != \";\" && !stat_end_chars[ch]) {\n                var need_semicolon = asi_skip_chars[ch] || asi_skip_words[str];\n                if (need_semicolon || options.semicolons) {\n                    output += \";\";\n                    current_col++;\n                    if (!line_fixed) {\n                        fix_line();\n                        if (line_fixed && !need_semicolon && output == \";\") {\n                            output = \"\";\n                            current_col = 0;\n                        }\n                    }\n                    if (line_end == output.length - 1) line_end++;\n                } else {\n                    fix_line();\n                    output += \"\\n\";\n                    current_line++;\n                    current_col = 0;\n                    // reset the semicolon flag, since we didn't print one\n                    // now and might still have to later\n                    if (/^\\s+$/.test(str)) might_need_semicolon = true;\n                }\n                if (!options.beautify) might_need_space = false;\n            }\n        }\n\n        if (might_need_space) {\n            if (require_space(prev, ch, str)) {\n                output += \" \";\n                current_col++;\n            }\n            if (prev != \"<\" || str != \"!\") might_need_space = false;\n        }\n\n        if (mapping_token) {\n            mappings.push({\n                token: mapping_token,\n                name: mapping_name,\n                line: current_line,\n                col: current_col,\n            });\n            mapping_token = false;\n            if (line_fixed) flush_mappings();\n        }\n\n        output += str;\n        var a = str.split(/\\r?\\n/), n = a.length - 1;\n        current_line += n;\n        current_col += a[0].length;\n        if (n > 0) {\n            fix_line();\n            current_col = a[n].length;\n        }\n        last = str;\n    } : function(str) {\n        var ch = str.charAt(0);\n        var prev = last.slice(-1);\n        if (might_need_semicolon) {\n            might_need_semicolon = false;\n            if (prev == \":\" && ch == \"}\" || (!ch || \";}\".indexOf(ch) < 0) && prev != \";\") {\n                output += \";\";\n                might_need_space = false;\n            }\n        }\n        if (might_need_space) {\n            if (require_space(prev, ch, str)) output += \" \";\n            if (prev != \"<\" || str != \"!\") might_need_space = false;\n        }\n        output += str;\n        last = str;\n    };\n\n    var space = options.beautify ? function() {\n        print(\" \");\n    } : function() {\n        might_need_space = true;\n    };\n\n    var indent = options.beautify ? function(half) {\n        if (need_newline_indented) print(\"\\n\");\n        print(half ? current_indent.slice(0, -half_indent) : current_indent);\n    } : noop;\n\n    var with_indent = options.beautify ? function(cont) {\n        var save_indentation = current_indent;\n        current_indent += full_indent;\n        cont();\n        current_indent = save_indentation;\n    } : function(cont) { cont() };\n\n    var may_add_newline = options.max_line_len || options.preserve_line ? function() {\n        fix_line();\n        line_end = output.length;\n        line_fixed = false;\n    } : noop;\n\n    var newline = options.beautify ? function() {\n        print(\"\\n\");\n        line_end = output.length;\n    } : may_add_newline;\n\n    var semicolon = options.beautify ? function() {\n        print(\";\");\n    } : function() {\n        might_need_semicolon = true;\n    };\n\n    function force_semicolon() {\n        if (might_need_semicolon) print(\";\");\n        print(\";\");\n    }\n\n    function with_block(cont, end) {\n        print(\"{\");\n        newline();\n        with_indent(cont);\n        add_mapping(end);\n        indent();\n        print(\"}\");\n    }\n\n    function with_parens(cont) {\n        print(\"(\");\n        may_add_newline();\n        cont();\n        may_add_newline();\n        print(\")\");\n    }\n\n    function with_square(cont) {\n        print(\"[\");\n        may_add_newline();\n        cont();\n        may_add_newline();\n        print(\"]\");\n    }\n\n    function comma() {\n        may_add_newline();\n        print(\",\");\n        may_add_newline();\n        space();\n    }\n\n    function colon() {\n        print(\":\");\n        space();\n    }\n\n    var add_mapping = mappings ? function(token, name) {\n        mapping_token = token;\n        mapping_name = name;\n    } : noop;\n\n    function get() {\n        if (!line_fixed) fix_line(true);\n        return stored + output;\n    }\n\n    function has_nlb() {\n        return /(^|\\n) *$/.test(output);\n    }\n\n    function pad_comment(token, force) {\n        if (need_newline_indented) return;\n        if (token.nlb && (force || !has_nlb())) {\n            need_newline_indented = true;\n        } else if (force) {\n            need_space = true;\n        }\n    }\n\n    function print_comment(comment) {\n        var value = comment.value.replace(/[@#]__PURE__/g, \" \");\n        if (/^\\s*$/.test(value) && !/^\\s*$/.test(comment.value)) return false;\n        if (/comment[134]/.test(comment.type)) {\n            print(\"//\" + value);\n            need_newline_indented = true;\n        } else if (comment.type == \"comment2\") {\n            print(\"/*\" + value + \"*/\");\n        }\n        return true;\n    }\n\n    function should_merge_comments(node, parent) {\n        if (parent instanceof AST_Binary) return parent.left === node;\n        if (parent.TYPE == \"Call\") return parent.expression === node;\n        if (parent instanceof AST_Conditional) return parent.condition === node;\n        if (parent instanceof AST_Dot) return parent.expression === node;\n        if (parent instanceof AST_Exit) return true;\n        if (parent instanceof AST_Sequence) return parent.expressions[0] === node;\n        if (parent instanceof AST_Sub) return parent.expression === node;\n        if (parent instanceof AST_UnaryPostfix) return true;\n        if (parent instanceof AST_Yield) return true;\n    }\n\n    function prepend_comments(node) {\n        var self = this;\n        var scan;\n        if (node instanceof AST_Exit) {\n            scan = node.value;\n        } else if (node instanceof AST_Yield) {\n            scan = node.expression;\n        }\n        var comments = dump(node);\n        if (!comments) comments = [];\n\n        if (scan) {\n            var tw = new TreeWalker(function(node) {\n                if (!should_merge_comments(node, tw.parent())) return true;\n                var before = dump(node);\n                if (before) comments = comments.concat(before);\n            });\n            tw.push(node);\n            scan.walk(tw);\n        }\n\n        if (current_line == 1 && current_col == 0) {\n            if (comments.length > 0 && options.shebang && comments[0].type == \"comment5\") {\n                print(\"#!\" + comments.shift().value + \"\\n\");\n                indent();\n            }\n            var preamble = options.preamble;\n            if (preamble) print(preamble.replace(/\\r\\n?|\\u2028|\\u2029|(^|\\S)\\s*$/g, \"$1\\n\"));\n        }\n\n        comments = comments.filter(comment_filter, node);\n        var printed = false;\n        comments.forEach(function(comment, index) {\n            pad_comment(comment, index);\n            if (print_comment(comment)) printed = true;\n        });\n        if (printed) pad_comment(node.start, true);\n\n        function dump(node) {\n            var token = node.start;\n            if (!token) {\n                if (!scan) return;\n                node.start = token = new AST_Token();\n            }\n            var comments = token.comments_before;\n            if (!comments) {\n                if (!scan) return;\n                token.comments_before = comments = [];\n            }\n            if (comments._dumped === self) return;\n            comments._dumped = self;\n            return comments;\n        }\n    }\n\n    function append_comments(node, tail) {\n        var self = this;\n        var token = node.end;\n        if (!token) return;\n        var comments = token[tail ? \"comments_before\" : \"comments_after\"];\n        if (!comments || comments._dumped === self) return;\n        if (!(node instanceof AST_Statement || all(comments, function(c) {\n            return !/comment[134]/.test(c.type);\n        }))) return;\n        comments._dumped = self;\n        comments.filter(comment_filter, node).forEach(function(comment, index) {\n            pad_comment(comment, index || !tail);\n            print_comment(comment);\n        });\n    }\n\n    return {\n        get             : get,\n        reset           : reset,\n        indent          : indent,\n        should_break    : options.beautify && options.width ? function() {\n            return current_col >= options.width;\n        } : return_false,\n        has_parens      : function() { return last.slice(-1) == \"(\" },\n        newline         : newline,\n        print           : print,\n        space           : space,\n        comma           : comma,\n        colon           : colon,\n        last            : function() { return last },\n        semicolon       : semicolon,\n        force_semicolon : force_semicolon,\n        to_utf8         : to_utf8,\n        print_name      : function(name) { print(to_utf8(name.toString(), true)) },\n        print_string    : options.inline_script ? function(str, quote) {\n            str = make_string(str, quote).replace(/<\\x2f(script)([>\\/\\t\\n\\f\\r ])/gi, \"<\\\\/$1$2\");\n            print(str.replace(/\\x3c!--/g, \"\\\\x3c!--\").replace(/--\\x3e/g, \"--\\\\x3e\"));\n        } : function(str, quote) {\n            print(make_string(str, quote));\n        },\n        with_indent     : with_indent,\n        with_block      : with_block,\n        with_parens     : with_parens,\n        with_square     : with_square,\n        add_mapping     : add_mapping,\n        option          : function(opt) { return options[opt] },\n        prepend_comments: options.comments || options.shebang ? prepend_comments : noop,\n        append_comments : options.comments ? append_comments : noop,\n        push_node       : function(node) { stack.push(node) },\n        pop_node        : options.preserve_line ? function() {\n            var node = stack.pop();\n            if (node.start && node.start.line > current_line) {\n                insert_newlines(node.start.line - current_line);\n            }\n        } : function() {\n            stack.pop();\n        },\n        parent          : function(n) {\n            return stack[stack.length - 2 - (n || 0)];\n        },\n    };\n}\n\n/* -----[ code generators ]----- */\n\n(function() {\n\n    /* -----[ utils ]----- */\n\n    function DEFPRINT(nodetype, generator) {\n        nodetype.DEFMETHOD(\"_codegen\", generator);\n    }\n\n    var use_asm = false;\n\n    AST_Node.DEFMETHOD(\"print\", function(stream, force_parens) {\n        var self = this;\n        stream.push_node(self);\n        if (force_parens || self.needs_parens(stream)) {\n            stream.with_parens(doit);\n        } else {\n            doit();\n        }\n        stream.pop_node();\n\n        function doit() {\n            stream.prepend_comments(self);\n            self.add_source_map(stream);\n            self._codegen(stream);\n            stream.append_comments(self);\n        }\n    });\n    var readonly = OutputStream({\n        inline_script: false,\n        shebang: false,\n        width: false,\n    });\n    AST_Node.DEFMETHOD(\"print_to_string\", function(options) {\n        if (options) {\n            var stream = OutputStream(options);\n            this.print(stream);\n            return stream.get();\n        }\n        this.print(readonly);\n        return readonly.reset();\n    });\n\n    /* -----[ PARENTHESES ]----- */\n\n    function PARENS(nodetype, func) {\n        nodetype.DEFMETHOD(\"needs_parens\", func);\n    }\n\n    PARENS(AST_Node, return_false);\n\n    // a function expression needs parens around it when it's provably\n    // the first token to appear in a statement.\n    function needs_parens_function(output) {\n        var p = output.parent();\n        if (!output.has_parens() && first_in_statement(output, false, true)) {\n            // export default function() {}\n            // export default (function foo() {});\n            // export default (function() {})(foo);\n            // export default (function() {})`foo`;\n            // export default (function() {}) ? foo : bar;\n            return this.name || !(p instanceof AST_ExportDefault);\n        }\n        if (output.option(\"webkit\") && p instanceof AST_PropAccess && p.expression === this) return true;\n        if (output.option(\"wrap_iife\") && p instanceof AST_Call && p.expression === this) return true;\n    }\n    PARENS(AST_AsyncFunction, needs_parens_function);\n    PARENS(AST_AsyncGeneratorFunction, needs_parens_function);\n    PARENS(AST_ClassExpression, needs_parens_function);\n    PARENS(AST_Function, needs_parens_function);\n    PARENS(AST_GeneratorFunction, needs_parens_function);\n\n    // same goes for an object literal, because otherwise it would be\n    // interpreted as a block of code.\n    function needs_parens_obj(output) {\n        return !output.has_parens() && first_in_statement(output, true);\n    }\n    PARENS(AST_Object, needs_parens_obj);\n\n    function needs_parens_unary(output) {\n        var p = output.parent();\n        // (-x) ** y\n        if (p instanceof AST_Binary) return p.operator == \"**\" && p.left === this;\n        // (await x)(y)\n        // new (await x)\n        if (p instanceof AST_Call) return p.expression === this;\n        // class extends (x++) {}\n        // class x extends (typeof y) {}\n        if (p instanceof AST_Class) return true;\n        // (x++)[y]\n        // (typeof x).y\n        // https://github.com/mishoo/UglifyJS/issues/115\n        if (p instanceof AST_PropAccess) return p.expression === this;\n        // (~x)`foo`\n        if (p instanceof AST_Template) return p.tag === this;\n    }\n    PARENS(AST_Await, needs_parens_unary);\n    PARENS(AST_Unary, needs_parens_unary);\n\n    PARENS(AST_Sequence, function(output) {\n        var p = output.parent();\n            // [ 1, (2, 3), 4 ] ---> [ 1, 3, 4 ]\n        return p instanceof AST_Array\n            // () ---> (foo, bar)\n            || is_arrow(p) && p.value === this\n            // await (foo, bar)\n            || p instanceof AST_Await\n            // 1 + (2, 3) + 4 ---> 8\n            || p instanceof AST_Binary\n            // new (foo, bar) or foo(1, (2, 3), 4)\n            || p instanceof AST_Call\n            // class extends (foo, bar) {}\n            // class foo extends (bar, baz) {}\n            || p instanceof AST_Class\n            // class { foo = (bar, baz) }\n            // class { [(foo, bar)]() {} }\n            || p instanceof AST_ClassProperty\n            // (false, true) ? (a = 10, b = 20) : (c = 30)\n            // ---> 20 (side effect, set a := 10 and b := 20)\n            || p instanceof AST_Conditional\n            // [ a = (1, 2) ] = [] ---> a == 2\n            || p instanceof AST_DefaultValue\n            // { [(1, 2)]: foo } = bar\n            // { 1: (2, foo) } = bar\n            || p instanceof AST_DestructuredKeyVal\n            // export default (foo, bar)\n            || p instanceof AST_ExportDefault\n            // for (foo of (bar, baz));\n            || p instanceof AST_ForOf\n            // { [(1, 2)]: 3 }[2] ---> 3\n            // { foo: (1, 2) }.foo ---> 2\n            || p instanceof AST_ObjectProperty\n            // (1, {foo:2}).foo or (1, {foo:2})[\"foo\"] ---> 2\n            || p instanceof AST_PropAccess && p.expression === this\n            // ...(foo, bar, baz)\n            || p instanceof AST_Spread\n            // (foo, bar)`baz`\n            || p instanceof AST_Template && p.tag === this\n            // !(foo, bar, baz)\n            || p instanceof AST_Unary\n            // var a = (1, 2), b = a + a; ---> b == 4\n            || p instanceof AST_VarDef\n            // yield (foo, bar)\n            || p instanceof AST_Yield;\n    });\n\n    PARENS(AST_Binary, function(output) {\n        var p = output.parent();\n        // await (foo && bar)\n        if (p instanceof AST_Await) return true;\n        // this deals with precedence:\n        //   3 * (2 + 1)\n        //   3 - (2 - 1)\n        //   (1 ** 2) ** 3\n        if (p instanceof AST_Binary) {\n            var po = p.operator, pp = PRECEDENCE[po];\n            var so = this.operator, sp = PRECEDENCE[so];\n            return pp > sp\n                || po == \"??\" && (so == \"&&\" || so == \"||\")\n                || (pp == sp && this === p[po == \"**\" ? \"left\" : \"right\"]);\n        }\n        // (foo && bar)()\n        if (p instanceof AST_Call) return p.expression === this;\n        // class extends (foo && bar) {}\n        // class foo extends (bar || null) {}\n        if (p instanceof AST_Class) return true;\n        // (foo && bar)[\"prop\"], (foo && bar).prop\n        if (p instanceof AST_PropAccess) return p.expression === this;\n        // (foo && bar)``\n        if (p instanceof AST_Template) return p.tag === this;\n        // typeof (foo && bar)\n        if (p instanceof AST_Unary) return true;\n    });\n\n    function need_chain_parens(node, parent) {\n        if (!node.terminal) return false;\n        if (!(parent instanceof AST_Call || parent instanceof AST_PropAccess)) return false;\n        return parent.expression === node;\n    }\n\n    PARENS(AST_PropAccess, function(output) {\n        var node = this;\n        var p = output.parent();\n        // i.e. new (foo().bar)\n        //\n        // if there's one call into this subtree, then we need\n        // parens around it too, otherwise the call will be\n        // interpreted as passing the arguments to the upper New\n        // expression.\n        if (p instanceof AST_New && p.expression === node && root_expr(node).TYPE == \"Call\") return true;\n        // (foo?.bar)()\n        // (foo?.bar).baz\n        // new (foo?.bar)()\n        return need_chain_parens(node, p);\n    });\n\n    PARENS(AST_Call, function(output) {\n        var node = this;\n        var p = output.parent();\n        if (p instanceof AST_New) return p.expression === node;\n        // https://bugs.webkit.org/show_bug.cgi?id=123506\n        if (output.option(\"webkit\")\n            && node.expression instanceof AST_Function\n            && p instanceof AST_PropAccess\n            && p.expression === node) {\n            var g = output.parent(1);\n            if (g instanceof AST_Assign && g.left === p) return true;\n        }\n        // (foo?.())()\n        // (foo?.()).bar\n        // new (foo?.())()\n        return need_chain_parens(node, p);\n    });\n\n    PARENS(AST_New, function(output) {\n        if (need_constructor_parens(this, output)) return false;\n        var p = output.parent();\n        // (new foo)(bar)\n        if (p instanceof AST_Call) return p.expression === this;\n        // (new Date).getTime(), (new Date)[\"getTime\"]()\n        if (p instanceof AST_PropAccess) return true;\n        // (new foo)`bar`\n        if (p instanceof AST_Template) return p.tag === this;\n    });\n\n    PARENS(AST_Number, function(output) {\n        if (!output.option(\"galio\")) return false;\n        // https://github.com/mishoo/UglifyJS/pull/1009\n        var p = output.parent();\n        return p instanceof AST_PropAccess && p.expression === this && /^0/.test(make_num(this.value));\n    });\n\n    function needs_parens_assign_cond(self, output) {\n        var p = output.parent();\n        // await (a = foo)\n        if (p instanceof AST_Await) return true;\n        // 1 + (a = 2) + 3 → 6, side effect setting a = 2\n        if (p instanceof AST_Binary) return !(p instanceof AST_Assign);\n        // (a = func)() —or— new (a = Object)()\n        if (p instanceof AST_Call) return p.expression === self;\n        // class extends (a = foo) {}\n        // class foo extends (bar ? baz : moo) {}\n        if (p instanceof AST_Class) return true;\n        // (a = foo) ? bar : baz\n        if (p instanceof AST_Conditional) return p.condition === self;\n        // (a = foo)[\"prop\"] —or— (a = foo).prop\n        if (p instanceof AST_PropAccess) return p.expression === self;\n        // (a = foo)`bar`\n        if (p instanceof AST_Template) return p.tag === self;\n        // !(a = false) → true\n        if (p instanceof AST_Unary) return true;\n    }\n    PARENS(AST_Arrow, function(output) {\n        return needs_parens_assign_cond(this, output);\n    });\n    PARENS(AST_Assign, function(output) {\n        if (needs_parens_assign_cond(this, output)) return true;\n        //  v8 parser bug   --->     workaround\n        // f([1], [a] = []) ---> f([1], ([a] = []))\n        if (output.option(\"v8\")) return this.left instanceof AST_Destructured;\n        // ({ p: a } = o);\n        if (this.left instanceof AST_DestructuredObject) return needs_parens_obj(output);\n    });\n    PARENS(AST_AsyncArrow, function(output) {\n        return needs_parens_assign_cond(this, output);\n    });\n    PARENS(AST_Conditional, function(output) {\n        return needs_parens_assign_cond(this, output)\n            // https://github.com/mishoo/UglifyJS/issues/1144\n            || output.option(\"extendscript\") && output.parent() instanceof AST_Conditional;\n    });\n    PARENS(AST_Yield, function(output) {\n        return needs_parens_assign_cond(this, output);\n    });\n\n    /* -----[ PRINTERS ]----- */\n\n    DEFPRINT(AST_Directive, function(output) {\n        var quote = this.quote;\n        var value = this.value;\n        switch (output.option(\"quote_style\")) {\n          case 0:\n          case 2:\n            if (value.indexOf('\"') == -1) quote = '\"';\n            break;\n          case 1:\n            if (value.indexOf(\"'\") == -1) quote = \"'\";\n            break;\n        }\n        output.print(quote + value + quote);\n        output.semicolon();\n    });\n    DEFPRINT(AST_Debugger, function(output) {\n        output.print(\"debugger\");\n        output.semicolon();\n    });\n\n    /* -----[ statements ]----- */\n\n    function display_body(body, is_toplevel, output, allow_directives) {\n        var last = body.length - 1;\n        var in_directive = allow_directives;\n        var was_asm = use_asm;\n        body.forEach(function(stmt, i) {\n            if (in_directive) {\n                if (stmt instanceof AST_Directive) {\n                    if (stmt.value == \"use asm\") use_asm = true;\n                } else if (!(stmt instanceof AST_EmptyStatement)) {\n                    if (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) {\n                        output.force_semicolon();\n                    }\n                    in_directive = false;\n                }\n            }\n            if (stmt instanceof AST_EmptyStatement) return;\n            output.indent();\n            stmt.print(output);\n            if (i == last && is_toplevel) return;\n            output.newline();\n            if (is_toplevel) output.newline();\n        });\n        use_asm = was_asm;\n    }\n\n    DEFPRINT(AST_Toplevel, function(output) {\n        display_body(this.body, true, output, true);\n        output.print(\"\");\n    });\n    DEFPRINT(AST_LabeledStatement, function(output) {\n        this.label.print(output);\n        output.colon();\n        var body = this.body;\n        if (body instanceof AST_EmptyStatement) {\n            output.force_semicolon();\n        } else {\n            body.print(output);\n        }\n    });\n    DEFPRINT(AST_SimpleStatement, function(output) {\n        this.body.print(output);\n        output.semicolon();\n    });\n    function print_braced_empty(self, output) {\n        output.print(\"{\");\n        output.with_indent(function() {\n            output.append_comments(self, true);\n        });\n        output.print(\"}\");\n    }\n    function print_braced(self, output, allow_directives) {\n        if (self.body.length > 0) {\n            output.with_block(function() {\n                display_body(self.body, false, output, allow_directives);\n            }, self.end);\n        } else print_braced_empty(self, output);\n    }\n    DEFPRINT(AST_BlockStatement, function(output) {\n        print_braced(this, output);\n    });\n    DEFPRINT(AST_EmptyStatement, function(output) {\n        output.semicolon();\n    });\n    DEFPRINT(AST_Do, function(output) {\n        var self = this;\n        output.print(\"do\");\n        make_block(self.body, output);\n        output.space();\n        output.print(\"while\");\n        output.space();\n        output.with_parens(function() {\n            self.condition.print(output);\n        });\n        output.semicolon();\n    });\n    DEFPRINT(AST_While, function(output) {\n        var self = this;\n        output.print(\"while\");\n        output.space();\n        output.with_parens(function() {\n            self.condition.print(output);\n        });\n        force_statement(self.body, output);\n    });\n    DEFPRINT(AST_For, function(output) {\n        var self = this;\n        output.print(\"for\");\n        output.space();\n        output.with_parens(function() {\n            if (self.init) {\n                if (self.init instanceof AST_Definitions) {\n                    self.init.print(output);\n                } else {\n                    parenthesize_for_no_in(self.init, output, true);\n                }\n                output.print(\";\");\n                output.space();\n            } else {\n                output.print(\";\");\n            }\n            if (self.condition) {\n                self.condition.print(output);\n                output.print(\";\");\n                output.space();\n            } else {\n                output.print(\";\");\n            }\n            if (self.step) {\n                self.step.print(output);\n            }\n        });\n        force_statement(self.body, output);\n    });\n    function print_for_enum(prefix, infix) {\n        return function(output) {\n            var self = this;\n            output.print(prefix);\n            output.space();\n            output.with_parens(function() {\n                self.init.print(output);\n                output.space();\n                output.print(infix);\n                output.space();\n                self.object.print(output);\n            });\n            force_statement(self.body, output);\n        };\n    }\n    DEFPRINT(AST_ForAwaitOf, print_for_enum(\"for await\", \"of\"));\n    DEFPRINT(AST_ForIn, print_for_enum(\"for\", \"in\"));\n    DEFPRINT(AST_ForOf, print_for_enum(\"for\", \"of\"));\n    DEFPRINT(AST_With, function(output) {\n        var self = this;\n        output.print(\"with\");\n        output.space();\n        output.with_parens(function() {\n            self.expression.print(output);\n        });\n        force_statement(self.body, output);\n    });\n    DEFPRINT(AST_ExportDeclaration, function(output) {\n        output.print(\"export\");\n        output.space();\n        this.body.print(output);\n    });\n    DEFPRINT(AST_ExportDefault, function(output) {\n        output.print(\"export\");\n        output.space();\n        output.print(\"default\");\n        output.space();\n        var body = this.body;\n        body.print(output);\n        if (body instanceof AST_ClassExpression) {\n            if (!body.name) return;\n        }\n        if (body instanceof AST_DefClass) return;\n        if (body instanceof AST_LambdaDefinition) return;\n        if (body instanceof AST_LambdaExpression) {\n            if (!body.name && !is_arrow(body)) return;\n        }\n        output.semicolon();\n    });\n    function print_alias(alias, output) {\n        var value = alias.value;\n        if (value == \"*\" || is_identifier_string(value)) {\n            output.print_name(value);\n        } else {\n            output.print_string(value, alias.quote);\n        }\n    }\n    DEFPRINT(AST_ExportForeign, function(output) {\n        var self = this;\n        output.print(\"export\");\n        output.space();\n        var len = self.keys.length;\n        if (len == 0) {\n            print_braced_empty(self, output);\n        } else if (self.keys[0].value == \"*\") {\n            print_entry(0);\n        } else output.with_block(function() {\n            output.indent();\n            print_entry(0);\n            for (var i = 1; i < len; i++) {\n                output.print(\",\");\n                output.newline();\n                output.indent();\n                print_entry(i);\n            }\n            output.newline();\n        }, self.end);\n        output.space();\n        output.print(\"from\");\n        output.space();\n        self.path.print(output);\n        output.semicolon();\n\n        function print_entry(index) {\n            var alias = self.aliases[index];\n            var key = self.keys[index];\n            print_alias(key, output);\n            if (alias.value != key.value) {\n                output.space();\n                output.print(\"as\");\n                output.space();\n                print_alias(alias, output);\n            }\n        }\n    });\n    DEFPRINT(AST_ExportReferences, function(output) {\n        var self = this;\n        output.print(\"export\");\n        output.space();\n        print_properties(self, output);\n        output.semicolon();\n    });\n    DEFPRINT(AST_Import, function(output) {\n        var self = this;\n        output.print(\"import\");\n        output.space();\n        if (self.default) self.default.print(output);\n        if (self.all) {\n            if (self.default) output.comma();\n            self.all.print(output);\n        }\n        if (self.properties) {\n            if (self.default) output.comma();\n            print_properties(self, output);\n        }\n        if (self.all || self.default || self.properties) {\n            output.space();\n            output.print(\"from\");\n            output.space();\n        }\n        self.path.print(output);\n        output.semicolon();\n    });\n\n    /* -----[ functions ]----- */\n    function print_funargs(self, output) {\n        output.with_parens(function() {\n            self.argnames.forEach(function(arg, i) {\n                if (i) output.comma();\n                arg.print(output);\n            });\n            if (self.rest) {\n                if (self.argnames.length) output.comma();\n                output.print(\"...\");\n                self.rest.print(output);\n            }\n        });\n    }\n    function print_arrow(self, output) {\n        var argname = self.argnames.length == 1 && !self.rest && self.argnames[0];\n        if (argname instanceof AST_SymbolFunarg && argname.name != \"yield\") {\n            argname.print(output);\n        } else {\n            print_funargs(self, output);\n        }\n        output.space();\n        output.print(\"=>\");\n        output.space();\n        if (self.value) {\n            self.value.print(output);\n        } else {\n            print_braced(self, output, true);\n        }\n    }\n    DEFPRINT(AST_Arrow, function(output) {\n        print_arrow(this, output);\n    });\n    DEFPRINT(AST_AsyncArrow, function(output) {\n        output.print(\"async\");\n        output.space();\n        print_arrow(this, output);\n    });\n    function print_lambda(self, output) {\n        if (self.name) {\n            output.space();\n            self.name.print(output);\n        }\n        print_funargs(self, output);\n        output.space();\n        print_braced(self, output, true);\n    }\n    DEFPRINT(AST_Lambda, function(output) {\n        output.print(\"function\");\n        print_lambda(this, output);\n    });\n    function print_async(output) {\n        output.print(\"async\");\n        output.space();\n        output.print(\"function\");\n        print_lambda(this, output);\n    }\n    DEFPRINT(AST_AsyncDefun, print_async);\n    DEFPRINT(AST_AsyncFunction, print_async);\n    function print_async_generator(output) {\n        output.print(\"async\");\n        output.space();\n        output.print(\"function*\");\n        print_lambda(this, output);\n    }\n    DEFPRINT(AST_AsyncGeneratorDefun, print_async_generator);\n    DEFPRINT(AST_AsyncGeneratorFunction, print_async_generator);\n    function print_generator(output) {\n        output.print(\"function*\");\n        print_lambda(this, output);\n    }\n    DEFPRINT(AST_GeneratorDefun, print_generator);\n    DEFPRINT(AST_GeneratorFunction, print_generator);\n\n    /* -----[ classes ]----- */\n    DEFPRINT(AST_Class, function(output) {\n        var self = this;\n        output.print(\"class\");\n        if (self.name) {\n            output.space();\n            self.name.print(output);\n        }\n        if (self.extends) {\n            output.space();\n            output.print(\"extends\");\n            output.space();\n            self.extends.print(output);\n        }\n        output.space();\n        print_properties(self, output, true);\n    });\n    DEFPRINT(AST_ClassField, function(output) {\n        var self = this;\n        if (self.static) {\n            output.print(\"static\");\n            output.space();\n        }\n        print_property_key(self, output);\n        if (self.value) {\n            output.space();\n            output.print(\"=\");\n            output.space();\n            self.value.print(output);\n        } else switch (self.key) {\n          case \"get\":\n          case \"set\":\n          case \"static\":\n            output.force_semicolon();\n            return;\n        }\n        output.semicolon();\n    });\n    DEFPRINT(AST_ClassGetter, print_accessor(\"get\"));\n    DEFPRINT(AST_ClassSetter, print_accessor(\"set\"));\n    function print_method(self, output) {\n        var fn = self.value;\n        if (is_async(fn)) {\n            output.print(\"async\");\n            output.space();\n        }\n        if (is_generator(fn)) output.print(\"*\");\n        print_property_key(self, output);\n        print_lambda(self.value, output);\n    }\n    DEFPRINT(AST_ClassMethod, function(output) {\n        var self = this;\n        if (self.static) {\n            output.print(\"static\");\n            output.space();\n        }\n        print_method(self, output);\n    });\n    DEFPRINT(AST_ClassInit, function(output) {\n        output.print(\"static\");\n        output.space();\n        print_braced(this.value, output);\n    });\n\n    /* -----[ jumps ]----- */\n    function print_jump(kind, prop) {\n        return function(output) {\n            output.print(kind);\n            var target = this[prop];\n            if (target) {\n                output.space();\n                target.print(output);\n            }\n            output.semicolon();\n        };\n    }\n    DEFPRINT(AST_Return, print_jump(\"return\", \"value\"));\n    DEFPRINT(AST_Throw, print_jump(\"throw\", \"value\"));\n    DEFPRINT(AST_Break, print_jump(\"break\", \"label\"));\n    DEFPRINT(AST_Continue, print_jump(\"continue\", \"label\"));\n\n    /* -----[ if ]----- */\n    function make_then(self, output) {\n        var b = self.body;\n        if (output.option(\"braces\") && !(b instanceof AST_Const || b instanceof AST_Let)\n            || output.option(\"ie\") && b instanceof AST_Do)\n            return make_block(b, output);\n        // The squeezer replaces \"block\"-s that contain only a single\n        // statement with the statement itself; technically, the AST\n        // is correct, but this can create problems when we output an\n        // IF having an ELSE clause where the THEN clause ends in an\n        // IF *without* an ELSE block (then the outer ELSE would refer\n        // to the inner IF).  This function checks for this case and\n        // adds the block braces if needed.\n        if (!b) return output.force_semicolon();\n        while (true) {\n            if (b instanceof AST_If) {\n                if (!b.alternative) {\n                    make_block(self.body, output);\n                    return;\n                }\n                b = b.alternative;\n            } else if (b instanceof AST_StatementWithBody) {\n                b = b.body;\n            } else break;\n        }\n        force_statement(self.body, output);\n    }\n    DEFPRINT(AST_If, function(output) {\n        var self = this;\n        output.print(\"if\");\n        output.space();\n        output.with_parens(function() {\n            self.condition.print(output);\n        });\n        if (self.alternative) {\n            make_then(self, output);\n            output.space();\n            output.print(\"else\");\n            if (self.alternative instanceof AST_If) {\n                output.space();\n                self.alternative.print(output);\n            } else {\n                force_statement(self.alternative, output);\n            }\n        } else {\n            force_statement(self.body, output);\n        }\n    });\n\n    /* -----[ switch ]----- */\n    DEFPRINT(AST_Switch, function(output) {\n        var self = this;\n        output.print(\"switch\");\n        output.space();\n        output.with_parens(function() {\n            self.expression.print(output);\n        });\n        output.space();\n        var last = self.body.length - 1;\n        if (last < 0) print_braced_empty(self, output);\n        else output.with_block(function() {\n            self.body.forEach(function(branch, i) {\n                output.indent(true);\n                branch.print(output);\n                if (i < last && branch.body.length > 0)\n                    output.newline();\n            });\n        }, self.end);\n    });\n    function print_branch_body(self, output) {\n        output.newline();\n        self.body.forEach(function(stmt) {\n            output.indent();\n            stmt.print(output);\n            output.newline();\n        });\n    }\n    DEFPRINT(AST_Default, function(output) {\n        output.print(\"default:\");\n        print_branch_body(this, output);\n    });\n    DEFPRINT(AST_Case, function(output) {\n        var self = this;\n        output.print(\"case\");\n        output.space();\n        self.expression.print(output);\n        output.print(\":\");\n        print_branch_body(self, output);\n    });\n\n    /* -----[ exceptions ]----- */\n    DEFPRINT(AST_Try, function(output) {\n        var self = this;\n        output.print(\"try\");\n        output.space();\n        print_braced(self, output);\n        if (self.bcatch) {\n            output.space();\n            self.bcatch.print(output);\n        }\n        if (self.bfinally) {\n            output.space();\n            self.bfinally.print(output);\n        }\n    });\n    DEFPRINT(AST_Catch, function(output) {\n        var self = this;\n        output.print(\"catch\");\n        if (self.argname) {\n            output.space();\n            output.with_parens(function() {\n                self.argname.print(output);\n            });\n        }\n        output.space();\n        print_braced(self, output);\n    });\n    DEFPRINT(AST_Finally, function(output) {\n        output.print(\"finally\");\n        output.space();\n        print_braced(this, output);\n    });\n\n    function print_definitions(type) {\n        return function(output) {\n            var self = this;\n            output.print(type);\n            output.space();\n            self.definitions.forEach(function(def, i) {\n                if (i) output.comma();\n                def.print(output);\n            });\n            var p = output.parent();\n            if (!(p instanceof AST_IterationStatement && p.init === self)) output.semicolon();\n        };\n    }\n    DEFPRINT(AST_Const, print_definitions(\"const\"));\n    DEFPRINT(AST_Let, print_definitions(\"let\"));\n    DEFPRINT(AST_Var, print_definitions(\"var\"));\n\n    function parenthesize_for_no_in(node, output, no_in) {\n        var parens = false;\n        // need to take some precautions here:\n        //    https://github.com/mishoo/UglifyJS/issues/60\n        if (no_in) node.walk(new TreeWalker(function(node) {\n            if (parens) return true;\n            if (node instanceof AST_Binary && node.operator == \"in\") return parens = true;\n            if (node instanceof AST_Scope && !(is_arrow(node) && node.value)) return true;\n        }));\n        node.print(output, parens);\n    }\n\n    DEFPRINT(AST_VarDef, function(output) {\n        var self = this;\n        self.name.print(output);\n        if (self.value) {\n            output.space();\n            output.print(\"=\");\n            output.space();\n            var p = output.parent(1);\n            var no_in = p instanceof AST_For || p instanceof AST_ForEnumeration;\n            parenthesize_for_no_in(self.value, output, no_in);\n        }\n    });\n\n    DEFPRINT(AST_DefaultValue, function(output) {\n        var self = this;\n        self.name.print(output);\n        output.space();\n        output.print(\"=\");\n        output.space();\n        self.value.print(output);\n    });\n\n    /* -----[ other expressions ]----- */\n    function print_annotation(self, output) {\n        if (!output.option(\"annotations\")) return;\n        if (!self.pure) return;\n        var level = 0, parent = self, node;\n        do {\n            node = parent;\n            parent = output.parent(level++);\n            if (parent instanceof AST_Call && parent.expression === node) return;\n        } while (parent instanceof AST_PropAccess && parent.expression === node);\n        output.print(\"/*@__PURE__*/\");\n    }\n    function print_call_args(self, output) {\n        output.with_parens(function() {\n            self.args.forEach(function(expr, i) {\n                if (i) output.comma();\n                expr.print(output);\n            });\n            output.add_mapping(self.end);\n        });\n    }\n    DEFPRINT(AST_Call, function(output) {\n        var self = this;\n        print_annotation(self, output);\n        self.expression.print(output);\n        if (self.optional) output.print(\"?.\");\n        print_call_args(self, output);\n    });\n    DEFPRINT(AST_New, function(output) {\n        var self = this;\n        print_annotation(self, output);\n        output.print(\"new\");\n        output.space();\n        self.expression.print(output);\n        if (need_constructor_parens(self, output)) print_call_args(self, output);\n    });\n    DEFPRINT(AST_Sequence, function(output) {\n        this.expressions.forEach(function(node, index) {\n            if (index > 0) {\n                output.comma();\n                if (output.should_break()) {\n                    output.newline();\n                    output.indent();\n                }\n            }\n            node.print(output);\n        });\n    });\n    DEFPRINT(AST_Dot, function(output) {\n        var self = this;\n        var expr = self.expression;\n        expr.print(output);\n        var prop = self.property;\n        if (output.option(\"ie\") && RESERVED_WORDS[prop] || self.quoted && output.option(\"keep_quoted_props\")) {\n            if (self.optional) output.print(\"?.\");\n            output.with_square(function() {\n                output.add_mapping(self.end);\n                output.print_string(prop);\n            });\n        } else {\n            if (expr instanceof AST_Number && !/[ex.)]/i.test(output.last())) output.print(\".\");\n            output.print(self.optional ? \"?.\" : \".\");\n            // the name after dot would be mapped about here.\n            output.add_mapping(self.end);\n            output.print_name(prop);\n        }\n    });\n    DEFPRINT(AST_Sub, function(output) {\n        var self = this;\n        self.expression.print(output);\n        if (self.optional) output.print(\"?.\");\n        output.with_square(function() {\n            self.property.print(output);\n        });\n    });\n    DEFPRINT(AST_Spread, function(output) {\n        output.print(\"...\");\n        this.expression.print(output);\n    });\n    DEFPRINT(AST_UnaryPrefix, function(output) {\n        var op = this.operator;\n        var exp = this.expression;\n        output.print(op);\n        if (/^[a-z]/i.test(op)\n            || (/[+-]$/.test(op)\n                && exp instanceof AST_UnaryPrefix\n                && /^[+-]/.test(exp.operator))) {\n            output.space();\n        }\n        exp.print(output);\n    });\n    DEFPRINT(AST_UnaryPostfix, function(output) {\n        var self = this;\n        self.expression.print(output);\n        output.add_mapping(self.end);\n        output.print(self.operator);\n    });\n    DEFPRINT(AST_Binary, function(output) {\n        var self = this;\n        self.left.print(output);\n        output.space();\n        output.print(self.operator);\n        output.space();\n        self.right.print(output);\n    });\n    DEFPRINT(AST_Conditional, function(output) {\n        var self = this;\n        self.condition.print(output);\n        output.space();\n        output.print(\"?\");\n        output.space();\n        self.consequent.print(output);\n        output.space();\n        output.colon();\n        self.alternative.print(output);\n    });\n    DEFPRINT(AST_Await, function(output) {\n        output.print(\"await\");\n        output.space();\n        this.expression.print(output);\n    });\n    DEFPRINT(AST_Yield, function(output) {\n        output.print(this.nested ? \"yield*\" : \"yield\");\n        if (this.expression) {\n            output.space();\n            this.expression.print(output);\n        }\n    });\n\n    /* -----[ literals ]----- */\n    DEFPRINT(AST_Array, function(output) {\n        var a = this.elements, len = a.length;\n        output.with_square(len > 0 ? function() {\n            output.space();\n            a.forEach(function(exp, i) {\n                if (i) output.comma();\n                exp.print(output);\n                // If the final element is a hole, we need to make sure it\n                // doesn't look like a trailing comma, by inserting an actual\n                // trailing comma.\n                if (i === len - 1 && exp instanceof AST_Hole)\n                  output.comma();\n            });\n            output.space();\n        } : noop);\n    });\n    DEFPRINT(AST_DestructuredArray, function(output) {\n        var a = this.elements, len = a.length, rest = this.rest;\n        output.with_square(len || rest ? function() {\n            output.space();\n            a.forEach(function(exp, i) {\n                if (i) output.comma();\n                exp.print(output);\n            });\n            if (rest) {\n                if (len) output.comma();\n                output.print(\"...\");\n                rest.print(output);\n            } else if (a[len - 1] instanceof AST_Hole) {\n                // If the final element is a hole, we need to make sure it\n                // doesn't look like a trailing comma, by inserting an actual\n                // trailing comma.\n                output.comma();\n            }\n            output.space();\n        } : noop);\n    });\n    DEFPRINT(AST_DestructuredKeyVal, function(output) {\n        var self = this;\n        var key = print_property_key(self, output);\n        var value = self.value;\n        if (key) {\n            if (value instanceof AST_DefaultValue) {\n                if (value.name instanceof AST_Symbol && key == get_symbol_name(value.name)) {\n                    output.space();\n                    output.print(\"=\");\n                    output.space();\n                    value.value.print(output);\n                    return;\n                }\n            } else if (value instanceof AST_Symbol) {\n                if (key == get_symbol_name(value)) return;\n            }\n        }\n        output.colon();\n        value.print(output);\n    });\n    DEFPRINT(AST_DestructuredObject, function(output) {\n        var self = this;\n        var props = self.properties, len = props.length, rest = self.rest;\n        if (len || rest) output.with_block(function() {\n            props.forEach(function(prop, i) {\n                if (i) {\n                    output.print(\",\");\n                    output.newline();\n                }\n                output.indent();\n                prop.print(output);\n            });\n            if (rest) {\n                if (len) {\n                    output.print(\",\");\n                    output.newline();\n                }\n                output.indent();\n                output.print(\"...\");\n                rest.print(output);\n            }\n            output.newline();\n        }, self.end);\n        else print_braced_empty(self, output);\n    });\n    function print_properties(self, output, no_comma) {\n        var props = self.properties;\n        if (props.length > 0) output.with_block(function() {\n            props.forEach(function(prop, i) {\n                if (i) {\n                    if (!no_comma) output.print(\",\");\n                    output.newline();\n                }\n                output.indent();\n                prop.print(output);\n            });\n            output.newline();\n        }, self.end);\n        else print_braced_empty(self, output);\n    }\n    DEFPRINT(AST_Object, function(output) {\n        print_properties(this, output);\n    });\n\n    function print_property_key(self, output) {\n        var key = self.key;\n        if (key instanceof AST_Node) return output.with_square(function() {\n            key.print(output);\n        });\n        var quote = self.start && self.start.quote;\n        if (output.option(\"quote_keys\") || quote && output.option(\"keep_quoted_props\")) {\n            output.print_string(key, quote);\n        } else if (\"\" + +key == key && key >= 0) {\n            output.print(make_num(key));\n        } else if (self.private) {\n            output.print_name(key);\n        } else if (RESERVED_WORDS[key] ? !output.option(\"ie\") : is_identifier_string(key)) {\n            output.print_name(key);\n            return key;\n        } else {\n            output.print_string(key, quote);\n        }\n    }\n    DEFPRINT(AST_ObjectKeyVal, function(output) {\n        var self = this;\n        print_property_key(self, output);\n        output.colon();\n        self.value.print(output);\n    });\n    DEFPRINT(AST_ObjectMethod, function(output) {\n        print_method(this, output);\n    });\n    function print_accessor(type) {\n        return function(output) {\n            var self = this;\n            if (self.static) {\n                output.print(\"static\");\n                output.space();\n            }\n            output.print(type);\n            output.space();\n            print_property_key(self, output);\n            print_lambda(self.value, output);\n        };\n    }\n    DEFPRINT(AST_ObjectGetter, print_accessor(\"get\"));\n    DEFPRINT(AST_ObjectSetter, print_accessor(\"set\"));\n    function get_symbol_name(sym) {\n        var def = sym.definition();\n        return def && def.mangled_name || sym.name;\n    }\n    DEFPRINT(AST_Symbol, function(output) {\n        output.print_name(get_symbol_name(this));\n    });\n    DEFPRINT(AST_SymbolExport, function(output) {\n        var self = this;\n        var name = get_symbol_name(self);\n        output.print_name(name);\n        var alias = self.alias;\n        if (alias.value != name) {\n            output.space();\n            output.print(\"as\");\n            output.space();\n            print_alias(alias, output);\n        }\n    });\n    DEFPRINT(AST_SymbolImport, function(output) {\n        var self = this;\n        var name = get_symbol_name(self);\n        var key = self.key;\n        if (key.value && key.value != name) {\n            print_alias(key, output);\n            output.space();\n            output.print(\"as\");\n            output.space();\n        }\n        output.print_name(name);\n    });\n    DEFPRINT(AST_Hole, noop);\n    DEFPRINT(AST_Template, function(output) {\n        var self = this;\n        if (self.tag) self.tag.print(output);\n        output.print(\"`\");\n        for (var i = 0; i < self.expressions.length; i++) {\n            output.print(output.to_utf8(self.strings[i]));\n            output.print(\"${\");\n            self.expressions[i].print(output);\n            output.print(\"}\");\n        }\n        output.print(output.to_utf8(self.strings[i]));\n        output.print(\"`\");\n    });\n    DEFPRINT(AST_BigInt, function(output) {\n        output.print(this.value + \"n\");\n    });\n    DEFPRINT(AST_Constant, function(output) {\n        output.print(\"\" + this.value);\n    });\n    DEFPRINT(AST_String, function(output) {\n        output.print_string(this.value, this.quote);\n    });\n    DEFPRINT(AST_Number, function(output) {\n        var start = this.start;\n        if (use_asm && start && start.raw != null) {\n            output.print(start.raw);\n        } else {\n            output.print(make_num(this.value));\n        }\n    });\n\n    DEFPRINT(AST_RegExp, function(output) {\n        var regexp = this.value;\n        var str = regexp.toString();\n        var end = str.lastIndexOf(\"/\");\n        if (regexp.raw_source) {\n            str = \"/\" + regexp.raw_source + str.slice(end);\n        } else if (end == 1) {\n            str = \"/(?:)\" + str.slice(end);\n        } else if (str.indexOf(\"/\", 1) < end) {\n            str = \"/\" + str.slice(1, end).replace(/\\\\\\\\|[^/]?\\//g, function(match) {\n                return match[0] == \"\\\\\" ? match : match.slice(0, -1) + \"\\\\/\";\n            }) + str.slice(end);\n        }\n        output.print(output.to_utf8(str).replace(/\\\\(?:\\0(?![0-9])|[^\\0])/g, function(match) {\n            switch (match[1]) {\n              case \"\\n\": return \"\\\\n\";\n              case \"\\r\": return \"\\\\r\";\n              case \"\\t\": return \"\\t\";\n              case \"\\b\": return \"\\b\";\n              case \"\\f\": return \"\\f\";\n              case \"\\0\": return \"\\0\";\n              case \"\\x0B\": return \"\\v\";\n              case \"\\u2028\": return \"\\\\u2028\";\n              case \"\\u2029\": return \"\\\\u2029\";\n              default: return match;\n            }\n        }).replace(/[\\n\\r\\u2028\\u2029]/g, function(c) {\n            switch (c) {\n              case \"\\n\": return \"\\\\n\";\n              case \"\\r\": return \"\\\\r\";\n              case \"\\u2028\": return \"\\\\u2028\";\n              case \"\\u2029\": return \"\\\\u2029\";\n            }\n        }));\n    });\n\n    function force_statement(stat, output) {\n        if (output.option(\"braces\") && !(stat instanceof AST_Const || stat instanceof AST_Let)) {\n            make_block(stat, output);\n        } else if (stat instanceof AST_EmptyStatement) {\n            output.force_semicolon();\n        } else {\n            output.space();\n            stat.print(output);\n        }\n    }\n\n    // self should be AST_New.  decide if we want to show parens or not.\n    function need_constructor_parens(self, output) {\n        // Always print parentheses with arguments\n        if (self.args.length > 0) return true;\n\n        return output.option(\"beautify\");\n    }\n\n    function best_of(a) {\n        var best = a[0], len = best.length;\n        for (var i = 1; i < a.length; ++i) {\n            if (a[i].length < len) {\n                best = a[i];\n                len = best.length;\n            }\n        }\n        return best;\n    }\n\n    function make_num(num) {\n        var str = num.toString(10).replace(/^0\\./, \".\").replace(\"e+\", \"e\");\n        var candidates = [ str ];\n        if (Math.floor(num) === num) {\n            if (num < 0) {\n                candidates.push(\"-0x\" + (-num).toString(16).toLowerCase());\n            } else {\n                candidates.push(\"0x\" + num.toString(16).toLowerCase());\n            }\n        }\n        var match, len, digits;\n        if (match = /^\\.0+/.exec(str)) {\n            len = match[0].length;\n            digits = str.slice(len);\n            candidates.push(digits + \"e-\" + (digits.length + len - 1));\n        } else if (match = /[^0]0+$/.exec(str)) {\n            len = match[0].length - 1;\n            candidates.push(str.slice(0, -len) + \"e\" + len);\n        } else if (match = /^(\\d)\\.(\\d+)e(-?\\d+)$/.exec(str)) {\n            candidates.push(match[1] + match[2] + \"e\" + (match[3] - match[2].length));\n        }\n        return best_of(candidates);\n    }\n\n    function make_block(stmt, output) {\n        output.space();\n        if (stmt instanceof AST_EmptyStatement) {\n            print_braced_empty(stmt, output);\n        } else if (stmt instanceof AST_BlockStatement) {\n            stmt.print(output);\n        } else output.with_block(function() {\n            output.indent();\n            stmt.print(output);\n            output.newline();\n        }, stmt.end);\n    }\n\n    /* -----[ source map generators ]----- */\n\n    function DEFMAP(nodetype, generator) {\n        nodetype.forEach(function(nodetype) {\n            nodetype.DEFMETHOD(\"add_source_map\", generator);\n        });\n    }\n\n    DEFMAP([\n        // We could easily add info for ALL nodes, but it seems to me that\n        // would be quite wasteful, hence this noop in the base class.\n        AST_Node,\n        // since the label symbol will mark it\n        AST_LabeledStatement,\n    ], noop);\n\n    // XXX: I'm not exactly sure if we need it for all of these nodes,\n    // or if we should add even more.\n    DEFMAP([\n        AST_Array,\n        AST_Await,\n        AST_BlockStatement,\n        AST_Catch,\n        AST_Constant,\n        AST_Debugger,\n        AST_Definitions,\n        AST_Destructured,\n        AST_Directive,\n        AST_Finally,\n        AST_Jump,\n        AST_Lambda,\n        AST_New,\n        AST_Object,\n        AST_Spread,\n        AST_StatementWithBody,\n        AST_Symbol,\n        AST_Switch,\n        AST_SwitchBranch,\n        AST_Try,\n        AST_UnaryPrefix,\n        AST_Yield,\n    ], function(output) {\n        output.add_mapping(this.start);\n    });\n\n    DEFMAP([\n        AST_ClassProperty,\n        AST_DestructuredKeyVal,\n        AST_ObjectProperty,\n    ], function(output) {\n        if (typeof this.key == \"string\") output.add_mapping(this.start, this.key);\n    });\n})();\n"
  },
  {
    "path": "lib/parse.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n    Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nvar KEYWORDS = \"break case catch class const continue debugger default delete do else extends finally for function if in instanceof new return switch throw try typeof var void while with\";\nvar KEYWORDS_ATOM = \"false null true\";\nvar RESERVED_WORDS = [\n    \"abstract async await boolean byte char double enum export final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield\",\n    KEYWORDS_ATOM,\n    KEYWORDS,\n].join(\" \");\nvar KEYWORDS_BEFORE_EXPRESSION = \"return new delete throw else case\";\n\nKEYWORDS = makePredicate(KEYWORDS);\nRESERVED_WORDS = makePredicate(RESERVED_WORDS);\nKEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);\nKEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);\n\nvar RE_BIN_NUMBER = /^0b([01]+)$/i;\nvar RE_HEX_NUMBER = /^0x([0-9a-f]+)$/i;\nvar RE_OCT_NUMBER = /^0o?([0-7]+)$/i;\n\nvar OPERATORS = makePredicate([\n    \"in\",\n    \"instanceof\",\n    \"typeof\",\n    \"new\",\n    \"void\",\n    \"delete\",\n    \"++\",\n    \"--\",\n    \"+\",\n    \"-\",\n    \"!\",\n    \"~\",\n    \"&\",\n    \"|\",\n    \"^\",\n    \"*\",\n    \"/\",\n    \"%\",\n    \"**\",\n    \">>\",\n    \"<<\",\n    \">>>\",\n    \"<\",\n    \">\",\n    \"<=\",\n    \">=\",\n    \"==\",\n    \"===\",\n    \"!=\",\n    \"!==\",\n    \"?\",\n    \"=\",\n    \"+=\",\n    \"-=\",\n    \"/=\",\n    \"*=\",\n    \"%=\",\n    \"**=\",\n    \">>=\",\n    \"<<=\",\n    \">>>=\",\n    \"&=\",\n    \"|=\",\n    \"^=\",\n    \"&&\",\n    \"||\",\n    \"??\",\n    \"&&=\",\n    \"||=\",\n    \"??=\",\n]);\n\nvar NEWLINE_CHARS = \"\\n\\r\\u2028\\u2029\";\nvar OPERATOR_CHARS = \"+-*&%=<>!?|~^\";\nvar PUNC_OPENERS = \"[{(\";\nvar PUNC_SEPARATORS = \",;:\";\nvar PUNC_CLOSERS = \")}]\";\nvar PUNC_AFTER_EXPRESSION = PUNC_SEPARATORS + PUNC_CLOSERS;\nvar PUNC_BEFORE_EXPRESSION = PUNC_OPENERS + PUNC_SEPARATORS;\nvar PUNC_CHARS = PUNC_BEFORE_EXPRESSION + \"`\" + PUNC_CLOSERS;\nvar WHITESPACE_CHARS = NEWLINE_CHARS + \" \\u00a0\\t\\f\\u000b\\u200b\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\uFEFF\";\nvar NON_IDENTIFIER_CHARS = makePredicate(characters(\"./'\\\"#\" + OPERATOR_CHARS + PUNC_CHARS + WHITESPACE_CHARS));\n\nNEWLINE_CHARS = makePredicate(characters(NEWLINE_CHARS));\nOPERATOR_CHARS = makePredicate(characters(OPERATOR_CHARS));\nPUNC_AFTER_EXPRESSION = makePredicate(characters(PUNC_AFTER_EXPRESSION));\nPUNC_BEFORE_EXPRESSION = makePredicate(characters(PUNC_BEFORE_EXPRESSION));\nPUNC_CHARS = makePredicate(characters(PUNC_CHARS));\nWHITESPACE_CHARS = makePredicate(characters(WHITESPACE_CHARS));\n\n/* -----[ Tokenizer ]----- */\n\nfunction is_surrogate_pair_head(code) {\n    return code >= 0xd800 && code <= 0xdbff;\n}\n\nfunction is_surrogate_pair_tail(code) {\n    return code >= 0xdc00 && code <= 0xdfff;\n}\n\nfunction is_digit(code) {\n    return code >= 48 && code <= 57;\n}\n\nfunction is_identifier_char(ch) {\n    return !NON_IDENTIFIER_CHARS[ch];\n}\n\nfunction is_identifier_string(str) {\n    return /^[a-z_$][a-z0-9_$]*$/i.test(str);\n}\n\nfunction decode_escape_sequence(seq) {\n    switch (seq[0]) {\n      case \"b\": return \"\\b\";\n      case \"f\": return \"\\f\";\n      case \"n\": return \"\\n\";\n      case \"r\": return \"\\r\";\n      case \"t\": return \"\\t\";\n      case \"u\":\n        var code;\n        if (seq[1] == \"{\" && seq.slice(-1) == \"}\") {\n            code = seq.slice(2, -1);\n        } else if (seq.length == 5) {\n            code = seq.slice(1);\n        } else {\n            return;\n        }\n        var num = parseInt(code, 16);\n        if (num < 0 || isNaN(num)) return;\n        if (num < 0x10000) return String.fromCharCode(num);\n        if (num > 0x10ffff) return;\n        return String.fromCharCode((num >> 10) + 0xd7c0) + String.fromCharCode((num & 0x03ff) + 0xdc00);\n      case \"v\": return \"\\u000b\";\n      case \"x\":\n        if (seq.length != 3) return;\n        var num = parseInt(seq.slice(1), 16);\n        if (num < 0 || isNaN(num)) return;\n        return String.fromCharCode(num);\n      case \"\\r\":\n      case \"\\n\":\n        return \"\";\n      default:\n        if (seq == \"0\") return \"\\0\";\n        if (seq[0] >= \"0\" && seq[0] <= \"9\") return;\n        return seq;\n    }\n}\n\nfunction parse_js_number(num) {\n    var match;\n    if (match = RE_BIN_NUMBER.exec(num)) return parseInt(match[1], 2);\n    if (match = RE_HEX_NUMBER.exec(num)) return parseInt(match[1], 16);\n    if (match = RE_OCT_NUMBER.exec(num)) return parseInt(match[1], 8);\n    var val = parseFloat(num);\n    if (val == num) return val;\n}\n\nfunction JS_Parse_Error(message, filename, line, col, pos) {\n    this.message = message;\n    this.filename = filename;\n    this.line = line;\n    this.col = col;\n    this.pos = pos;\n    try {\n        throw new SyntaxError(message, filename, line, col);\n    } catch (cause) {\n        configure_error_stack(this, cause);\n    }\n}\nJS_Parse_Error.prototype = Object.create(SyntaxError.prototype);\nJS_Parse_Error.prototype.constructor = JS_Parse_Error;\n\nfunction js_error(message, filename, line, col, pos) {\n    throw new JS_Parse_Error(message, filename, line, col, pos);\n}\n\nfunction is_token(token, type, val) {\n    return token.type == type && (val == null || token.value == val);\n}\n\nvar EX_EOF = {};\n\nfunction tokenizer($TEXT, filename, html5_comments, shebang) {\n\n    var S = {\n        text            : $TEXT,\n        filename        : filename,\n        pos             : 0,\n        tokpos          : 0,\n        line            : 1,\n        tokline         : 0,\n        col             : 0,\n        tokcol          : 0,\n        newline_before  : false,\n        regex_allowed   : false,\n        comments_before : [],\n        directives      : Object.create(null),\n        read_template   : with_eof_error(\"Unterminated template literal\", function(strings) {\n            var s = \"\";\n            for (;;) {\n                var ch = read();\n                switch (ch) {\n                  case \"\\\\\":\n                    ch += read();\n                    break;\n                  case \"`\":\n                    strings.push(s);\n                    return;\n                  case \"$\":\n                    if (peek() == \"{\") {\n                        next();\n                        strings.push(s);\n                        S.regex_allowed = true;\n                        return true;\n                    }\n                }\n                s += ch;\n            }\n\n            function read() {\n                var ch = next(true, true);\n                return ch == \"\\r\" ? \"\\n\" : ch;\n            }\n        }),\n    };\n    var prev_was_dot = false;\n\n    function peek() {\n        return S.text.charAt(S.pos);\n    }\n\n    function next(signal_eof, in_string) {\n        var ch = S.text.charAt(S.pos++);\n        if (signal_eof && !ch)\n            throw EX_EOF;\n        if (NEWLINE_CHARS[ch]) {\n            S.col = 0;\n            S.line++;\n            if (!in_string) S.newline_before = true;\n            if (ch == \"\\r\" && peek() == \"\\n\") {\n                // treat `\\r\\n` as `\\n`\n                S.pos++;\n                ch = \"\\n\";\n            }\n        } else {\n            S.col++;\n        }\n        return ch;\n    }\n\n    function forward(i) {\n        while (i-- > 0) next();\n    }\n\n    function looking_at(str) {\n        return S.text.substr(S.pos, str.length) == str;\n    }\n\n    function find_eol() {\n        var text = S.text;\n        for (var i = S.pos; i < S.text.length; ++i) {\n            if (NEWLINE_CHARS[text[i]]) return i;\n        }\n        return -1;\n    }\n\n    function find(what, signal_eof) {\n        var pos = S.text.indexOf(what, S.pos);\n        if (signal_eof && pos == -1) throw EX_EOF;\n        return pos;\n    }\n\n    function start_token() {\n        S.tokline = S.line;\n        S.tokcol = S.col;\n        S.tokpos = S.pos;\n    }\n\n    function token(type, value, is_comment) {\n        S.regex_allowed = type == \"operator\" && !UNARY_POSTFIX[value]\n            || type == \"keyword\" && KEYWORDS_BEFORE_EXPRESSION[value]\n            || type == \"punc\" && PUNC_BEFORE_EXPRESSION[value];\n        if (type == \"punc\" && value == \".\") prev_was_dot = true;\n        else if (!is_comment) prev_was_dot = false;\n        var ret = {\n            type    : type,\n            value   : value,\n            line    : S.tokline,\n            col     : S.tokcol,\n            pos     : S.tokpos,\n            endline : S.line,\n            endcol  : S.col,\n            endpos  : S.pos,\n            nlb     : S.newline_before,\n            file    : filename\n        };\n        if (/^(?:num|string|regexp)$/i.test(type)) {\n            ret.raw = $TEXT.substring(ret.pos, ret.endpos);\n        }\n        if (!is_comment) {\n            ret.comments_before = S.comments_before;\n            ret.comments_after = S.comments_before = [];\n        }\n        S.newline_before = false;\n        return new AST_Token(ret);\n    }\n\n    function skip_whitespace() {\n        while (WHITESPACE_CHARS[peek()])\n            next();\n    }\n\n    function read_while(pred) {\n        var ret = \"\", ch;\n        while ((ch = peek()) && pred(ch, ret)) ret += next();\n        return ret;\n    }\n\n    function parse_error(err) {\n        js_error(err, filename, S.tokline, S.tokcol, S.tokpos);\n    }\n\n    function is_octal(num) {\n        return /^0[0-7_]+$/.test(num);\n    }\n\n    function read_num(prefix) {\n        var has_e = false, after_e = false, has_x = false, has_dot = prefix == \".\";\n        var num = read_while(function(ch, str) {\n            switch (ch) {\n              case \"x\": case \"X\":\n                return has_x ? false : (has_x = true);\n              case \"e\": case \"E\":\n                return has_x ? true : has_e ? false : (has_e = after_e = true);\n              case \"+\": case \"-\":\n                return after_e;\n              case (after_e = false, \".\"):\n                return has_dot || has_e || has_x || is_octal(str) ? false : (has_dot = true);\n            }\n            return /[_0-9a-dfo]/i.test(ch);\n        });\n        if (prefix) num = prefix + num;\n        if (is_octal(num)) {\n            if (next_token.has_directive(\"use strict\")) parse_error(\"Legacy octal literals are not allowed in strict mode\");\n        } else {\n            num = num.replace(has_x ? /([1-9a-f]|.0)_(?=[0-9a-f])/gi : /([1-9]|.0)_(?=[0-9])/gi, \"$1\");\n        }\n        var valid = parse_js_number(num);\n        if (isNaN(valid)) parse_error(\"Invalid syntax: \" + num);\n        if (has_dot || has_e || peek() != \"n\") return token(\"num\", valid);\n        next();\n        return token(\"bigint\", num.toLowerCase());\n    }\n\n    function read_escaped_char(in_string) {\n        var seq = next(true, in_string);\n        if (seq >= \"0\" && seq <= \"7\") return read_octal_escape_sequence(seq);\n        if (seq == \"u\") {\n            var ch = next(true, in_string);\n            seq += ch;\n            if (ch != \"{\") {\n                seq += next(true, in_string) + next(true, in_string) + next(true, in_string);\n            } else do {\n                ch = next(true, in_string);\n                seq += ch;\n            } while (ch != \"}\");\n        } else if (seq == \"x\") {\n            seq += next(true, in_string) + next(true, in_string);\n        }\n        var str = decode_escape_sequence(seq);\n        if (typeof str != \"string\") parse_error(\"Invalid escape sequence: \\\\\" + seq);\n        return str;\n    }\n\n    function read_octal_escape_sequence(ch) {\n        // Read\n        var p = peek();\n        if (p >= \"0\" && p <= \"7\") {\n            ch += next(true);\n            if (ch[0] <= \"3\" && (p = peek()) >= \"0\" && p <= \"7\")\n                ch += next(true);\n        }\n\n        // Parse\n        if (ch === \"0\") return \"\\0\";\n        if (ch.length > 0 && next_token.has_directive(\"use strict\"))\n            parse_error(\"Legacy octal escape sequences are not allowed in strict mode\");\n        return String.fromCharCode(parseInt(ch, 8));\n    }\n\n    var read_string = with_eof_error(\"Unterminated string constant\", function(quote_char) {\n        var quote = next(), ret = \"\";\n        for (;;) {\n            var ch = next(true, true);\n            if (ch == \"\\\\\") ch = read_escaped_char(true);\n            else if (NEWLINE_CHARS[ch]) parse_error(\"Unterminated string constant\");\n            else if (ch == quote) break;\n            ret += ch;\n        }\n        var tok = token(\"string\", ret);\n        tok.quote = quote_char;\n        return tok;\n    });\n\n    function skip_line_comment(type) {\n        var regex_allowed = S.regex_allowed;\n        var i = find_eol(), ret;\n        if (i == -1) {\n            ret = S.text.substr(S.pos);\n            S.pos = S.text.length;\n        } else {\n            ret = S.text.substring(S.pos, i);\n            S.pos = i;\n        }\n        S.col = S.tokcol + (S.pos - S.tokpos);\n        S.comments_before.push(token(type, ret, true));\n        S.regex_allowed = regex_allowed;\n        return next_token;\n    }\n\n    var skip_multiline_comment = with_eof_error(\"Unterminated multiline comment\", function() {\n        var regex_allowed = S.regex_allowed;\n        var i = find(\"*/\", true);\n        var text = S.text.substring(S.pos, i).replace(/\\r\\n|\\r|\\u2028|\\u2029/g, \"\\n\");\n        // update stream position\n        forward(text.length /* doesn't count \\r\\n as 2 char while S.pos - i does */ + 2);\n        S.comments_before.push(token(\"comment2\", text, true));\n        S.regex_allowed = regex_allowed;\n        return next_token;\n    });\n\n    function read_name() {\n        var backslash = false, ch, escaped = false, name = peek() == \"#\" ? next() : \"\";\n        while (ch = peek()) {\n            if (!backslash) {\n                if (ch == \"\\\\\") escaped = backslash = true, next();\n                else if (is_identifier_char(ch)) name += next();\n                else break;\n            } else {\n                if (ch != \"u\") parse_error(\"Expecting UnicodeEscapeSequence -- uXXXX\");\n                ch = read_escaped_char();\n                if (!is_identifier_char(ch)) parse_error(\"Unicode char: \" + ch.charCodeAt(0) + \" is not valid in identifier\");\n                name += ch;\n                backslash = false;\n            }\n        }\n        if (KEYWORDS[name] && escaped) {\n            var hex = name.charCodeAt(0).toString(16).toUpperCase();\n            name = \"\\\\u\" + \"0000\".substr(hex.length) + hex + name.slice(1);\n        }\n        return name;\n    }\n\n    var read_regexp = with_eof_error(\"Unterminated regular expression\", function(source) {\n        var prev_backslash = false, ch, in_class = false;\n        while ((ch = next(true))) if (NEWLINE_CHARS[ch]) {\n            parse_error(\"Unexpected line terminator\");\n        } else if (prev_backslash) {\n            source += \"\\\\\" + ch;\n            prev_backslash = false;\n        } else if (ch == \"[\") {\n            in_class = true;\n            source += ch;\n        } else if (ch == \"]\" && in_class) {\n            in_class = false;\n            source += ch;\n        } else if (ch == \"/\" && !in_class) {\n            break;\n        } else if (ch == \"\\\\\") {\n            prev_backslash = true;\n        } else {\n            source += ch;\n        }\n        var mods = read_name();\n        try {\n            var regexp = new RegExp(source, mods);\n            regexp.raw_source = source;\n            return token(\"regexp\", regexp);\n        } catch (e) {\n            parse_error(e.message);\n        }\n    });\n\n    function read_operator(prefix) {\n        function grow(op) {\n            if (!peek()) return op;\n            var bigger = op + peek();\n            if (OPERATORS[bigger]) {\n                next();\n                return grow(bigger);\n            } else {\n                return op;\n            }\n        }\n        return token(\"operator\", grow(prefix || next()));\n    }\n\n    function handle_slash() {\n        next();\n        switch (peek()) {\n          case \"/\":\n            next();\n            return skip_line_comment(\"comment1\");\n          case \"*\":\n            next();\n            return skip_multiline_comment();\n        }\n        return S.regex_allowed ? read_regexp(\"\") : read_operator(\"/\");\n    }\n\n    function handle_dot() {\n        next();\n        if (looking_at(\"..\")) return token(\"operator\", \".\" + next() + next());\n        return is_digit(peek().charCodeAt(0)) ? read_num(\".\") : token(\"punc\", \".\");\n    }\n\n    function read_word() {\n        var word = read_name();\n        if (prev_was_dot) return token(\"name\", word);\n        return KEYWORDS_ATOM[word] ? token(\"atom\", word)\n            : !KEYWORDS[word] ? token(\"name\", word)\n            : OPERATORS[word] ? token(\"operator\", word)\n            : token(\"keyword\", word);\n    }\n\n    function with_eof_error(eof_error, cont) {\n        return function(x) {\n            try {\n                return cont(x);\n            } catch (ex) {\n                if (ex === EX_EOF) parse_error(eof_error);\n                else throw ex;\n            }\n        };\n    }\n\n    function next_token(force_regexp) {\n        if (force_regexp != null)\n            return read_regexp(force_regexp);\n        if (shebang && S.pos == 0 && looking_at(\"#!\")) {\n            start_token();\n            forward(2);\n            skip_line_comment(\"comment5\");\n        }\n        for (;;) {\n            skip_whitespace();\n            start_token();\n            if (html5_comments) {\n                if (looking_at(\"<!--\")) {\n                    forward(4);\n                    skip_line_comment(\"comment3\");\n                    continue;\n                }\n                if (looking_at(\"-->\") && S.newline_before) {\n                    forward(3);\n                    skip_line_comment(\"comment4\");\n                    continue;\n                }\n            }\n            var ch = peek();\n            if (!ch) return token(\"eof\");\n            var code = ch.charCodeAt(0);\n            switch (code) {\n              case 34: case 39: return read_string(ch);\n              case 46: return handle_dot();\n              case 47:\n                var tok = handle_slash();\n                if (tok === next_token) continue;\n                return tok;\n            }\n            if (is_digit(code)) return read_num();\n            if (PUNC_CHARS[ch]) return token(\"punc\", next());\n            if (looking_at(\"=>\")) return token(\"punc\", next() + next());\n            if (OPERATOR_CHARS[ch]) return read_operator();\n            if (code == 35 || code == 92 || !NON_IDENTIFIER_CHARS[ch]) return read_word();\n            break;\n        }\n        parse_error(\"Unexpected character '\" + ch + \"'\");\n    }\n\n    next_token.context = function(nc) {\n        if (nc) S = nc;\n        return S;\n    };\n\n    next_token.add_directive = function(directive) {\n        S.directives[directive] = true;\n    }\n\n    next_token.push_directives_stack = function() {\n        S.directives = Object.create(S.directives);\n    }\n\n    next_token.pop_directives_stack = function() {\n        S.directives = Object.getPrototypeOf(S.directives);\n    }\n\n    next_token.has_directive = function(directive) {\n        return !!S.directives[directive];\n    }\n\n    return next_token;\n}\n\n/* -----[ Parser (constants) ]----- */\n\nvar UNARY_PREFIX = makePredicate(\"typeof void delete -- ++ ! ~ - +\");\n\nvar UNARY_POSTFIX = makePredicate(\"-- ++\");\n\nvar ASSIGNMENT = makePredicate(\"= += -= /= *= %= **= >>= <<= >>>= &= |= ^= &&= ||= ??=\");\n\nvar PRECEDENCE = function(a, ret) {\n    for (var i = 0; i < a.length;) {\n        var b = a[i++];\n        for (var j = 0; j < b.length; j++) {\n            ret[b[j]] = i;\n        }\n    }\n    return ret;\n}([\n    [\"??\"],\n    [\"||\"],\n    [\"&&\"],\n    [\"|\"],\n    [\"^\"],\n    [\"&\"],\n    [\"==\", \"===\", \"!=\", \"!==\"],\n    [\"<\", \">\", \"<=\", \">=\", \"in\", \"instanceof\"],\n    [\">>\", \"<<\", \">>>\"],\n    [\"+\", \"-\"],\n    [\"*\", \"/\", \"%\"],\n    [\"**\"],\n], {});\n\nvar ATOMIC_START_TOKEN = makePredicate(\"atom bigint num regexp string\");\n\n/* -----[ Parser ]----- */\n\nfunction parse($TEXT, options) {\n    options = defaults(options, {\n        bare_returns   : false,\n        expression     : false,\n        filename       : null,\n        html5_comments : true,\n        module         : false,\n        shebang        : true,\n        strict         : false,\n        toplevel       : null,\n    }, true);\n\n    var S = {\n        input         : typeof $TEXT == \"string\"\n                        ? tokenizer($TEXT, options.filename, options.html5_comments, options.shebang)\n                        : $TEXT,\n        in_async      : false,\n        in_directives : true,\n        in_funarg     : -1,\n        in_function   : 0,\n        in_generator  : false,\n        in_loop       : 0,\n        labels        : [],\n        peeked        : null,\n        prev          : null,\n        token         : null,\n    };\n\n    S.token = next();\n\n    function is(type, value) {\n        return is_token(S.token, type, value);\n    }\n\n    function peek() {\n        return S.peeked || (S.peeked = S.input());\n    }\n\n    function next() {\n        S.prev = S.token;\n        if (S.peeked) {\n            S.token = S.peeked;\n            S.peeked = null;\n        } else {\n            S.token = S.input();\n        }\n        S.in_directives = S.in_directives && (\n            S.token.type == \"string\" || is(\"punc\", \";\")\n        );\n        return S.token;\n    }\n\n    function prev() {\n        return S.prev;\n    }\n\n    function croak(msg, line, col, pos) {\n        var ctx = S.input.context();\n        js_error(msg,\n                 ctx.filename,\n                 line != null ? line : ctx.tokline,\n                 col != null ? col : ctx.tokcol,\n                 pos != null ? pos : ctx.tokpos);\n    }\n\n    function token_error(token, msg) {\n        croak(msg, token.line, token.col);\n    }\n\n    function token_to_string(type, value) {\n        return type + (value === undefined ? \"\" : \" «\" + value + \"»\");\n    }\n\n    function unexpected(token) {\n        if (token == null) token = S.token;\n        token_error(token, \"Unexpected token: \" + token_to_string(token.type, token.value));\n    }\n\n    function expect_token(type, val) {\n        if (is(type, val)) return next();\n        token_error(S.token, \"Unexpected token: \" + token_to_string(S.token.type, S.token.value) + \", expected: \" + token_to_string(type, val));\n    }\n\n    function expect(punc) {\n        return expect_token(\"punc\", punc);\n    }\n\n    function has_newline_before(token) {\n        return token.nlb || !all(token.comments_before, function(comment) {\n            return !comment.nlb;\n        });\n    }\n\n    function can_insert_semicolon() {\n        return !options.strict\n            && (is(\"eof\") || is(\"punc\", \"}\") || has_newline_before(S.token));\n    }\n\n    function semicolon(optional) {\n        if (is(\"punc\", \";\")) next();\n        else if (!optional && !can_insert_semicolon()) expect(\";\");\n    }\n\n    function parenthesized() {\n        expect(\"(\");\n        var exp = expression();\n        expect(\")\");\n        return exp;\n    }\n\n    function embed_tokens(parser) {\n        return function() {\n            var start = S.token;\n            var expr = parser.apply(null, arguments);\n            var end = prev();\n            expr.start = start;\n            expr.end = end;\n            return expr;\n        };\n    }\n\n    function handle_regexp() {\n        if (is(\"operator\", \"/\") || is(\"operator\", \"/=\")) {\n            S.peeked = null;\n            S.token = S.input(S.token.value.substr(1)); // force regexp\n        }\n    }\n\n    var statement = embed_tokens(function(toplevel) {\n        handle_regexp();\n        switch (S.token.type) {\n          case \"string\":\n            var dir = S.in_directives;\n            var body = expression();\n            if (dir) {\n                if (body instanceof AST_String) {\n                    var value = body.start.raw.slice(1, -1);\n                    S.input.add_directive(value);\n                    body.value = value;\n                } else {\n                    S.in_directives = dir = false;\n                }\n            }\n            semicolon();\n            return dir ? new AST_Directive(body) : new AST_SimpleStatement({ body: body });\n          case \"num\":\n          case \"bigint\":\n          case \"regexp\":\n          case \"operator\":\n          case \"atom\":\n            return simple_statement();\n\n          case \"name\":\n            switch (S.token.value) {\n              case \"async\":\n                if (is_token(peek(), \"keyword\", \"function\")) {\n                    next();\n                    next();\n                    if (!is(\"operator\", \"*\")) return function_(AST_AsyncDefun);\n                    next();\n                    return function_(AST_AsyncGeneratorDefun);\n                }\n                break;\n              case \"await\":\n                if (S.in_async) return simple_statement();\n                break;\n              case \"export\":\n                if (!toplevel && options.module !== \"\") unexpected();\n                next();\n                return export_();\n              case \"import\":\n                var token = peek();\n                if (token.type == \"punc\" && /^[(.]$/.test(token.value)) break;\n                if (!toplevel && options.module !== \"\") unexpected();\n                next();\n                return import_();\n              case \"let\":\n                if (is_vardefs()) {\n                    next();\n                    var node = let_();\n                    semicolon();\n                    return node;\n                }\n                break;\n              case \"yield\":\n                if (S.in_generator) return simple_statement();\n                break;\n            }\n            return is_token(peek(), \"punc\", \":\")\n                ? labeled_statement()\n                : simple_statement();\n\n          case \"punc\":\n            switch (S.token.value) {\n              case \"{\":\n                return new AST_BlockStatement({\n                    start : S.token,\n                    body  : block_(),\n                    end   : prev()\n                });\n              case \"[\":\n              case \"(\":\n              case \"`\":\n                return simple_statement();\n              case \";\":\n                S.in_directives = false;\n                next();\n                return new AST_EmptyStatement();\n              default:\n                unexpected();\n            }\n\n          case \"keyword\":\n            switch (S.token.value) {\n              case \"break\":\n                next();\n                return break_cont(AST_Break);\n\n              case \"class\":\n                next();\n                return class_(AST_DefClass);\n\n              case \"const\":\n                next();\n                var node = const_();\n                semicolon();\n                return node;\n\n              case \"continue\":\n                next();\n                return break_cont(AST_Continue);\n\n              case \"debugger\":\n                next();\n                semicolon();\n                return new AST_Debugger();\n\n              case \"do\":\n                next();\n                var body = in_loop(statement);\n                expect_token(\"keyword\", \"while\");\n                var condition = parenthesized();\n                semicolon(true);\n                return new AST_Do({\n                    body      : body,\n                    condition : condition,\n                });\n\n              case \"while\":\n                next();\n                return new AST_While({\n                    condition : parenthesized(),\n                    body      : in_loop(statement),\n                });\n\n              case \"for\":\n                next();\n                return for_();\n\n              case \"function\":\n                next();\n                if (!is(\"operator\", \"*\")) return function_(AST_Defun);\n                next();\n                return function_(AST_GeneratorDefun);\n\n              case \"if\":\n                next();\n                return if_();\n\n              case \"return\":\n                if (S.in_function == 0 && !options.bare_returns)\n                    croak(\"'return' outside of function\");\n                next();\n                var value = null;\n                if (is(\"punc\", \";\")) {\n                    next();\n                } else if (!can_insert_semicolon()) {\n                    value = expression();\n                    semicolon();\n                }\n                return new AST_Return({ value: value });\n\n              case \"switch\":\n                next();\n                return new AST_Switch({\n                    expression : parenthesized(),\n                    body       : in_loop(switch_body_),\n                });\n\n              case \"throw\":\n                next();\n                if (has_newline_before(S.token))\n                    croak(\"Illegal newline after 'throw'\");\n                var value = expression();\n                semicolon();\n                return new AST_Throw({ value: value });\n\n              case \"try\":\n                next();\n                return try_();\n\n              case \"var\":\n                next();\n                var node = var_();\n                semicolon();\n                return node;\n\n              case \"with\":\n                if (S.input.has_directive(\"use strict\")) {\n                    croak(\"Strict mode may not include a with statement\");\n                }\n                next();\n                return new AST_With({\n                    expression : parenthesized(),\n                    body       : statement(),\n                });\n            }\n        }\n        unexpected();\n    });\n\n    function labeled_statement() {\n        var label = as_symbol(AST_Label);\n        if (!all(S.labels, function(l) {\n            return l.name != label.name;\n        })) {\n            // ECMA-262, 12.12: An ECMAScript program is considered\n            // syntactically incorrect if it contains a\n            // LabelledStatement that is enclosed by a\n            // LabelledStatement with the same Identifier as label.\n            croak(\"Label \" + label.name + \" defined twice\");\n        }\n        expect(\":\");\n        S.labels.push(label);\n        var stat = statement();\n        S.labels.pop();\n        if (!(stat instanceof AST_IterationStatement)) {\n            // check for `continue` that refers to this label.\n            // those should be reported as syntax errors.\n            // https://github.com/mishoo/UglifyJS/issues/287\n            label.references.forEach(function(ref) {\n                if (ref instanceof AST_Continue) {\n                    token_error(ref.label.start, \"Continue label `\" + label.name + \"` must refer to IterationStatement\");\n                }\n            });\n        }\n        return new AST_LabeledStatement({ body: stat, label: label });\n    }\n\n    function simple_statement() {\n        var body = expression();\n        semicolon();\n        return new AST_SimpleStatement({ body: body });\n    }\n\n    function break_cont(type) {\n        var label = null, ldef;\n        if (!can_insert_semicolon()) {\n            label = as_symbol(AST_LabelRef, true);\n        }\n        if (label != null) {\n            ldef = find_if(function(l) {\n                return l.name == label.name;\n            }, S.labels);\n            if (!ldef) token_error(label.start, \"Undefined label \" + label.name);\n            label.thedef = ldef;\n        } else if (S.in_loop == 0) croak(type.TYPE + \" not inside a loop or switch\");\n        semicolon();\n        var stat = new type({ label: label });\n        if (ldef) ldef.references.push(stat);\n        return stat;\n    }\n\n    function has_modifier(name, no_nlb) {\n        if (!is(\"name\", name)) return;\n        var token = peek();\n        if (!token) return;\n        if (is_token(token, \"operator\", \"=\")) return;\n        if (token.type == \"punc\" && /^[(;}]$/.test(token.value)) return;\n        if (no_nlb && has_newline_before(token)) return;\n        return next();\n    }\n\n    function class_(ctor) {\n        var was_async = S.in_async;\n        var was_gen = S.in_generator;\n        S.input.push_directives_stack();\n        S.input.add_directive(\"use strict\");\n        var name;\n        if (ctor === AST_DefClass) {\n            name = as_symbol(AST_SymbolDefClass);\n        } else {\n            name = as_symbol(AST_SymbolClass, true);\n        }\n        var parent = null;\n        if (is(\"keyword\", \"extends\")) {\n            next();\n            handle_regexp();\n            parent = expr_atom(true);\n        }\n        expect(\"{\");\n        var props = [];\n        while (!is(\"punc\", \"}\")) {\n            if (is(\"punc\", \";\")) {\n                next();\n                continue;\n            }\n            var start = S.token;\n            var fixed = !!has_modifier(\"static\");\n            var async = has_modifier(\"async\", true);\n            if (is(\"operator\", \"*\")) {\n                next();\n                var internal = is(\"name\") && /^#/.test(S.token.value);\n                var key = as_property_key();\n                var gen_start = S.token;\n                var gen = function_(async ? AST_AsyncGeneratorFunction : AST_GeneratorFunction);\n                gen.start = gen_start;\n                gen.end = prev();\n                props.push(new AST_ClassMethod({\n                    start: start,\n                    static: fixed,\n                    private: internal,\n                    key: key,\n                    value: gen,\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (fixed && is(\"punc\", \"{\")) {\n                props.push(new AST_ClassInit({\n                    start: start,\n                    value: new AST_ClassInitBlock({\n                        start: start,\n                        body: block_(),\n                        end: prev(),\n                    }),\n                    end: prev(),\n                }));\n                continue;\n            }\n            var internal = is(\"name\") && /^#/.test(S.token.value);\n            var key = as_property_key();\n            if (is(\"punc\", \"(\")) {\n                var func_start = S.token;\n                var func = function_(async ? AST_AsyncFunction : AST_Function);\n                func.start = func_start;\n                func.end = prev();\n                props.push(new AST_ClassMethod({\n                    start: start,\n                    static: fixed,\n                    private: internal,\n                    key: key,\n                    value: func,\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (async) unexpected(async);\n            var value = null;\n            if (is(\"operator\", \"=\")) {\n                next();\n                S.in_async = false;\n                S.in_generator = false;\n                value = maybe_assign();\n                S.in_generator = was_gen;\n                S.in_async = was_async;\n            } else if (!(is(\"punc\", \";\") || is(\"punc\", \"}\"))) {\n                var type = null;\n                switch (key) {\n                  case \"get\":\n                    type = AST_ClassGetter;\n                    break;\n                  case \"set\":\n                    type = AST_ClassSetter;\n                    break;\n                }\n                if (type) {\n                    props.push(new type({\n                        start: start,\n                        static: fixed,\n                        private: is(\"name\") && /^#/.test(S.token.value),\n                        key: as_property_key(),\n                        value: create_accessor(),\n                        end: prev(),\n                    }));\n                    continue;\n                }\n            }\n            semicolon();\n            props.push(new AST_ClassField({\n                start: start,\n                static: fixed,\n                private: internal,\n                key: key,\n                value: value,\n                end: prev(),\n            }));\n        }\n        next();\n        S.input.pop_directives_stack();\n        S.in_generator = was_gen;\n        S.in_async = was_async;\n        return new ctor({\n            extends: parent,\n            name: name,\n            properties: props,\n        });\n    }\n\n    function for_() {\n        var await_token = is(\"name\", \"await\") && next();\n        expect(\"(\");\n        var init = null;\n        if (await_token || !is(\"punc\", \";\")) {\n            init = is(\"keyword\", \"const\")\n                ? (next(), const_(true))\n                : is(\"name\", \"let\") && is_vardefs()\n                ? (next(), let_(true))\n                : is(\"keyword\", \"var\")\n                ? (next(), var_(true))\n                : expression(true);\n            var ctor;\n            if (await_token) {\n                expect_token(\"name\", \"of\");\n                ctor = AST_ForAwaitOf;\n            } else if (is(\"operator\", \"in\")) {\n                next();\n                ctor = AST_ForIn;\n            } else if (is(\"name\", \"of\")) {\n                next();\n                ctor = AST_ForOf;\n            }\n            if (ctor) {\n                if (init instanceof AST_Definitions) {\n                    if (init.definitions.length > 1) {\n                        token_error(init.start, \"Only one variable declaration allowed in for..in/of loop\");\n                    }\n                    if (ctor !== AST_ForIn && init.definitions[0].value) {\n                        token_error(init.definitions[0].value.start, \"No initializers allowed in for..of loop\");\n                    }\n                } else if (!(is_assignable(init) || (init = to_destructured(init)) instanceof AST_Destructured)) {\n                    token_error(init.start, \"Invalid left-hand side in for..in/of loop\");\n                }\n                return for_enum(ctor, init);\n            }\n        }\n        return regular_for(init);\n    }\n\n    function regular_for(init) {\n        expect(\";\");\n        var test = is(\"punc\", \";\") ? null : expression();\n        expect(\";\");\n        var step = is(\"punc\", \")\") ? null : expression();\n        expect(\")\");\n        return new AST_For({\n            init      : init,\n            condition : test,\n            step      : step,\n            body      : in_loop(statement)\n        });\n    }\n\n    function for_enum(ctor, init) {\n        handle_regexp();\n        var obj = expression();\n        expect(\")\");\n        return new ctor({\n            init   : init,\n            object : obj,\n            body   : in_loop(statement)\n        });\n    }\n\n    function to_funarg(node) {\n        if (node instanceof AST_Array) {\n            var rest = null;\n            if (node.elements[node.elements.length - 1] instanceof AST_Spread) {\n                rest = to_funarg(node.elements.pop().expression);\n            }\n            return new AST_DestructuredArray({\n                start: node.start,\n                elements: node.elements.map(to_funarg),\n                rest: rest,\n                end: node.end,\n            });\n        }\n        if (node instanceof AST_Assign) return new AST_DefaultValue({\n            start: node.start,\n            name: to_funarg(node.left),\n            value: node.right,\n            end: node.end,\n        });\n        if (node instanceof AST_DefaultValue) {\n            node.name = to_funarg(node.name);\n            return node;\n        }\n        if (node instanceof AST_DestructuredArray) {\n            node.elements = node.elements.map(to_funarg);\n            if (node.rest) node.rest = to_funarg(node.rest);\n            return node;\n        }\n        if (node instanceof AST_DestructuredObject) {\n            node.properties.forEach(function(prop) {\n                prop.value = to_funarg(prop.value);\n            });\n            if (node.rest) node.rest = to_funarg(node.rest);\n            return node;\n        }\n        if (node instanceof AST_Hole) return node;\n        if (node instanceof AST_Object) {\n            var rest = null;\n            if (node.properties[node.properties.length - 1] instanceof AST_Spread) {\n                rest = to_funarg(node.properties.pop().expression);\n            }\n            return new AST_DestructuredObject({\n                start: node.start,\n                properties: node.properties.map(function(prop) {\n                    if (!(prop instanceof AST_ObjectKeyVal)) token_error(prop.start, \"Invalid destructuring assignment\");\n                    return new AST_DestructuredKeyVal({\n                        start: prop.start,\n                        key: prop.key,\n                        value: to_funarg(prop.value),\n                        end: prop.end,\n                    });\n                }),\n                rest: rest,\n                end: node.end,\n            });\n        }\n        if (node instanceof AST_SymbolFunarg) return node;\n        if (node instanceof AST_SymbolRef) return new AST_SymbolFunarg(node);\n        if (node instanceof AST_Yield) return new AST_SymbolFunarg({\n            start: node.start,\n            name: \"yield\",\n            end: node.end,\n        });\n        token_error(node.start, \"Invalid arrow parameter\");\n    }\n\n    function arrow(exprs, start, async) {\n        var was_async = S.in_async;\n        var was_gen = S.in_generator;\n        S.in_async = async;\n        S.in_generator = false;\n        var was_funarg = S.in_funarg;\n        S.in_funarg = S.in_function;\n        var argnames = exprs.map(to_funarg);\n        var rest = exprs.rest || null;\n        if (rest) rest = to_funarg(rest);\n        S.in_funarg = was_funarg;\n        expect(\"=>\");\n        var body, value;\n        var loop = S.in_loop;\n        var labels = S.labels;\n        ++S.in_function;\n        S.input.push_directives_stack();\n        S.in_loop = 0;\n        S.labels = [];\n        if (is(\"punc\", \"{\")) {\n            S.in_directives = true;\n            body = block_();\n            value = null;\n        } else {\n            body = [];\n            handle_regexp();\n            value = maybe_assign();\n        }\n        var is_strict = S.input.has_directive(\"use strict\");\n        S.input.pop_directives_stack();\n        --S.in_function;\n        S.in_loop = loop;\n        S.labels = labels;\n        S.in_generator = was_gen;\n        S.in_async = was_async;\n        var node = new (async ? AST_AsyncArrow : AST_Arrow)({\n            start: start,\n            argnames: argnames,\n            rest: rest,\n            body: body,\n            value: value,\n            end: prev(),\n        });\n        if (is_strict) node.each_argname(strict_verify_symbol);\n        return node;\n    }\n\n    var function_ = function(ctor) {\n        var was_async = S.in_async;\n        var was_gen = S.in_generator;\n        var name;\n        if (/Defun$/.test(ctor.TYPE)) {\n            name = as_symbol(AST_SymbolDefun);\n            S.in_async = /^Async/.test(ctor.TYPE);\n            S.in_generator = /Generator/.test(ctor.TYPE);\n        } else {\n            S.in_async = /^Async/.test(ctor.TYPE);\n            S.in_generator = /Generator/.test(ctor.TYPE);\n            name = as_symbol(AST_SymbolLambda, true);\n        }\n        if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration))\n            unexpected(prev());\n        expect(\"(\");\n        var was_funarg = S.in_funarg;\n        S.in_funarg = S.in_function;\n        var argnames = expr_list(\")\", !options.strict, false, function() {\n            return maybe_default(AST_SymbolFunarg);\n        });\n        S.in_funarg = was_funarg;\n        var loop = S.in_loop;\n        var labels = S.labels;\n        ++S.in_function;\n        S.in_directives = true;\n        S.input.push_directives_stack();\n        S.in_loop = 0;\n        S.labels = [];\n        var body = block_();\n        var is_strict = S.input.has_directive(\"use strict\");\n        S.input.pop_directives_stack();\n        --S.in_function;\n        S.in_loop = loop;\n        S.labels = labels;\n        S.in_generator = was_gen;\n        S.in_async = was_async;\n        var node = new ctor({\n            name: name,\n            argnames: argnames,\n            rest: argnames.rest || null,\n            body: body,\n        });\n        if (is_strict) {\n            if (name) strict_verify_symbol(name);\n            node.each_argname(strict_verify_symbol);\n        }\n        return node;\n    };\n\n    function if_() {\n        var cond = parenthesized(), body = statement(), alt = null;\n        if (is(\"keyword\", \"else\")) {\n            next();\n            alt = statement();\n        }\n        return new AST_If({\n            condition   : cond,\n            body        : body,\n            alternative : alt,\n        });\n    }\n\n    function is_alias() {\n        return is(\"name\") || is(\"string\") || is_identifier_string(S.token.value);\n    }\n\n    function make_string(token) {\n        return new AST_String({\n            start: token,\n            quote: token.quote,\n            value: token.value,\n            end: token,\n        });\n    }\n\n    function as_path() {\n        var path = S.token;\n        expect_token(\"string\");\n        semicolon();\n        return make_string(path);\n    }\n\n    function export_() {\n        if (is(\"operator\", \"*\")) {\n            var key = S.token;\n            var alias = key;\n            next();\n            if (is(\"name\", \"as\")) {\n                next();\n                if (!is_alias()) expect_token(\"name\");\n                alias = S.token;\n                next();\n            }\n            expect_token(\"name\", \"from\");\n            return new AST_ExportForeign({\n                aliases: [ make_string(alias) ],\n                keys: [ make_string(key) ],\n                path: as_path(),\n            });\n        }\n        if (is(\"punc\", \"{\")) {\n            next();\n            var aliases = [];\n            var keys = [];\n            while (is_alias()) {\n                var key = S.token;\n                next();\n                keys.push(key);\n                if (is(\"name\", \"as\")) {\n                    next();\n                    if (!is_alias()) expect_token(\"name\");\n                    aliases.push(S.token);\n                    next();\n                } else {\n                    aliases.push(key);\n                }\n                if (!is(\"punc\", \"}\")) expect(\",\");\n            }\n            expect(\"}\");\n            if (is(\"name\", \"from\")) {\n                next();\n                return new AST_ExportForeign({\n                    aliases: aliases.map(make_string),\n                    keys: keys.map(make_string),\n                    path: as_path(),\n                });\n            }\n            semicolon();\n            return new AST_ExportReferences({\n                properties: keys.map(function(token, index) {\n                    if (!is_token(token, \"name\")) token_error(token, \"Name expected\");\n                    var sym = _make_symbol(AST_SymbolExport, token);\n                    sym.alias = make_string(aliases[index]);\n                    return sym;\n                }),\n            });\n        }\n        if (is(\"keyword\", \"default\")) {\n            next();\n            var start = S.token;\n            var body = export_default_decl();\n            if (body) {\n                body.start = start;\n                body.end = prev();\n            } else {\n                handle_regexp();\n                body = expression();\n                semicolon();\n            }\n            return new AST_ExportDefault({ body: body });\n        }\n        return new AST_ExportDeclaration({ body: export_decl() });\n    }\n\n    function maybe_named(def, expr) {\n        if (expr.name) {\n            expr = new def(expr);\n            expr.name = new (def === AST_DefClass ? AST_SymbolDefClass : AST_SymbolDefun)(expr.name);\n        }\n        return expr;\n    }\n\n    function export_default_decl() {\n        if (is(\"name\", \"async\")) {\n            if (!is_token(peek(), \"keyword\", \"function\")) return;\n            next();\n            next();\n            if (!is(\"operator\", \"*\")) return maybe_named(AST_AsyncDefun, function_(AST_AsyncFunction));\n            next();\n            return maybe_named(AST_AsyncGeneratorDefun, function_(AST_AsyncGeneratorFunction));\n        } else if (is(\"keyword\")) switch (S.token.value) {\n          case \"class\":\n            next();\n            return maybe_named(AST_DefClass, class_(AST_ClassExpression));\n          case \"function\":\n            next();\n            if (!is(\"operator\", \"*\")) return maybe_named(AST_Defun, function_(AST_Function));\n            next();\n            return maybe_named(AST_GeneratorDefun, function_(AST_GeneratorFunction));\n        }\n    }\n\n    var export_decl = embed_tokens(function() {\n        if (is(\"name\")) switch (S.token.value) {\n          case \"async\":\n            next();\n            expect_token(\"keyword\", \"function\");\n            if (!is(\"operator\", \"*\")) return function_(AST_AsyncDefun);\n            next();\n            return function_(AST_AsyncGeneratorDefun);\n          case \"let\":\n            next();\n            var node = let_();\n            semicolon();\n            return node;\n        } else if (is(\"keyword\")) switch (S.token.value) {\n          case \"class\":\n            next();\n            return class_(AST_DefClass);\n          case \"const\":\n            next();\n            var node = const_();\n            semicolon();\n            return node;\n          case \"function\":\n            next();\n            if (!is(\"operator\", \"*\")) return function_(AST_Defun);\n            next();\n            return function_(AST_GeneratorDefun);\n          case \"var\":\n            next();\n            var node = var_();\n            semicolon();\n            return node;\n        }\n        unexpected();\n    });\n\n    function import_() {\n        var all = null;\n        var def = as_symbol(AST_SymbolImport, true);\n        var props = null;\n        var cont;\n        if (def) {\n            def.key = new AST_String({\n                start: def.start,\n                value: \"\",\n                end: def.end,\n            });\n            if (cont = is(\"punc\", \",\")) next();\n        } else {\n            cont = !is(\"string\");\n        }\n        if (cont) {\n            if (is(\"operator\", \"*\")) {\n                var key = S.token;\n                next();\n                expect_token(\"name\", \"as\");\n                all = as_symbol(AST_SymbolImport);\n                all.key = make_string(key);\n            } else {\n                expect(\"{\");\n                props = [];\n                while (is_alias()) {\n                    var alias;\n                    if (is_token(peek(), \"name\", \"as\")) {\n                        var key = S.token;\n                        next();\n                        next();\n                        alias = as_symbol(AST_SymbolImport);\n                        alias.key = make_string(key);\n                    } else {\n                        alias = as_symbol(AST_SymbolImport);\n                        alias.key = new AST_String({\n                            start: alias.start,\n                            value: alias.name,\n                            end: alias.end,\n                        });\n                    }\n                    props.push(alias);\n                    if (!is(\"punc\", \"}\")) expect(\",\");\n                }\n                expect(\"}\");\n            }\n        }\n        if (all || def || props) expect_token(\"name\", \"from\");\n        return new AST_Import({\n            all: all,\n            default: def,\n            path: as_path(),\n            properties: props,\n        });\n    }\n\n    function block_() {\n        expect(\"{\");\n        var a = [];\n        while (!is(\"punc\", \"}\")) {\n            if (is(\"eof\")) expect(\"}\");\n            a.push(statement());\n        }\n        next();\n        return a;\n    }\n\n    function switch_body_() {\n        expect(\"{\");\n        var a = [], branch, cur, default_branch, tmp;\n        while (!is(\"punc\", \"}\")) {\n            if (is(\"eof\")) expect(\"}\");\n            if (is(\"keyword\", \"case\")) {\n                if (branch) branch.end = prev();\n                cur = [];\n                branch = new AST_Case({\n                    start      : (tmp = S.token, next(), tmp),\n                    expression : expression(),\n                    body       : cur\n                });\n                a.push(branch);\n                expect(\":\");\n            } else if (is(\"keyword\", \"default\")) {\n                if (branch) branch.end = prev();\n                if (default_branch) croak(\"More than one default clause in switch statement\");\n                cur = [];\n                branch = new AST_Default({\n                    start : (tmp = S.token, next(), expect(\":\"), tmp),\n                    body  : cur\n                });\n                a.push(branch);\n                default_branch = branch;\n            } else {\n                if (!cur) unexpected();\n                cur.push(statement());\n            }\n        }\n        if (branch) branch.end = prev();\n        next();\n        return a;\n    }\n\n    function try_() {\n        var body = block_(), bcatch = null, bfinally = null;\n        if (is(\"keyword\", \"catch\")) {\n            var start = S.token;\n            next();\n            var name = null;\n            if (is(\"punc\", \"(\")) {\n                next();\n                name = maybe_destructured(AST_SymbolCatch);\n                expect(\")\");\n            }\n            bcatch = new AST_Catch({\n                start   : start,\n                argname : name,\n                body    : block_(),\n                end     : prev()\n            });\n        }\n        if (is(\"keyword\", \"finally\")) {\n            var start = S.token;\n            next();\n            bfinally = new AST_Finally({\n                start : start,\n                body  : block_(),\n                end   : prev()\n            });\n        }\n        if (!bcatch && !bfinally)\n            croak(\"Missing catch/finally blocks\");\n        return new AST_Try({\n            body     : body,\n            bcatch   : bcatch,\n            bfinally : bfinally\n        });\n    }\n\n    function vardefs(type, no_in) {\n        var a = [];\n        for (;;) {\n            var start = S.token;\n            var name = maybe_destructured(type);\n            var value = null;\n            if (is(\"operator\", \"=\")) {\n                next();\n                value = maybe_assign(no_in);\n            } else if (!no_in && (type === AST_SymbolConst || name instanceof AST_Destructured)) {\n                croak(\"Missing initializer in declaration\");\n            }\n            a.push(new AST_VarDef({\n                start : start,\n                name  : name,\n                value : value,\n                end   : prev()\n            }));\n            if (!is(\"punc\", \",\"))\n                break;\n            next();\n        }\n        return a;\n    }\n\n    function is_vardefs() {\n        var token = peek();\n        return is_token(token, \"name\") || is_token(token, \"punc\", \"[\") || is_token(token, \"punc\", \"{\");\n    }\n\n    var const_ = function(no_in) {\n        return new AST_Const({\n            start       : prev(),\n            definitions : vardefs(AST_SymbolConst, no_in),\n            end         : prev()\n        });\n    };\n\n    var let_ = function(no_in) {\n        return new AST_Let({\n            start       : prev(),\n            definitions : vardefs(AST_SymbolLet, no_in),\n            end         : prev()\n        });\n    };\n\n    var var_ = function(no_in) {\n        return new AST_Var({\n            start       : prev(),\n            definitions : vardefs(AST_SymbolVar, no_in),\n            end         : prev()\n        });\n    };\n\n    var new_ = function(allow_calls) {\n        var start = S.token;\n        expect_token(\"operator\", \"new\");\n        var call;\n        if (is(\"punc\", \".\") && is_token(peek(), \"name\", \"target\")) {\n            next();\n            next();\n            call = new AST_NewTarget();\n        } else {\n            var exp = expr_atom(false), args;\n            if (is(\"punc\", \"(\")) {\n                next();\n                args = expr_list(\")\", !options.strict);\n            } else {\n                args = [];\n            }\n            call = new AST_New({ expression: exp, args: args });\n        }\n        call.start = start;\n        call.end = prev();\n        return subscripts(call, allow_calls);\n    };\n\n    function as_atom_node() {\n        var ret, tok = S.token, value = tok.value;\n        switch (tok.type) {\n          case \"num\":\n            if (isFinite(value)) {\n                ret = new AST_Number({ value: value });\n            } else {\n                ret = new AST_Infinity();\n                if (value < 0) ret = new AST_UnaryPrefix({ operator: \"-\", expression: ret });\n            }\n            break;\n          case \"bigint\":\n            ret = new AST_BigInt({ value: value });\n            break;\n          case \"string\":\n            ret = new AST_String({ value: value, quote: tok.quote });\n            break;\n          case \"regexp\":\n            ret = new AST_RegExp({ value: value });\n            break;\n          case \"atom\":\n            switch (value) {\n              case \"false\":\n                ret = new AST_False();\n                break;\n              case \"true\":\n                ret = new AST_True();\n                break;\n              case \"null\":\n                ret = new AST_Null();\n                break;\n              default:\n                unexpected();\n            }\n            break;\n          default:\n            unexpected();\n        }\n        next();\n        ret.start = ret.end = tok;\n        return ret;\n    }\n\n    var expr_atom = function(allow_calls) {\n        if (is(\"operator\", \"new\")) {\n            return new_(allow_calls);\n        }\n        var start = S.token;\n        if (is(\"punc\")) {\n            switch (start.value) {\n              case \"`\":\n                return subscripts(template(null), allow_calls);\n              case \"(\":\n                next();\n                if (is(\"punc\", \")\")) {\n                    next();\n                    return arrow([], start);\n                }\n                var ex = expression(false, true);\n                var len = start.comments_before.length;\n                [].unshift.apply(ex.start.comments_before, start.comments_before);\n                start.comments_before.length = 0;\n                start.comments_before = ex.start.comments_before;\n                start.comments_before_length = len;\n                if (len == 0 && start.comments_before.length > 0) {\n                    var comment = start.comments_before[0];\n                    if (!comment.nlb) {\n                        comment.nlb = start.nlb;\n                        start.nlb = false;\n                    }\n                }\n                start.comments_after = ex.start.comments_after;\n                ex.start = start;\n                expect(\")\");\n                var end = prev();\n                end.comments_before = ex.end.comments_before;\n                end.comments_after.forEach(function(comment) {\n                    ex.end.comments_after.push(comment);\n                    if (comment.nlb) S.token.nlb = true;\n                });\n                end.comments_after.length = 0;\n                end.comments_after = ex.end.comments_after;\n                ex.end = end;\n                if (is(\"punc\", \"=>\")) return arrow(ex instanceof AST_Sequence ? ex.expressions : [ ex ], start);\n                return subscripts(ex, allow_calls);\n              case \"[\":\n                return subscripts(array_(), allow_calls);\n              case \"{\":\n                return subscripts(object_(), allow_calls);\n            }\n            unexpected();\n        }\n        if (is(\"keyword\")) switch (start.value) {\n          case \"class\":\n            next();\n            var clazz = class_(AST_ClassExpression);\n            clazz.start = start;\n            clazz.end = prev();\n            return subscripts(clazz, allow_calls);\n          case \"function\":\n            next();\n            var func;\n            if (is(\"operator\", \"*\")) {\n                next();\n                func = function_(AST_GeneratorFunction);\n            } else {\n                func = function_(AST_Function);\n            }\n            func.start = start;\n            func.end = prev();\n            return subscripts(func, allow_calls);\n        }\n        if (is(\"name\")) {\n            var sym = _make_symbol(AST_SymbolRef, start);\n            next();\n            if (sym.name == \"async\") {\n                if (is(\"keyword\", \"function\")) {\n                    next();\n                    var func;\n                    if (is(\"operator\", \"*\")) {\n                        next();\n                        func = function_(AST_AsyncGeneratorFunction);\n                    } else {\n                        func = function_(AST_AsyncFunction);\n                    }\n                    func.start = start;\n                    func.end = prev();\n                    return subscripts(func, allow_calls);\n                }\n                if (is(\"name\") && is_token(peek(), \"punc\", \"=>\")) {\n                    start = S.token;\n                    sym = _make_symbol(AST_SymbolRef, start);\n                    next();\n                    return arrow([ sym ], start, true);\n                }\n                if (is(\"punc\", \"(\")) {\n                    var call = subscripts(sym, allow_calls);\n                    if (!is(\"punc\", \"=>\")) return call;\n                    var args = call.args;\n                    if (args[args.length - 1] instanceof AST_Spread) {\n                        args.rest = args.pop().expression;\n                    }\n                    return arrow(args, start, true);\n                }\n            }\n            return is(\"punc\", \"=>\") ? arrow([ sym ], start) : subscripts(sym, allow_calls);\n        }\n        if (ATOMIC_START_TOKEN[S.token.type]) {\n            return subscripts(as_atom_node(), allow_calls);\n        }\n        unexpected();\n    };\n\n    function expr_list(closing, allow_trailing_comma, allow_empty, parser) {\n        if (!parser) parser = maybe_assign;\n        var first = true, a = [];\n        while (!is(\"punc\", closing)) {\n            if (first) first = false; else expect(\",\");\n            if (allow_trailing_comma && is(\"punc\", closing)) break;\n            if (allow_empty && is(\"punc\", \",\")) {\n                a.push(new AST_Hole({ start: S.token, end: S.token }));\n            } else if (!is(\"operator\", \"...\")) {\n                a.push(parser());\n            } else if (parser === maybe_assign) {\n                a.push(new AST_Spread({\n                    start: S.token,\n                    expression: (next(), parser()),\n                    end: prev(),\n                }));\n            } else {\n                next();\n                a.rest = parser();\n                if (a.rest instanceof AST_DefaultValue) token_error(a.rest.start, \"Invalid rest parameter\");\n                break;\n            }\n        }\n        expect(closing);\n        return a;\n    }\n\n    var array_ = embed_tokens(function() {\n        expect(\"[\");\n        return new AST_Array({\n            elements: expr_list(\"]\", !options.strict, true)\n        });\n    });\n\n    var create_accessor = embed_tokens(function() {\n        return function_(AST_Accessor);\n    });\n\n    var object_ = embed_tokens(function() {\n        expect(\"{\");\n        var first = true, a = [];\n        while (!is(\"punc\", \"}\")) {\n            if (first) first = false; else expect(\",\");\n            // allow trailing comma\n            if (!options.strict && is(\"punc\", \"}\")) break;\n            var start = S.token;\n            if (is(\"operator\", \"*\")) {\n                next();\n                var key = as_property_key();\n                var gen_start = S.token;\n                var gen = function_(AST_GeneratorFunction);\n                gen.start = gen_start;\n                gen.end = prev();\n                a.push(new AST_ObjectMethod({\n                    start: start,\n                    key: key,\n                    value: gen,\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (is(\"operator\", \"...\")) {\n                next();\n                a.push(new AST_Spread({\n                    start: start,\n                    expression: maybe_assign(),\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (is_token(peek(), \"operator\", \"=\")) {\n                var name = as_symbol(AST_SymbolRef);\n                next();\n                a.push(new AST_ObjectKeyVal({\n                    start: start,\n                    key: start.value,\n                    value: new AST_Assign({\n                        start: start,\n                        left: name,\n                        operator: \"=\",\n                        right: maybe_assign(),\n                        end: prev(),\n                    }),\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (is_token(peek(), \"punc\", \",\") || is_token(peek(), \"punc\", \"}\")) {\n                a.push(new AST_ObjectKeyVal({\n                    start: start,\n                    key: start.value,\n                    value: as_symbol(AST_SymbolRef),\n                    end: prev(),\n                }));\n                continue;\n            }\n            var key = as_property_key();\n            if (is(\"punc\", \"(\")) {\n                var func_start = S.token;\n                var func = function_(AST_Function);\n                func.start = func_start;\n                func.end = prev();\n                a.push(new AST_ObjectMethod({\n                    start: start,\n                    key: key,\n                    value: func,\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (is(\"punc\", \":\")) {\n                next();\n                a.push(new AST_ObjectKeyVal({\n                    start: start,\n                    key: key,\n                    value: maybe_assign(),\n                    end: prev(),\n                }));\n                continue;\n            }\n            if (start.type == \"name\") switch (key) {\n              case \"async\":\n                var is_gen = is(\"operator\", \"*\") && next();\n                key = as_property_key();\n                var func_start = S.token;\n                var func = function_(is_gen ? AST_AsyncGeneratorFunction : AST_AsyncFunction);\n                func.start = func_start;\n                func.end = prev();\n                a.push(new AST_ObjectMethod({\n                    start: start,\n                    key: key,\n                    value: func,\n                    end: prev(),\n                }));\n                continue;\n              case \"get\":\n                a.push(new AST_ObjectGetter({\n                    start: start,\n                    key: as_property_key(),\n                    value: create_accessor(),\n                    end: prev(),\n                }));\n                continue;\n              case \"set\":\n                a.push(new AST_ObjectSetter({\n                    start: start,\n                    key: as_property_key(),\n                    value: create_accessor(),\n                    end: prev(),\n                }));\n                continue;\n            }\n            unexpected();\n        }\n        next();\n        return new AST_Object({ properties: a });\n    });\n\n    function as_property_key() {\n        var tmp = S.token;\n        switch (tmp.type) {\n          case \"operator\":\n            if (!KEYWORDS[tmp.value]) unexpected();\n          case \"num\":\n          case \"string\":\n          case \"name\":\n          case \"keyword\":\n          case \"atom\":\n            next();\n            return \"\" + tmp.value;\n          case \"punc\":\n            expect(\"[\");\n            var key = maybe_assign();\n            expect(\"]\");\n            return key;\n          default:\n            unexpected();\n        }\n    }\n\n    function as_name() {\n        var name = S.token.value;\n        expect_token(\"name\");\n        return name;\n    }\n\n    function _make_symbol(type, token) {\n        var name = token.value;\n        switch (name) {\n          case \"await\":\n            if (S.in_async) unexpected(token);\n            break;\n          case \"super\":\n            type = AST_Super;\n            break;\n          case \"this\":\n            type = AST_This;\n            break;\n          case \"yield\":\n            if (S.in_generator) unexpected(token);\n            break;\n        }\n        return new type({\n            name: \"\" + name,\n            start: token,\n            end: token,\n        });\n    }\n\n    function strict_verify_symbol(sym) {\n        if (sym.name == \"arguments\" || sym.name == \"eval\" || sym.name == \"let\")\n            token_error(sym.start, \"Unexpected \" + sym.name + \" in strict mode\");\n    }\n\n    function as_symbol(type, no_error) {\n        if (!is(\"name\")) {\n            if (!no_error) croak(\"Name expected\");\n            return null;\n        }\n        var sym = _make_symbol(type, S.token);\n        if (S.input.has_directive(\"use strict\") && sym instanceof AST_SymbolDeclaration) {\n            strict_verify_symbol(sym);\n        }\n        next();\n        return sym;\n    }\n\n    function maybe_destructured(type) {\n        var start = S.token;\n        if (is(\"punc\", \"[\")) {\n            next();\n            var elements = expr_list(\"]\", !options.strict, true, function() {\n                return maybe_default(type);\n            });\n            return new AST_DestructuredArray({\n                start: start,\n                elements: elements,\n                rest: elements.rest || null,\n                end: prev(),\n            });\n        }\n        if (is(\"punc\", \"{\")) {\n            next();\n            var first = true, a = [], rest = null;\n            while (!is(\"punc\", \"}\")) {\n                if (first) first = false; else expect(\",\");\n                // allow trailing comma\n                if (!options.strict && is(\"punc\", \"}\")) break;\n                var key_start = S.token;\n                if (is(\"punc\", \"[\") || is_token(peek(), \"punc\", \":\")) {\n                    var key = as_property_key();\n                    expect(\":\");\n                    a.push(new AST_DestructuredKeyVal({\n                        start: key_start,\n                        key: key,\n                        value: maybe_default(type),\n                        end: prev(),\n                    }));\n                    continue;\n                }\n                if (is(\"operator\", \"...\")) {\n                    next();\n                    rest = maybe_destructured(type);\n                    break;\n                }\n                var name = as_symbol(type);\n                if (is(\"operator\", \"=\")) {\n                    next();\n                    name = new AST_DefaultValue({\n                        start: name.start,\n                        name: name,\n                        value: maybe_assign(),\n                        end: prev(),\n                    });\n                }\n                a.push(new AST_DestructuredKeyVal({\n                    start: key_start,\n                    key: key_start.value,\n                    value: name,\n                    end: prev(),\n                }));\n            }\n            expect(\"}\");\n            return new AST_DestructuredObject({\n                start: start,\n                properties: a,\n                rest: rest,\n                end: prev(),\n            });\n        }\n        return as_symbol(type);\n    }\n\n    function maybe_default(type) {\n        var start = S.token;\n        var name = maybe_destructured(type);\n        if (!is(\"operator\", \"=\")) return name;\n        next();\n        return new AST_DefaultValue({\n            start: start,\n            name: name,\n            value: maybe_assign(),\n            end: prev(),\n        });\n    }\n\n    function template(tag) {\n        var start = tag ? tag.start : S.token;\n        var read = S.input.context().read_template;\n        var strings = [];\n        var expressions = [];\n        while (read(strings)) {\n            next();\n            expressions.push(expression());\n            if (!is(\"punc\", \"}\")) unexpected();\n        }\n        next();\n        return new AST_Template({\n            start: start,\n            expressions: expressions,\n            strings: strings,\n            tag: tag,\n            end: prev(),\n        });\n    }\n\n    function subscripts(expr, allow_calls) {\n        var start = expr.start;\n        var optional = null;\n        while (true) {\n            if (is(\"operator\", \"?\") && is_token(peek(), \"punc\", \".\")) {\n                next();\n                next();\n                optional = expr;\n            }\n            if (is(\"punc\", \"[\")) {\n                next();\n                var prop = expression();\n                expect(\"]\");\n                expr = new AST_Sub({\n                    start: start,\n                    optional: optional === expr,\n                    expression: expr,\n                    property: prop,\n                    end: prev(),\n                });\n            } else if (allow_calls && is(\"punc\", \"(\")) {\n                next();\n                expr = new AST_Call({\n                    start: start,\n                    optional: optional === expr,\n                    expression: expr,\n                    args: expr_list(\")\", !options.strict),\n                    end: prev(),\n                });\n            } else if (optional === expr || is(\"punc\", \".\")) {\n                if (optional !== expr) next();\n                expr = new AST_Dot({\n                    start: start,\n                    optional: optional === expr,\n                    expression: expr,\n                    property: as_name(),\n                    end: prev(),\n                });\n            } else if (is(\"punc\", \"`\")) {\n                if (optional) croak(\"Invalid template on optional chain\");\n                expr = template(expr);\n            } else {\n                break;\n            }\n        }\n        if (optional) expr.terminal = true;\n        if (expr instanceof AST_Call && !expr.pure) {\n            var start = expr.start;\n            var comments = start.comments_before;\n            var i = HOP(start, \"comments_before_length\") ? start.comments_before_length : comments.length;\n            while (--i >= 0) {\n                if (/[@#]__PURE__/.test(comments[i].value)) {\n                    expr.pure = true;\n                    break;\n                }\n            }\n        }\n        return expr;\n    }\n\n    function maybe_unary(no_in) {\n        var start = S.token;\n        if (S.in_async && is(\"name\", \"await\")) {\n            if (S.in_funarg === S.in_function) croak(\"Invalid use of await in function argument\");\n            S.input.context().regex_allowed = true;\n            next();\n            return new AST_Await({\n                start: start,\n                expression: maybe_unary(no_in),\n                end: prev(),\n            });\n        }\n        if (S.in_generator && is(\"name\", \"yield\")) {\n            if (S.in_funarg === S.in_function) croak(\"Invalid use of yield in function argument\");\n            S.input.context().regex_allowed = true;\n            next();\n            var exp = null;\n            var nested = false;\n            if (is(\"operator\", \"*\")) {\n                next();\n                exp = maybe_assign(no_in);\n                nested = true;\n            } else if (is(\"punc\") ? !PUNC_AFTER_EXPRESSION[S.token.value] : !can_insert_semicolon()) {\n                exp = maybe_assign(no_in);\n            }\n            return new AST_Yield({\n                start: start,\n                expression: exp,\n                nested: nested,\n                end: prev(),\n            });\n        }\n        if (is(\"operator\") && UNARY_PREFIX[start.value]) {\n            next();\n            handle_regexp();\n            var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(no_in));\n            ex.start = start;\n            ex.end = prev();\n            return ex;\n        }\n        var val = expr_atom(true);\n        while (is(\"operator\") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) {\n            val = make_unary(AST_UnaryPostfix, S.token, val);\n            val.start = start;\n            val.end = S.token;\n            next();\n        }\n        return val;\n    }\n\n    function make_unary(ctor, token, expr) {\n        var op = token.value;\n        switch (op) {\n          case \"++\":\n          case \"--\":\n            if (!is_assignable(expr))\n                token_error(token, \"Invalid use of \" + op + \" operator\");\n            break;\n          case \"delete\":\n            if (expr instanceof AST_SymbolRef && S.input.has_directive(\"use strict\"))\n                token_error(expr.start, \"Calling delete on expression not allowed in strict mode\");\n            break;\n        }\n        return new ctor({ operator: op, expression: expr });\n    }\n\n    var expr_op = function(left, min_precision, no_in) {\n        var op = is(\"operator\") ? S.token.value : null;\n        if (op == \"in\" && no_in) op = null;\n        var precision = op != null ? PRECEDENCE[op] : null;\n        if (precision != null && precision > min_precision) {\n            next();\n            var right = expr_op(maybe_unary(no_in), op == \"**\" ? precision - 1 : precision, no_in);\n            return expr_op(new AST_Binary({\n                start    : left.start,\n                left     : left,\n                operator : op,\n                right    : right,\n                end      : right.end,\n            }), min_precision, no_in);\n        }\n        return left;\n    };\n\n    function expr_ops(no_in) {\n        return expr_op(maybe_unary(no_in), 0, no_in);\n    }\n\n    var maybe_conditional = function(no_in) {\n        var start = S.token;\n        var expr = expr_ops(no_in);\n        if (is(\"operator\", \"?\")) {\n            next();\n            var yes = maybe_assign();\n            expect(\":\");\n            return new AST_Conditional({\n                start       : start,\n                condition   : expr,\n                consequent  : yes,\n                alternative : maybe_assign(no_in),\n                end         : prev()\n            });\n        }\n        return expr;\n    };\n\n    function is_assignable(expr) {\n        return expr instanceof AST_PropAccess && !expr.optional || expr instanceof AST_SymbolRef;\n    }\n\n    function to_destructured(node) {\n        if (node instanceof AST_Array) {\n            var rest = null;\n            if (node.elements[node.elements.length - 1] instanceof AST_Spread) {\n                rest = to_destructured(node.elements.pop().expression);\n                if (!(rest instanceof AST_Destructured || is_assignable(rest))) return node;\n            }\n            var elements = node.elements.map(to_destructured);\n            return all(elements, function(node) {\n                return node instanceof AST_DefaultValue\n                    || node instanceof AST_Destructured\n                    || node instanceof AST_Hole\n                    || is_assignable(node);\n            }) ? new AST_DestructuredArray({\n                start: node.start,\n                elements: elements,\n                rest: rest,\n                end: node.end,\n            }) : node;\n        }\n        if (node instanceof AST_Assign) {\n            var name = to_destructured(node.left);\n            return name instanceof AST_Destructured || is_assignable(name) ? new AST_DefaultValue({\n                start: node.start,\n                name: name,\n                value: node.right,\n                end: node.end,\n            }) : node;\n        }\n        if (!(node instanceof AST_Object)) return node;\n        var rest = null;\n        if (node.properties[node.properties.length - 1] instanceof AST_Spread) {\n            rest = to_destructured(node.properties.pop().expression);\n            if (!(rest instanceof AST_Destructured || is_assignable(rest))) return node;\n        }\n        var props = [];\n        for (var i = 0; i < node.properties.length; i++) {\n            var prop = node.properties[i];\n            if (!(prop instanceof AST_ObjectKeyVal)) return node;\n            var value = to_destructured(prop.value);\n            if (!(value instanceof AST_DefaultValue || value instanceof AST_Destructured || is_assignable(value))) {\n                return node;\n            }\n            props.push(new AST_DestructuredKeyVal({\n                start: prop.start,\n                key: prop.key,\n                value: value,\n                end: prop.end,\n            }));\n        }\n        return new AST_DestructuredObject({\n            start: node.start,\n            properties: props,\n            rest: rest,\n            end: node.end,\n        });\n    }\n\n    function maybe_assign(no_in) {\n        var start = S.token;\n        var left = maybe_conditional(no_in), val = S.token.value;\n        if (is(\"operator\") && ASSIGNMENT[val]) {\n            if (is_assignable(left) || val == \"=\" && (left = to_destructured(left)) instanceof AST_Destructured) {\n                next();\n                return new AST_Assign({\n                    start    : start,\n                    left     : left,\n                    operator : val,\n                    right    : maybe_assign(no_in),\n                    end      : prev()\n                });\n            }\n            croak(\"Invalid assignment\");\n        }\n        return left;\n    }\n\n    function expression(no_in, maybe_arrow) {\n        var start = S.token;\n        var exprs = [];\n        while (true) {\n            if (maybe_arrow && is(\"operator\", \"...\")) {\n                next();\n                exprs.rest = maybe_destructured(AST_SymbolFunarg);\n                break;\n            }\n            exprs.push(maybe_assign(no_in));\n            if (!is(\"punc\", \",\")) break;\n            next();\n            if (maybe_arrow && is(\"punc\", \")\") && is_token(peek(), \"punc\", \"=>\")) break;\n        }\n        return exprs.length == 1 && !exprs.rest ? exprs[0] : new AST_Sequence({\n            start: start,\n            expressions: exprs,\n            end: prev(),\n        });\n    }\n\n    function in_loop(cont) {\n        ++S.in_loop;\n        var ret = cont();\n        --S.in_loop;\n        return ret;\n    }\n\n    if (options.expression) {\n        handle_regexp();\n        var exp = expression();\n        expect_token(\"eof\");\n        return exp;\n    }\n\n    return function() {\n        var start = S.token;\n        var body = [];\n        if (options.module) {\n            S.in_async = true;\n            S.input.add_directive(\"use strict\");\n        }\n        S.input.push_directives_stack();\n        while (!is(\"eof\"))\n            body.push(statement(true));\n        S.input.pop_directives_stack();\n        var end = prev() || start;\n        var toplevel = options.toplevel;\n        if (toplevel) {\n            toplevel.body = toplevel.body.concat(body);\n            toplevel.end = end;\n        } else {\n            toplevel = new AST_Toplevel({ start: start, body: body, end: end });\n        }\n        return toplevel;\n    }();\n}\n"
  },
  {
    "path": "lib/propmangle.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction get_builtins() {\n    var names = new Dictionary();\n    // constants\n    [\n        \"NaN\",\n        \"null\",\n        \"true\",\n        \"false\",\n        \"Infinity\",\n        \"-Infinity\",\n        \"undefined\",\n    ].forEach(add);\n    // global functions\n    [\n        \"encodeURI\",\n        \"encodeURIComponent\",\n        \"escape\",\n        \"eval\",\n        \"decodeURI\",\n        \"decodeURIComponent\",\n        \"isFinite\",\n        \"isNaN\",\n        \"parseFloat\",\n        \"parseInt\",\n        \"unescape\",\n    ].forEach(add);\n    // global constructors & objects\n    var global = Function(\"return this\")();\n    [\n        \"Array\",\n        \"ArrayBuffer\",\n        \"Atomics\",\n        \"BigInt\",\n        \"Boolean\",\n        \"console\",\n        \"DataView\",\n        \"Date\",\n        \"Error\",\n        \"Function\",\n        \"Int8Array\",\n        \"Intl\",\n        \"JSON\",\n        \"Map\",\n        \"Math\",\n        \"Number\",\n        \"Object\",\n        \"Promise\",\n        \"Proxy\",\n        \"Reflect\",\n        \"RegExp\",\n        \"Set\",\n        \"String\",\n        \"Symbol\",\n        \"WebAssembly\",\n    ].forEach(function(name) {\n        add(name);\n        var ctor = global[name];\n        if (!ctor) return;\n        Object.getOwnPropertyNames(ctor).map(add);\n        if (typeof ctor != \"function\") return;\n        if (ctor.__proto__) Object.getOwnPropertyNames(ctor.__proto__).map(add);\n        if (ctor.prototype) Object.getOwnPropertyNames(ctor.prototype).map(add);\n        try {\n            Object.getOwnPropertyNames(new ctor()).map(add);\n        } catch (e) {\n            try {\n                Object.getOwnPropertyNames(ctor()).map(add);\n            } catch (e) {}\n        }\n    });\n    return (get_builtins = function() {\n        return names.clone();\n    })();\n\n    function add(name) {\n        names.set(name, true);\n    }\n}\n\nfunction reserve_quoted_keys(ast, reserved) {\n    ast.walk(new TreeWalker(function(node) {\n        if (node instanceof AST_ClassProperty\n            || node instanceof AST_DestructuredKeyVal\n            || node instanceof AST_ObjectProperty) {\n            if (node.key instanceof AST_Node) {\n                addStrings(node.key, add);\n            } else if (node.start && node.start.quote) {\n                add(node.key);\n            }\n        } else if (node instanceof AST_Dot) {\n            if (node.quoted) add(node.property);\n        } else if (node instanceof AST_Sub) {\n            addStrings(node.property, add);\n        }\n    }));\n\n    function add(name) {\n        push_uniq(reserved, name);\n    }\n}\n\nfunction addStrings(node, add) {\n    if (node instanceof AST_Conditional) {\n        addStrings(node.consequent, add);\n        addStrings(node.alternative, add);\n    } else if (node instanceof AST_Sequence) {\n        addStrings(node.tail_node(), add);\n    } else if (node instanceof AST_String) {\n        add(node.value);\n    }\n}\n\nfunction mangle_properties(ast, options) {\n    options = defaults(options, {\n        builtins: false,\n        cache: null,\n        debug: false,\n        domprops: false,\n        globals: false,\n        keep_quoted: false,\n        regex: null,\n        reserved: null,\n    }, true);\n\n    var is_global = options.globals ? function(prop_access) {\n        var exp = prop_access.expression;\n        return exp instanceof AST_SymbolRef && exp.definition().undeclared;\n    } : return_false;\n    var reserved = options.builtins ? new Dictionary() : get_builtins();\n    if (!options.domprops && typeof domprops !== \"undefined\") domprops.forEach(function(name) {\n        reserved.set(name, true);\n    });\n    if (Array.isArray(options.reserved)) options.reserved.forEach(function(name) {\n        reserved.set(name, true);\n    });\n\n    var cname = [ -1, -1 ];\n    var cache;\n    if (options.cache) {\n        cache = options.cache.props;\n        cache.each(function(name) {\n            reserved.set(name, true);\n        });\n    } else {\n        cache = new Dictionary();\n    }\n\n    var regex = options.regex;\n\n    // note debug is either false (disabled), or a string of the debug suffix to use (enabled).\n    // note debug may be enabled as an empty string, which is falsy. Also treat passing 'true'\n    // the same as passing an empty string.\n    var debug = options.debug !== false;\n    var debug_suffix;\n    if (debug) debug_suffix = options.debug === true ? \"\" : options.debug;\n\n    var names_to_mangle = new Dictionary();\n    var unmangleable = reserved.clone();\n\n    // step 1: find candidates to mangle\n    ast.walk(new TreeWalker(function(node) {\n        if (node.TYPE == \"Call\") {\n            var exp = node.expression;\n            if (exp instanceof AST_Dot) switch (exp.property) {\n              case \"defineProperty\":\n              case \"getOwnPropertyDescriptor\":\n                if (node.args.length < 2) break;\n                exp = exp.expression;\n                if (!(exp instanceof AST_SymbolRef)) break;\n                if (exp.name != \"Object\") break;\n                if (!exp.definition().undeclared) break;\n                addStrings(node.args[1], add);\n                break;\n              case \"hasOwnProperty\":\n                if (node.args.length < 1) break;\n                addStrings(node.args[0], add);\n                break;\n            }\n        } else if (node instanceof AST_ClassProperty\n            || node instanceof AST_DestructuredKeyVal\n            || node instanceof AST_ObjectProperty) {\n            if (node.key instanceof AST_Node) {\n                addStrings(node.key, add);\n            } else {\n                add(node.key);\n            }\n        } else if (node instanceof AST_Dot) {\n            if (is_global(node)) {\n                add_global(node.property);\n            } else if (is_lhs(node, this.parent())) {\n                add(node.property);\n            }\n        } else if (node instanceof AST_Sub) {\n            if (is_global(node)) {\n                addStrings(node.property, add_global);\n            } else if (is_lhs(node, this.parent())) {\n                addStrings(node.property, add);\n            }\n        }\n    }));\n\n    // step 2: renaming properties\n    ast.walk(new TreeWalker(function(node, descend) {\n        if (node instanceof AST_Binary) {\n            if (node.operator == \"in\") mangleStrings(node.left);\n        } else if (node.TYPE == \"Call\") {\n            var exp = node.expression;\n            if (exp instanceof AST_Dot) switch (exp.property) {\n              case \"defineProperty\":\n              case \"getOwnPropertyDescriptor\":\n                if (node.args.length < 2) break;\n                exp = exp.expression;\n                if (!(exp instanceof AST_SymbolRef)) break;\n                if (exp.name != \"Object\") break;\n                if (!exp.definition().undeclared) break;\n                mangleStrings(node.args[1]);\n                break;\n              case \"hasOwnProperty\":\n                if (node.args.length < 1) break;\n                mangleStrings(node.args[0]);\n                break;\n            }\n        } else if (node instanceof AST_Class) {\n            var save_cname = cname[1];\n            cname[1] = -1;\n            descend();\n            cname[1] = save_cname;\n            return true;\n        } else if (node instanceof AST_ClassProperty\n            || node instanceof AST_DestructuredKeyVal\n            || node instanceof AST_ObjectProperty) {\n            if (node.key instanceof AST_Node) {\n                mangleStrings(node.key);\n            } else {\n                node.key = mangle(node.key);\n            }\n        } else if (node instanceof AST_Dot) {\n            node.property = mangle(node.property);\n        } else if (node instanceof AST_Sub) {\n            if (!options.keep_quoted) mangleStrings(node.property);\n        }\n    }));\n\n    // only function declarations after this line\n\n    function can_mangle(name) {\n        if (unmangleable.has(name)) return false;\n        if (/^-?[0-9]+(\\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;\n        return true;\n    }\n\n    function should_mangle(name) {\n        if (reserved.has(name)) {\n            AST_Node.info(\"Preserving reserved property {this}\", name);\n            return false;\n        }\n        if (regex && !regex.test(name)) {\n            AST_Node.info(\"Preserving excluded property {this}\", name);\n            return false;\n        }\n        return cache.has(name) || names_to_mangle.has(name);\n    }\n\n    function add(name) {\n        if (can_mangle(name)) names_to_mangle.set(name, true);\n        if (!should_mangle(name)) unmangleable.set(name, true);\n    }\n\n    function add_global(name) {\n        add(name);\n        if (!should_mangle(name)) return;\n        var def = ast.globals.get(name);\n        if (!def) return;\n        var opts = Object.create(options);\n        opts.reserved = reserved.map(function(_, name) {\n            return name;\n        });\n        def.unmangleable = return_false;\n        def.mangle(_default_mangler_options(opts));\n        delete def.unmangleable;\n        var mangled_name = def.mangled_name || name;\n        cache.set(name, mangled_name);\n        unmangleable.set(mangled_name, true);\n    }\n\n    function mangle(name) {\n        if (!should_mangle(name)) return name;\n        var mangled = cache.get(name);\n        if (!mangled) {\n            if (debug) {\n                // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo ---> o._$foo$NNN_.\n                var debug_mangled = \"_$\" + name + \"$\" + debug_suffix + \"_\";\n                if (can_mangle(debug_mangled)) mangled = debug_mangled;\n            }\n            var hash = +/^#/.test(name);\n            // either debug mode is off, or it is on and we could not use the mangled name\n            if (!mangled) do {\n                mangled = base54(++cname[hash]);\n            } while (!can_mangle(mangled));\n            if (hash) mangled = \"#\" + mangled;\n            cache.set(name, mangled);\n        }\n        AST_Node.info(\"Mapping property {name} to {mangled}\", {\n            mangled: mangled,\n            name: name,\n        });\n        return mangled;\n    }\n\n    function mangleStrings(node) {\n        if (node instanceof AST_Sequence) {\n            mangleStrings(node.tail_node());\n        } else if (node instanceof AST_String) {\n            node.value = mangle(node.value);\n        } else if (node instanceof AST_Conditional) {\n            mangleStrings(node.consequent);\n            mangleStrings(node.alternative);\n        }\n    }\n}\n"
  },
  {
    "path": "lib/scope.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction SymbolDef(id, scope, orig, init) {\n    this._bits = 0;\n    this.defun = undefined;\n    this.eliminated = 0;\n    this.id = id;\n    this.init = init;\n    this.mangled_name = null;\n    this.name = orig.name;\n    this.orig = [ orig ];\n    this.references = [];\n    this.replaced = 0;\n    this.safe_ids = undefined;\n    this.scope = scope;\n}\n\nSymbolDef.prototype = {\n    forEach: function(fn) {\n        this.orig.forEach(fn);\n        this.references.forEach(fn);\n    },\n    mangle: function(options) {\n        if (this.mangled_name) return;\n        var cache = this.global && options.cache && options.cache.props;\n        if (cache && cache.has(this.name)) {\n            this.mangled_name = cache.get(this.name);\n        } else if (!this.unmangleable(options)) {\n            var def = this.redefined();\n            if (def) {\n                this.mangled_name = def.mangled_name || def.name;\n            } else {\n                this.mangled_name = next_mangled_name(this, options);\n            }\n            if (cache) cache.set(this.name, this.mangled_name);\n        }\n    },\n    redefined: function() {\n        var self = this;\n        var scope = self.defun;\n        if (!scope) return;\n        var name = self.name;\n        var def = scope.variables.get(name)\n            || scope instanceof AST_Toplevel && scope.globals.get(name)\n            || self.orig[0] instanceof AST_SymbolConst && find_if(function(def) {\n                return def.name == name;\n            }, scope.enclosed);\n        if (def && def !== self) return def.redefined() || def;\n    },\n    unmangleable: function(options) {\n        if (this.exported) return true;\n        if (this.undeclared) return true;\n        if (!options.eval && this.scope.pinned()) return true;\n        if (options.keep_fargs && is_funarg(this)) return true;\n        if (options.keep_fnames) {\n            var sym = this.orig[0];\n            if (sym instanceof AST_SymbolClass) return true;\n            if (sym instanceof AST_SymbolDefClass) return true;\n            if (sym instanceof AST_SymbolDefun) return true;\n            if (sym instanceof AST_SymbolLambda) return true;\n        }\n        if (!options.toplevel && this.global) return true;\n        return false;\n    },\n};\n\nDEF_BITPROPS(SymbolDef, [\n    \"const_redefs\",\n    \"cross_loop\",\n    \"direct_access\",\n    \"exported\",\n    \"global\",\n    \"undeclared\",\n]);\n\nfunction is_funarg(def) {\n    return def.orig[0] instanceof AST_SymbolFunarg || def.orig[1] instanceof AST_SymbolFunarg;\n}\n\nvar unary_side_effects = makePredicate(\"delete ++ --\");\n\nfunction is_lhs(node, parent) {\n    if (parent instanceof AST_Assign) return parent.left === node && node;\n    if (parent instanceof AST_DefaultValue) return parent.name === node && node;\n    if (parent instanceof AST_Destructured) return node;\n    if (parent instanceof AST_DestructuredKeyVal) return node;\n    if (parent instanceof AST_ForEnumeration) return parent.init === node && node;\n    if (parent instanceof AST_Unary) return unary_side_effects[parent.operator] && parent.expression;\n}\n\nAST_Toplevel.DEFMETHOD(\"figure_out_scope\", function(options) {\n    options = defaults(options, {\n        cache: null,\n        ie: false,\n    });\n\n    // pass 1: setup scope chaining and handle definitions\n    var self = this;\n    var defun = null;\n    var exported = false;\n    var next_def_id = 0;\n    var scope = self.parent_scope = null;\n    var tw = new TreeWalker(function(node, descend) {\n        if (node instanceof AST_DefClass) {\n            var save_exported = exported;\n            exported = tw.parent() instanceof AST_ExportDeclaration;\n            node.name.walk(tw);\n            exported = save_exported;\n            walk_scope(function() {\n                if (node.extends) node.extends.walk(tw);\n                node.properties.forEach(function(prop) {\n                    prop.walk(tw);\n                });\n            });\n            return true;\n        }\n        if (node instanceof AST_Definitions) {\n            var save_exported = exported;\n            exported = tw.parent() instanceof AST_ExportDeclaration;\n            descend();\n            exported = save_exported;\n            return true;\n        }\n        if (node instanceof AST_LambdaDefinition) {\n            var save_exported = exported;\n            exported = tw.parent() instanceof AST_ExportDeclaration;\n            node.name.walk(tw);\n            exported = save_exported;\n            walk_scope(function() {\n                node.argnames.forEach(function(argname) {\n                    argname.walk(tw);\n                });\n                if (node.rest) node.rest.walk(tw);\n                walk_body(node, tw);\n            });\n            return true;\n        }\n        if (node instanceof AST_Switch) {\n            node.expression.walk(tw);\n            walk_scope(function() {\n                walk_body(node, tw);\n            });\n            return true;\n        }\n        if (node instanceof AST_SwitchBranch) {\n            node.init_vars(scope);\n            descend();\n            return true;\n        }\n        if (node instanceof AST_Try) {\n            walk_scope(function() {\n                walk_body(node, tw);\n            });\n            if (node.bcatch) node.bcatch.walk(tw);\n            if (node.bfinally) node.bfinally.walk(tw);\n            return true;\n        }\n        if (node instanceof AST_With) {\n            var s = scope;\n            do {\n                s = s.resolve();\n                if (s.uses_with) break;\n                s.uses_with = true;\n            } while (s = s.parent_scope);\n            walk_scope(descend);\n            return true;\n        }\n        if (node instanceof AST_BlockScope) {\n            walk_scope(descend);\n            return true;\n        }\n        if (node instanceof AST_Symbol) {\n            node.scope = scope;\n        }\n        if (node instanceof AST_Label) {\n            node.thedef = node;\n            node.references = [];\n        }\n        if (node instanceof AST_SymbolCatch) {\n            scope.def_variable(node).defun = defun;\n        } else if (node instanceof AST_SymbolConst) {\n            var def = scope.def_variable(node);\n            def.defun = defun;\n            if (exported) def.exported = true;\n        } else if (node instanceof AST_SymbolDefun) {\n            var def = defun.def_function(node, tw.parent());\n            if (exported) def.exported = true;\n        } else if (node instanceof AST_SymbolFunarg) {\n            defun.def_variable(node);\n        } else if (node instanceof AST_SymbolLambda) {\n            var def = defun.def_function(node, node.name == \"arguments\" ? undefined : defun);\n            if (options.ie && node.name != \"arguments\") def.defun = defun.parent_scope.resolve();\n        } else if (node instanceof AST_SymbolLet) {\n            var def = scope.def_variable(node);\n            if (exported) def.exported = true;\n        } else if (node instanceof AST_SymbolVar) {\n            var def = defun.def_variable(node, node instanceof AST_SymbolImport ? undefined : null);\n            if (exported) def.exported = true;\n        }\n\n        function walk_scope(descend) {\n            node.init_vars(scope);\n            var save_defun = defun;\n            var save_scope = scope;\n            if (node instanceof AST_Scope) defun = node;\n            scope = node;\n            descend();\n            scope = save_scope;\n            defun = save_defun;\n        }\n    });\n    self.make_def = function(orig, init) {\n        return new SymbolDef(++next_def_id, this, orig, init);\n    };\n    self.walk(tw);\n\n    // pass 2: find back references and eval\n    self.globals = new Dictionary();\n    var in_arg = [];\n    var tw = new TreeWalker(function(node) {\n        if (node instanceof AST_Catch) {\n            if (!(node.argname instanceof AST_Destructured)) return;\n            in_arg.push(node);\n            node.argname.walk(tw);\n            in_arg.pop();\n            walk_body(node, tw);\n            return true;\n        }\n        if (node instanceof AST_Lambda) {\n            in_arg.push(node);\n            if (node.name) node.name.walk(tw);\n            node.argnames.forEach(function(argname) {\n                argname.walk(tw);\n            });\n            if (node.rest) node.rest.walk(tw);\n            in_arg.pop();\n            walk_lambda(node, tw);\n            return true;\n        }\n        if (node instanceof AST_LoopControl) {\n            if (node.label) node.label.thedef.references.push(node);\n            return true;\n        }\n        if (node instanceof AST_SymbolDeclaration) {\n            var def = node.definition();\n            def.preinit = def.references.length;\n            if (node instanceof AST_SymbolCatch) {\n                // ensure mangling works if `catch` reuses a scope variable\n                var redef = def.redefined();\n                if (redef) for (var s = node.scope; s; s = s.parent_scope) {\n                    if (!push_uniq(s.enclosed, redef)) break;\n                    if (s === redef.scope) break;\n                }\n            } else if (node instanceof AST_SymbolConst) {\n                // ensure compression works if `const` reuses a scope variable\n                var redef = def.redefined();\n                if (redef) redef.const_redefs = true;\n            } else if (def.scope !== node.scope && (node instanceof AST_SymbolDefun\n                || node instanceof AST_SymbolFunarg\n                || node instanceof AST_SymbolVar)) {\n                node.mark_enclosed(options);\n                var redef = node.scope.find_variable(node.name);\n                if (node.thedef !== redef) {\n                    node.thedef = redef;\n                    redef.orig.push(node);\n                    node.mark_enclosed(options);\n                }\n            }\n            if (node.name != \"arguments\") return true;\n            var parent = node instanceof AST_SymbolVar && tw.parent();\n            if (parent instanceof AST_VarDef && !parent.value) return true;\n            var sym = node.scope.resolve().find_variable(\"arguments\");\n            if (sym && is_arguments(sym)) sym.scope.uses_arguments = 3;\n            return true;\n        }\n        if (node instanceof AST_SymbolRef) {\n            var name = node.name;\n            var sym = node.scope.find_variable(name);\n            for (var i = in_arg.length; i > 0 && sym;) {\n                i = in_arg.lastIndexOf(sym.scope, i - 1);\n                if (i < 0) break;\n                var decl = sym.orig[0];\n                if (decl instanceof AST_SymbolCatch\n                    || decl instanceof AST_SymbolFunarg\n                    || decl instanceof AST_SymbolLambda) {\n                    node.in_arg = true;\n                    break;\n                }\n                sym = sym.scope.parent_scope.find_variable(name);\n            }\n            if (!sym) {\n                sym = self.def_global(node);\n            } else if (name == \"arguments\" && is_arguments(sym)) {\n                var parent = tw.parent();\n                if (is_lhs(node, parent)) {\n                    sym.scope.uses_arguments = 3;\n                } else if (sym.scope.uses_arguments < 2\n                    && !(parent instanceof AST_PropAccess && parent.expression === node)) {\n                    sym.scope.uses_arguments = 2;\n                } else if (!sym.scope.uses_arguments) {\n                    sym.scope.uses_arguments = true;\n                }\n            }\n            if (name == \"eval\") {\n                var parent = tw.parent();\n                if (parent.TYPE == \"Call\" && parent.expression === node) {\n                    var s = node.scope;\n                    do {\n                        s = s.resolve();\n                        if (s.uses_eval) break;\n                        s.uses_eval = true;\n                    } while (s = s.parent_scope);\n                } else if (sym.undeclared) {\n                    self.uses_eval = true;\n                }\n            }\n            if (sym.init instanceof AST_LambdaDefinition && sym.scope !== sym.init.name.scope) {\n                var scope = node.scope;\n                do {\n                    if (scope === sym.init.name.scope) break;\n                } while (scope = scope.parent_scope);\n                if (!scope) sym.init = undefined;\n            }\n            node.thedef = sym;\n            node.reference(options);\n            return true;\n        }\n    });\n    self.walk(tw);\n\n    // pass 3: fix up any scoping issue with IE8\n    if (options.ie) self.walk(new TreeWalker(function(node) {\n        if (node instanceof AST_SymbolCatch) {\n            var def = node.thedef;\n            var scope = def.defun;\n            if (def.name != \"arguments\" && scope.name instanceof AST_SymbolLambda && scope.name.name == def.name) {\n                scope = scope.parent_scope.resolve();\n            }\n            redefine(node, scope);\n            return true;\n        }\n        if (node instanceof AST_SymbolLambda) {\n            var def = node.thedef;\n            if (!redefine(node, node.scope.parent_scope.resolve())) {\n                def.defun = undefined;\n            } else if (typeof node.thedef.init !== \"undefined\") {\n                node.thedef.init = false;\n            } else if (def.init) {\n                node.thedef.init = def.init;\n            }\n            return true;\n        }\n    }));\n\n    function is_arguments(sym) {\n        return sym.orig[0] instanceof AST_SymbolFunarg\n            && !(sym.orig[1] instanceof AST_SymbolFunarg || sym.orig[2] instanceof AST_SymbolFunarg)\n            && !is_arrow(sym.scope);\n    }\n\n    function redefine(node, scope) {\n        var name = node.name;\n        var old_def = node.thedef;\n        if (!all(old_def.orig, function(sym) {\n            return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet);\n        })) return false;\n        var new_def = scope.find_variable(name);\n        if (new_def) {\n            var redef = new_def.redefined();\n            if (redef) new_def = redef;\n        } else {\n            new_def = self.globals.get(name);\n        }\n        if (new_def) {\n            new_def.orig.push(node);\n        } else {\n            new_def = scope.def_variable(node);\n        }\n        if (new_def.undeclared) self.variables.set(name, new_def);\n        if (name == \"arguments\" && is_arguments(old_def) && node instanceof AST_SymbolLambda) return true;\n        old_def.defun = new_def.scope;\n        old_def.forEach(function(node) {\n            node.redef = old_def;\n            node.thedef = new_def;\n            node.reference(options);\n        });\n        return true;\n    }\n});\n\nAST_Toplevel.DEFMETHOD(\"def_global\", function(node) {\n    var globals = this.globals, name = node.name;\n    if (globals.has(name)) {\n        return globals.get(name);\n    } else {\n        var g = this.make_def(node);\n        g.undeclared = true;\n        g.global = true;\n        globals.set(name, g);\n        return g;\n    }\n});\n\nfunction init_block_vars(scope, parent, orig) {\n    // variables from this or outer scope(s) that are referenced from this or inner scopes\n    scope.enclosed = orig ? orig.enclosed.slice() : [];\n    // map name to AST_SymbolDefun (functions defined in this scope)\n    scope.functions = orig ? orig.functions.clone() : new Dictionary();\n    // map name to AST_SymbolVar (variables defined in this scope; includes functions)\n    scope.variables = orig ? orig.variables.clone() : new Dictionary();\n    if (!parent) return;\n    // top-level tracking of SymbolDef instances\n    scope.make_def = parent.make_def;\n    // the parent scope (null if this is the top level)\n    scope.parent_scope = parent;\n}\n\nfunction init_scope_vars(scope, parent, orig) {\n    init_block_vars(scope, parent, orig);\n    // will be set to true if this or nested scope uses the global `eval`\n    scope.uses_eval = false;\n    // will be set to true if this or some nested scope uses the `with` statement\n    scope.uses_with = false;\n}\n\nAST_BlockScope.DEFMETHOD(\"init_vars\", function(parent, orig) {\n    init_block_vars(this, parent, orig);\n});\nAST_Scope.DEFMETHOD(\"init_vars\", function(parent, orig) {\n    init_scope_vars(this, parent, orig);\n});\nAST_Arrow.DEFMETHOD(\"init_vars\", function(parent, orig) {\n    init_scope_vars(this, parent, orig);\n    return this;\n});\nAST_AsyncArrow.DEFMETHOD(\"init_vars\", function(parent, orig) {\n    init_scope_vars(this, parent, orig);\n});\nAST_Lambda.DEFMETHOD(\"init_vars\", function(parent, orig) {\n    init_scope_vars(this, parent, orig);\n    this.uses_arguments = false;\n    this.def_variable(new AST_SymbolFunarg({\n        name: \"arguments\",\n        scope: this,\n        start: this.start,\n        end: this.end,\n    }));\n    return this;\n});\n\nAST_Symbol.DEFMETHOD(\"mark_enclosed\", function(options) {\n    var def = this.definition();\n    for (var s = this.scope; s; s = s.parent_scope) {\n        if (!push_uniq(s.enclosed, def)) break;\n        if (!options) {\n            s._var_names = undefined;\n        } else {\n            if (options.keep_fargs && s instanceof AST_Lambda) s.each_argname(function(arg) {\n                push_uniq(def.scope.enclosed, arg.definition());\n            });\n            if (options.keep_fnames) s.functions.each(function(d) {\n                push_uniq(def.scope.enclosed, d);\n            });\n        }\n        if (s === def.scope) break;\n    }\n});\n\nAST_Symbol.DEFMETHOD(\"reference\", function(options) {\n    this.definition().references.push(this);\n    this.mark_enclosed(options);\n});\n\nAST_BlockScope.DEFMETHOD(\"find_variable\", function(name) {\n    return this.variables.get(name)\n        || this.parent_scope && this.parent_scope.find_variable(name);\n});\n\nAST_BlockScope.DEFMETHOD(\"def_function\", function(symbol, init) {\n    var def = this.def_variable(symbol, init);\n    if (!def.init || def.init instanceof AST_LambdaDefinition) def.init = init;\n    this.functions.set(symbol.name, def);\n    return def;\n});\n\nAST_BlockScope.DEFMETHOD(\"def_variable\", function(symbol, init) {\n    var def = this.variables.get(symbol.name);\n    if (def) {\n        def.orig.push(symbol);\n        if (def.init instanceof AST_LambdaExpression) def.init = init;\n    } else {\n        def = this.make_def(symbol, init);\n        this.variables.set(symbol.name, def);\n        def.global = !this.parent_scope;\n    }\n    return symbol.thedef = def;\n});\n\nfunction names_in_use(scope, options) {\n    var names = scope.names_in_use;\n    if (!names) {\n        scope.cname = -1;\n        scope.cname_holes = [];\n        scope.names_in_use = names = new Dictionary();\n        var cache = options.cache && options.cache.props;\n        scope.enclosed.forEach(function(def) {\n            if (def.unmangleable(options)) names.set(def.name, true);\n            if (def.global && cache && cache.has(def.name)) {\n                names.set(cache.get(def.name), true);\n            }\n        });\n    }\n    return names;\n}\n\nfunction next_mangled_name(def, options) {\n    var scope = def.scope;\n    var in_use = names_in_use(scope, options);\n    var holes = scope.cname_holes;\n    var names = new Dictionary();\n    var scopes = [ scope ];\n    def.forEach(function(sym) {\n        var scope = sym.scope;\n        do {\n            if (member(scope, scopes)) break;\n            names_in_use(scope, options).each(function(marker, name) {\n                names.set(name, marker);\n            });\n            scopes.push(scope);\n        } while (scope = scope.parent_scope);\n    });\n    var name;\n    for (var i = 0; i < holes.length; i++) {\n        name = base54(holes[i]);\n        if (names.has(name)) continue;\n        holes.splice(i, 1);\n        in_use.set(name, true);\n        return name;\n    }\n    while (true) {\n        name = base54(++scope.cname);\n        if (in_use.has(name) || RESERVED_WORDS[name] || options.reserved.has[name]) continue;\n        if (!names.has(name)) break;\n        holes.push(scope.cname);\n    }\n    in_use.set(name, true);\n    return name;\n}\n\nAST_Symbol.DEFMETHOD(\"unmangleable\", function(options) {\n    var def = this.definition();\n    return !def || def.unmangleable(options);\n});\n\n// labels are always mangleable\nAST_Label.DEFMETHOD(\"unmangleable\", return_false);\n\nAST_Symbol.DEFMETHOD(\"definition\", function() {\n    return this.thedef;\n});\n\nfunction _default_mangler_options(options) {\n    options = defaults(options, {\n        eval        : false,\n        ie          : false,\n        keep_fargs  : false,\n        keep_fnames : false,\n        reserved    : [],\n        toplevel    : false,\n        v8          : false,\n        webkit      : false,\n    });\n    if (!Array.isArray(options.reserved)) options.reserved = [];\n    // Never mangle `arguments`\n    push_uniq(options.reserved, \"arguments\");\n    options.reserved.has = makePredicate(options.reserved);\n    return options;\n}\n\n// We only need to mangle declaration nodes. Special logic wired into the code\n// generator will display the mangled name if it is present (and for\n// `AST_SymbolRef`s it will use the mangled name of the `AST_SymbolDeclaration`\n// that it points to).\nAST_Toplevel.DEFMETHOD(\"mangle_names\", function(options) {\n    options = _default_mangler_options(options);\n    if (options.cache && options.cache.props) {\n        var mangled_names = names_in_use(this, options);\n        options.cache.props.each(function(mangled_name) {\n            mangled_names.set(mangled_name, true);\n        });\n    }\n    var cutoff = 36;\n    var lname = -1;\n    var redefined = [];\n    var tw = new TreeWalker(function(node, descend) {\n        var save_nesting;\n        if (node instanceof AST_BlockScope) {\n            // `lname` is incremented when we get to the `AST_Label`\n            if (node instanceof AST_LabeledStatement) save_nesting = lname;\n            if (options.webkit && node instanceof AST_IterationStatement && node.init instanceof AST_Let) {\n                node.init.definitions.forEach(function(defn) {\n                    defn.name.match_symbol(function(sym) {\n                        if (!(sym instanceof AST_SymbolLet)) return;\n                        var def = sym.definition();\n                        var scope = sym.scope.parent_scope;\n                        var redef = scope.def_variable(sym);\n                        sym.thedef = def;\n                        scope.to_mangle.push(redef);\n                        def.redefined = function() {\n                            return redef;\n                        };\n                    });\n                }, true);\n            }\n            var to_mangle = node.to_mangle = [];\n            node.variables.each(function(def, name) {\n                if (def.unmangleable(options)) {\n                    names_in_use(node, options).set(name, true);\n                } else if (!defer_redef(def)) {\n                    to_mangle.push(def);\n                }\n            });\n            descend();\n            if (options.cache && node instanceof AST_Toplevel) {\n                node.globals.each(mangle);\n            }\n            if (node instanceof AST_Defun && tw.has_directive(\"use asm\")) {\n                var sym = new AST_SymbolRef(node.name);\n                sym.scope = node;\n                sym.reference(options);\n            }\n            if (to_mangle.length > cutoff) {\n                var indices = to_mangle.map(function(def, index) {\n                    return index;\n                }).sort(function(i, j) {\n                    return to_mangle[j].references.length - to_mangle[i].references.length || i - j;\n                });\n                to_mangle = indices.slice(0, cutoff).sort(function(i, j) {\n                    return i - j;\n                }).map(function(index) {\n                    return to_mangle[index];\n                }).concat(indices.slice(cutoff).sort(function(i, j) {\n                    return i - j;\n                }).map(function(index) {\n                    return to_mangle[index];\n                }));\n            }\n            to_mangle.forEach(mangle);\n            if (node instanceof AST_LabeledStatement && !(options.v8 && in_label(tw))) lname = save_nesting;\n            return true;\n        }\n        if (node instanceof AST_Label) {\n            var name;\n            do {\n                name = base54(++lname);\n            } while (RESERVED_WORDS[name]);\n            node.mangled_name = name;\n            return true;\n        }\n    });\n    this.walk(tw);\n    redefined.forEach(mangle);\n\n    function mangle(def) {\n        if (options.reserved.has[def.name]) return;\n        def.mangle(options);\n    }\n\n    function defer_redef(def) {\n        var sym = def.orig[0];\n        var redef = def.redefined();\n        if (!redef) {\n            if (!(sym instanceof AST_SymbolConst)) return false;\n            var scope = def.scope.resolve();\n            if (def.scope === scope) return false;\n            if (def.scope.parent_scope.find_variable(sym.name)) return false;\n            redef = scope.def_variable(sym);\n            scope.to_mangle.push(redef);\n        }\n        redefined.push(def);\n        def.references.forEach(reference);\n        if (sym instanceof AST_SymbolCatch || sym instanceof AST_SymbolConst) {\n            reference(sym);\n            def.redefined = function() {\n                return redef;\n            };\n        }\n        return true;\n\n        function reference(sym) {\n            sym.thedef = redef;\n            sym.reference(options);\n            sym.thedef = def;\n        }\n    }\n\n    function in_label(tw) {\n        var level = 0, parent;\n        while (parent = tw.parent(level++)) {\n            if (parent instanceof AST_Block) return parent instanceof AST_Toplevel && !options.toplevel;\n            if (parent instanceof AST_LabeledStatement) return true;\n        }\n    }\n});\n\nAST_Toplevel.DEFMETHOD(\"find_colliding_names\", function(options) {\n    var cache = options.cache && options.cache.props;\n    var avoid = Object.create(RESERVED_WORDS);\n    options.reserved.forEach(to_avoid);\n    this.globals.each(add_def);\n    this.walk(new TreeWalker(function(node) {\n        if (node instanceof AST_BlockScope) node.variables.each(add_def);\n    }));\n    return avoid;\n\n    function to_avoid(name) {\n        avoid[name] = true;\n    }\n\n    function add_def(def) {\n        var name = def.name;\n        if (def.global && cache && cache.has(name)) name = cache.get(name);\n        else if (!def.unmangleable(options)) return;\n        to_avoid(name);\n    }\n});\n\nAST_Toplevel.DEFMETHOD(\"expand_names\", function(options) {\n    base54.reset();\n    base54.sort();\n    options = _default_mangler_options(options);\n    var avoid = this.find_colliding_names(options);\n    var cname = 0;\n    this.globals.each(rename);\n    this.walk(new TreeWalker(function(node) {\n        if (node instanceof AST_BlockScope) node.variables.each(rename);\n    }));\n\n    function next_name() {\n        var name;\n        do {\n            name = base54(cname++);\n        } while (avoid[name]);\n        return name;\n    }\n\n    function rename(def) {\n        if (def.global && options.cache) return;\n        if (def.unmangleable(options)) return;\n        if (options.reserved.has[def.name]) return;\n        var redef = def.redefined();\n        var name = redef ? redef.rename || redef.name : next_name();\n        def.rename = name;\n        def.forEach(function(sym) {\n            if (sym.definition() === def) sym.name = name;\n        });\n    }\n});\n\nAST_Node.DEFMETHOD(\"tail_node\", return_this);\nAST_Sequence.DEFMETHOD(\"tail_node\", function() {\n    return this.expressions[this.expressions.length - 1];\n});\n\nAST_Toplevel.DEFMETHOD(\"compute_char_frequency\", function(options) {\n    options = _default_mangler_options(options);\n    base54.reset();\n    var fn = AST_Symbol.prototype.add_source_map;\n    try {\n        AST_Symbol.prototype.add_source_map = function() {\n            if (!this.unmangleable(options)) base54.consider(this.name, -1);\n        };\n        if (options.properties) {\n            AST_Dot.prototype.add_source_map = function() {\n                base54.consider(this.property, -1);\n            };\n            AST_Sub.prototype.add_source_map = function() {\n                skip_string(this.property);\n            };\n        }\n        base54.consider(this.print_to_string(), 1);\n    } finally {\n        AST_Symbol.prototype.add_source_map = fn;\n        delete AST_Dot.prototype.add_source_map;\n        delete AST_Sub.prototype.add_source_map;\n    }\n    base54.sort();\n\n    function skip_string(node) {\n        if (node instanceof AST_String) {\n            base54.consider(node.value, -1);\n        } else if (node instanceof AST_Conditional) {\n            skip_string(node.consequent);\n            skip_string(node.alternative);\n        } else if (node instanceof AST_Sequence) {\n            skip_string(node.tail_node());\n        }\n    }\n});\n\nvar base54 = (function() {\n    var freq = Object.create(null);\n    function init(chars) {\n        var array = [];\n        for (var i = 0; i < chars.length; i++) {\n            var ch = chars[i];\n            array.push(ch);\n            freq[ch] = -1e-2 * i;\n        }\n        return array;\n    }\n    var digits = init(\"0123456789\");\n    var leading = init(\"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_\");\n    var chars, frequency;\n    function reset() {\n        chars = null;\n        frequency = Object.create(freq);\n    }\n    base54.consider = function(str, delta) {\n        for (var i = str.length; --i >= 0;) {\n            frequency[str[i]] += delta;\n        }\n    };\n    function compare(a, b) {\n        return frequency[b] - frequency[a];\n    }\n    base54.sort = function() {\n        chars = leading.sort(compare).concat(digits).sort(compare);\n    };\n    base54.reset = reset;\n    reset();\n    function base54(num) {\n        var ret = leading[num % 54];\n        for (num = Math.floor(num / 54); --num >= 0; num >>= 6) {\n            ret += chars[num & 0x3F];\n        }\n        return ret;\n    }\n    return base54;\n})();\n"
  },
  {
    "path": "lib/sourcemap.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nvar vlq_char = characters(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\");\nvar vlq_bits = vlq_char.reduce(function(map, ch, bits) {\n    map[ch] = bits;\n    return map;\n}, Object.create(null));\n\nfunction vlq_decode(indices, str) {\n    var value = 0;\n    var shift = 0;\n    for (var i = 0, j = 0; i < str.length; i++) {\n        var bits = vlq_bits[str[i]];\n        value += (bits & 31) << shift;\n        if (bits & 32) {\n            shift += 5;\n        } else {\n            indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;\n            value = shift = 0;\n        }\n    }\n    return j;\n}\n\nfunction vlq_encode(num) {\n    var result = \"\";\n    num = Math.abs(num) << 1 | num >>> 31;\n    do {\n        var bits = num & 31;\n        if (num >>>= 5) bits |= 32;\n        result += vlq_char[bits];\n    } while (num);\n    return result;\n}\n\nfunction create_array_map() {\n    var map = new Dictionary();\n    var array = [];\n    array.index = function(name) {\n        var index = map.get(name);\n        if (!(index >= 0)) {\n            index = array.length;\n            array.push(name);\n            map.set(name, index);\n        }\n        return index;\n    };\n    return array;\n}\n\nfunction SourceMap(options) {\n    var sources = create_array_map();\n    var sources_content = options.includeSources && new Dictionary();\n    var names = create_array_map();\n    var mappings = \"\";\n    if (options.orig) Object.keys(options.orig).forEach(function(name) {\n        var map = options.orig[name];\n        var indices = [ 0, 0, 1, 0, 0 ];\n        options.orig[name] = {\n            names: map.names,\n            mappings: map.mappings.split(/;/).map(function(line) {\n                indices[0] = 0;\n                return line.split(/,/).map(function(segment) {\n                    return indices.slice(0, vlq_decode(indices, segment));\n                });\n            }),\n            sources: map.sources,\n        };\n        if (!sources_content || !map.sourcesContent) return;\n        for (var i = 0; i < map.sources.length; i++) {\n            var content = map.sourcesContent[i];\n            if (content) sources_content.set(map.sources[i], content);\n        }\n    });\n    var prev_source;\n    var generated_line = 1;\n    var generated_column = 0;\n    var source_index = 0;\n    var original_line = 1;\n    var original_column = 0;\n    var name_index = 0;\n    return {\n        add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {\n            var map = options.orig[source];\n            if (map) {\n                var segments = map.mappings[orig_line - 1];\n                if (!segments) return;\n                var indices;\n                for (var i = 0; i < segments.length; i++) {\n                    var col = segments[i][0];\n                    if (orig_col >= col) indices = segments[i];\n                    if (orig_col <= col) break;\n                }\n                if (!indices || indices.length < 4) {\n                    source = null;\n                } else {\n                    source = map.sources[indices[1]];\n                    orig_line = indices[2];\n                    orig_col = indices[3];\n                    if (indices.length > 4) name = map.names[indices[4]];\n                }\n            }\n            add(source, gen_line, gen_col, orig_line, orig_col, name);\n        } : add,\n        setSourceContent: sources_content ? function(source, content) {\n            if (!sources_content.has(source)) {\n                sources_content.set(source, content);\n            }\n        } : noop,\n        toString: function() {\n            return JSON.stringify({\n                version: 3,\n                file: options.filename || undefined,\n                sourceRoot: options.root || undefined,\n                sources: sources,\n                sourcesContent: sources_content ? sources.map(function(source) {\n                    return sources_content.get(source) || null;\n                }) : undefined,\n                names: names,\n                mappings: mappings,\n            });\n        }\n    };\n\n    function add(source, gen_line, gen_col, orig_line, orig_col, name) {\n        if (prev_source == null && source == null) return;\n        prev_source = source;\n        if (generated_line < gen_line) {\n            generated_column = 0;\n            do {\n                mappings += \";\";\n            } while (++generated_line < gen_line);\n        } else if (mappings) {\n            mappings += \",\";\n        }\n        mappings += vlq_encode(gen_col - generated_column);\n        generated_column = gen_col;\n        if (source == null) return;\n        var src_idx = sources.index(source);\n        mappings += vlq_encode(src_idx - source_index);\n        source_index = src_idx;\n        mappings += vlq_encode(orig_line - original_line);\n        original_line = orig_line;\n        mappings += vlq_encode(orig_col - original_column);\n        original_column = orig_col;\n        if (options.names && name != null) {\n            var name_idx = names.index(name);\n            mappings += vlq_encode(name_idx - name_index);\n            name_index = name_idx;\n        }\n    }\n}\n"
  },
  {
    "path": "lib/transform.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction TreeTransformer(before, after) {\n    TreeWalker.call(this);\n    this.before = before;\n    this.after = after;\n}\nTreeTransformer.prototype = new TreeWalker;\n\n(function(DEF) {\n    function do_list(list, tw) {\n        return List(list, function(node) {\n            return node.transform(tw, true);\n        });\n    }\n\n    DEF(AST_Node, noop);\n    DEF(AST_LabeledStatement, function(self, tw) {\n        self.label = self.label.transform(tw);\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_SimpleStatement, function(self, tw) {\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_Block, function(self, tw) {\n        self.body = do_list(self.body, tw);\n    });\n    DEF(AST_Do, function(self, tw) {\n        self.body = self.body.transform(tw);\n        self.condition = self.condition.transform(tw);\n    });\n    DEF(AST_While, function(self, tw) {\n        self.condition = self.condition.transform(tw);\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_For, function(self, tw) {\n        if (self.init) self.init = self.init.transform(tw);\n        if (self.condition) self.condition = self.condition.transform(tw);\n        if (self.step) self.step = self.step.transform(tw);\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_ForEnumeration, function(self, tw) {\n        self.init = self.init.transform(tw);\n        self.object = self.object.transform(tw);\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_With, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_Exit, function(self, tw) {\n        if (self.value) self.value = self.value.transform(tw);\n    });\n    DEF(AST_LoopControl, function(self, tw) {\n        if (self.label) self.label = self.label.transform(tw);\n    });\n    DEF(AST_If, function(self, tw) {\n        self.condition = self.condition.transform(tw);\n        self.body = self.body.transform(tw);\n        if (self.alternative) self.alternative = self.alternative.transform(tw);\n    });\n    DEF(AST_Switch, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n        self.body = do_list(self.body, tw);\n    });\n    DEF(AST_Case, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n        self.body = do_list(self.body, tw);\n    });\n    DEF(AST_Try, function(self, tw) {\n        self.body = do_list(self.body, tw);\n        if (self.bcatch) self.bcatch = self.bcatch.transform(tw);\n        if (self.bfinally) self.bfinally = self.bfinally.transform(tw);\n    });\n    DEF(AST_Catch, function(self, tw) {\n        if (self.argname) self.argname = self.argname.transform(tw);\n        self.body = do_list(self.body, tw);\n    });\n    DEF(AST_Definitions, function(self, tw) {\n        self.definitions = do_list(self.definitions, tw);\n    });\n    DEF(AST_VarDef, function(self, tw) {\n        self.name = self.name.transform(tw);\n        if (self.value) self.value = self.value.transform(tw);\n    });\n    DEF(AST_DefaultValue, function(self, tw) {\n        self.name = self.name.transform(tw);\n        self.value = self.value.transform(tw);\n    });\n    DEF(AST_Lambda, function(self, tw) {\n        if (self.name) self.name = self.name.transform(tw);\n        self.argnames = do_list(self.argnames, tw);\n        if (self.rest) self.rest = self.rest.transform(tw);\n        self.body = do_list(self.body, tw);\n    });\n    function transform_arrow(self, tw) {\n        self.argnames = do_list(self.argnames, tw);\n        if (self.rest) self.rest = self.rest.transform(tw);\n        if (self.value) {\n            self.value = self.value.transform(tw);\n        } else {\n            self.body = do_list(self.body, tw);\n        }\n    }\n    DEF(AST_Arrow, transform_arrow);\n    DEF(AST_AsyncArrow, transform_arrow);\n    DEF(AST_Class, function(self, tw) {\n        if (self.name) self.name = self.name.transform(tw);\n        if (self.extends) self.extends = self.extends.transform(tw);\n        self.properties = do_list(self.properties, tw);\n    });\n    DEF(AST_ClassProperty, function(self, tw) {\n        if (self.key instanceof AST_Node) self.key = self.key.transform(tw);\n        if (self.value) self.value = self.value.transform(tw);\n    });\n    DEF(AST_Call, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n        self.args = do_list(self.args, tw);\n    });\n    DEF(AST_Sequence, function(self, tw) {\n        self.expressions = do_list(self.expressions, tw);\n    });\n    DEF(AST_Await, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n    });\n    DEF(AST_Yield, function(self, tw) {\n        if (self.expression) self.expression = self.expression.transform(tw);\n    });\n    DEF(AST_Dot, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n    });\n    DEF(AST_Sub, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n        self.property = self.property.transform(tw);\n    });\n    DEF(AST_Spread, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n    });\n    DEF(AST_Unary, function(self, tw) {\n        self.expression = self.expression.transform(tw);\n    });\n    DEF(AST_Binary, function(self, tw) {\n        self.left = self.left.transform(tw);\n        self.right = self.right.transform(tw);\n    });\n    DEF(AST_Conditional, function(self, tw) {\n        self.condition = self.condition.transform(tw);\n        self.consequent = self.consequent.transform(tw);\n        self.alternative = self.alternative.transform(tw);\n    });\n    DEF(AST_Array, function(self, tw) {\n        self.elements = do_list(self.elements, tw);\n    });\n    DEF(AST_DestructuredArray, function(self, tw) {\n        self.elements = do_list(self.elements, tw);\n        if (self.rest) self.rest = self.rest.transform(tw);\n    });\n    DEF(AST_DestructuredKeyVal, function(self, tw) {\n        if (self.key instanceof AST_Node) self.key = self.key.transform(tw);\n        self.value = self.value.transform(tw);\n    });\n    DEF(AST_DestructuredObject, function(self, tw) {\n        self.properties = do_list(self.properties, tw);\n        if (self.rest) self.rest = self.rest.transform(tw);\n    });\n    DEF(AST_Object, function(self, tw) {\n        self.properties = do_list(self.properties, tw);\n    });\n    DEF(AST_ObjectProperty, function(self, tw) {\n        if (self.key instanceof AST_Node) self.key = self.key.transform(tw);\n        self.value = self.value.transform(tw);\n    });\n    DEF(AST_ExportDeclaration, function(self, tw) {\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_ExportDefault, function(self, tw) {\n        self.body = self.body.transform(tw);\n    });\n    DEF(AST_ExportReferences, function(self, tw) {\n        self.properties = do_list(self.properties, tw);\n    });\n    DEF(AST_Import, function(self, tw) {\n        if (self.all) self.all = self.all.transform(tw);\n        if (self.default) self.default = self.default.transform(tw);\n        if (self.properties) self.properties = do_list(self.properties, tw);\n    });\n    DEF(AST_Template, function(self, tw) {\n        if (self.tag) self.tag = self.tag.transform(tw);\n        self.expressions = do_list(self.expressions, tw);\n    });\n})(function(node, descend) {\n    node.DEFMETHOD(\"transform\", function(tw, in_list) {\n        var x, y;\n        tw.push(this);\n        if (tw.before) x = tw.before(this, descend, in_list);\n        if (typeof x === \"undefined\") {\n            x = this;\n            descend(x, tw);\n            if (tw.after) {\n                y = tw.after(x, in_list);\n                if (typeof y !== \"undefined\") x = y;\n            }\n        }\n        tw.pop();\n        return x;\n    });\n});\n"
  },
  {
    "path": "lib/utils.js",
    "content": "/***********************************************************************\n\n  A JavaScript tokenizer / parser / beautifier / compressor.\n  https://github.com/mishoo/UglifyJS\n\n  -------------------------------- (C) ---------------------------------\n\n                           Author: Mihai Bazon\n                         <mihai.bazon@gmail.com>\n                       http://mihai.bazon.net/blog\n\n  Distributed under the BSD license:\n\n    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n    Redistribution and use in source and binary forms, with or without\n    modification, are permitted provided that the following conditions\n    are met:\n\n        * Redistributions of source code must retain the above\n          copyright notice, this list of conditions and the following\n          disclaimer.\n\n        * Redistributions in binary form must reproduce the above\n          copyright notice, this list of conditions and the following\n          disclaimer in the documentation and/or other materials\n          provided with the distribution.\n\n    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY\n    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n    SUCH DAMAGE.\n\n ***********************************************************************/\n\n\"use strict\";\n\nfunction characters(str) {\n    return str.split(\"\");\n}\n\nfunction member(name, array) {\n    return array.indexOf(name) >= 0;\n}\n\nfunction find_if(func, array) {\n    for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];\n}\n\nfunction configure_error_stack(ex, cause) {\n    var stack = ex.name + \": \" + ex.message;\n    Object.defineProperty(ex, \"stack\", {\n        get: function() {\n            if (cause) {\n                cause.name = \"\" + ex.name;\n                stack = \"\" + cause.stack;\n                var msg = \"\" + cause.message;\n                cause = null;\n                var index = stack.indexOf(msg);\n                if (index < 0) {\n                    index = 0;\n                } else {\n                    index += msg.length;\n                    index = stack.indexOf(\"\\n\", index) + 1;\n                }\n                stack = stack.slice(0, index) + stack.slice(stack.indexOf(\"\\n\", index) + 1);\n            }\n            return stack;\n        },\n    });\n}\n\nfunction DefaultsError(msg, defs) {\n    this.message = msg;\n    this.defs = defs;\n    try {\n        throw new Error(msg);\n    } catch (cause) {\n        configure_error_stack(this, cause);\n    }\n}\nDefaultsError.prototype = Object.create(Error.prototype);\nDefaultsError.prototype.constructor = DefaultsError;\nDefaultsError.prototype.name = \"DefaultsError\";\n\nfunction defaults(args, defs, croak) {\n    if (croak) for (var i in args) {\n        if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError(\"`\" + i + \"` is not a supported option\", defs);\n    }\n    for (var i in args) {\n        if (HOP(args, i)) defs[i] = args[i];\n    }\n    return defs;\n}\n\nfunction noop() {}\nfunction return_false() { return false; }\nfunction return_true() { return true; }\nfunction return_this() { return this; }\nfunction return_null() { return null; }\n\nvar List = (function() {\n    function List(a, f) {\n        var ret = [];\n        for (var i = 0; i < a.length; i++) {\n            var val = f(a[i], i);\n            if (val === skip) continue;\n            if (val instanceof Splice) {\n                ret.push.apply(ret, val.v);\n            } else {\n                ret.push(val);\n            }\n        }\n        return ret;\n    }\n    List.is_op = function(val) {\n        return val === skip || val instanceof Splice;\n    };\n    List.splice = function(val) {\n        return new Splice(val);\n    };\n    var skip = List.skip = {};\n    function Splice(val) {\n        this.v = val;\n    }\n    return List;\n})();\n\nfunction push_uniq(array, el) {\n    if (array.indexOf(el) < 0) return array.push(el);\n}\n\nfunction string_template(text, props) {\n    return text.replace(/\\{([^{}]+)\\}/g, function(str, p) {\n        var value = p == \"this\" ? props : props[p];\n        if (value instanceof AST_Node) return value.print_to_string();\n        if (value instanceof AST_Token) return value.file + \":\" + value.line + \",\" + value.col;\n        return value;\n    });\n}\n\nfunction remove(array, el) {\n    var index = array.indexOf(el);\n    if (index >= 0) array.splice(index, 1);\n}\n\nfunction makePredicate(words) {\n    if (!Array.isArray(words)) words = words.split(\" \");\n    var map = Object.create(null);\n    words.forEach(function(word) {\n        map[word] = true;\n    });\n    return map;\n}\n\nfunction all(array, predicate) {\n    for (var i = array.length; --i >= 0;)\n        if (!predicate(array[i], i))\n            return false;\n    return true;\n}\n\nfunction Dictionary() {\n    this.values = Object.create(null);\n}\nDictionary.prototype = {\n    set: function(key, val) {\n        if (key == \"__proto__\") {\n            this.proto_value = val;\n        } else {\n            this.values[key] = val;\n        }\n        return this;\n    },\n    add: function(key, val) {\n        var list = this.get(key);\n        if (list) {\n            list.push(val);\n        } else {\n            this.set(key, [ val ]);\n        }\n        return this;\n    },\n    get: function(key) {\n        return key == \"__proto__\" ? this.proto_value : this.values[key];\n    },\n    del: function(key) {\n        if (key == \"__proto__\") {\n            delete this.proto_value;\n        } else {\n            delete this.values[key];\n        }\n        return this;\n    },\n    has: function(key) {\n        return key == \"__proto__\" ? \"proto_value\" in this : key in this.values;\n    },\n    all: function(predicate) {\n        for (var i in this.values)\n            if (!predicate(this.values[i], i)) return false;\n        if (\"proto_value\" in this && !predicate(this.proto_value, \"__proto__\")) return false;\n        return true;\n    },\n    each: function(f) {\n        for (var i in this.values)\n            f(this.values[i], i);\n        if (\"proto_value\" in this) f(this.proto_value, \"__proto__\");\n    },\n    size: function() {\n        return Object.keys(this.values).length + (\"proto_value\" in this);\n    },\n    map: function(f) {\n        var ret = [];\n        for (var i in this.values)\n            ret.push(f(this.values[i], i));\n        if (\"proto_value\" in this) ret.push(f(this.proto_value, \"__proto__\"));\n        return ret;\n    },\n    clone: function() {\n        var ret = new Dictionary();\n        this.each(function(value, i) {\n            ret.set(i, value);\n        });\n        return ret;\n    },\n    toObject: function() {\n        var obj = {};\n        this.each(function(value, i) {\n            obj[\"$\" + i] = value;\n        });\n        return obj;\n    },\n};\nDictionary.fromObject = function(obj) {\n    var dict = new Dictionary();\n    for (var i in obj)\n        if (HOP(obj, i)) dict.set(i.slice(1), obj[i]);\n    return dict;\n};\n\nfunction HOP(obj, prop) {\n    return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\n// return true if the node at the top of the stack (that means the\n// innermost node in the current output) is lexically the first in\n// a statement.\nfunction first_in_statement(stack, arrow, export_default) {\n    var node = stack.parent(-1);\n    for (var i = 0, p; p = stack.parent(i++); node = p) {\n        if (is_arrow(p)) {\n            return arrow && p.value === node;\n        } else if (p instanceof AST_Binary) {\n            if (p.left === node) continue;\n        } else if (p.TYPE == \"Call\") {\n            if (p.expression === node) continue;\n        } else if (p instanceof AST_Conditional) {\n            if (p.condition === node) continue;\n        } else if (p instanceof AST_ExportDefault) {\n            return export_default;\n        } else if (p instanceof AST_PropAccess) {\n            if (p.expression === node) continue;\n        } else if (p instanceof AST_Sequence) {\n            if (p.expressions[0] === node) continue;\n        } else if (p instanceof AST_SimpleStatement) {\n            return true;\n        } else if (p instanceof AST_Template) {\n            if (p.tag === node) continue;\n        } else if (p instanceof AST_UnaryPostfix) {\n            if (p.expression === node) continue;\n        }\n        return false;\n    }\n}\n\nfunction DEF_BITPROPS(ctor, props) {\n    if (props.length > 31) throw new Error(\"Too many properties: \" + props.length + \"\\n\" + props.join(\", \"));\n    props.forEach(function(name, pos) {\n        var mask = 1 << pos;\n        Object.defineProperty(ctor.prototype, name, {\n            get: function() {\n                return !!(this._bits & mask);\n            },\n            set: function(val) {\n                if (val)\n                    this._bits |= mask;\n                else\n                    this._bits &= ~mask;\n            },\n        });\n    });\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"uglify-js\",\n  \"description\": \"JavaScript parser, mangler/compressor and beautifier toolkit\",\n  \"author\": \"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)\",\n  \"license\": \"BSD-2-Clause\",\n  \"version\": \"3.19.3\",\n  \"engines\": {\n    \"node\": \">=0.8.0\"\n  },\n  \"maintainers\": [\n    \"Alex Lam <alexlamsl@gmail.com>\",\n    \"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)\"\n  ],\n  \"repository\": \"mishoo/UglifyJS\",\n  \"main\": \"tools/node.js\",\n  \"bin\": {\n    \"uglifyjs\": \"bin/uglifyjs\"\n  },\n  \"files\": [\n    \"bin\",\n    \"lib\",\n    \"tools\",\n    \"LICENSE\"\n  ],\n  \"devDependencies\": {\n    \"acorn\": \"~8.7.1\",\n    \"semver\": \"~6.3.0\"\n  },\n  \"scripts\": {\n    \"test\": \"node test/compress.js && node test/mocha.js\"\n  },\n  \"keywords\": [\n    \"cli\",\n    \"compress\",\n    \"compressor\",\n    \"ecma\",\n    \"ecmascript\",\n    \"es\",\n    \"es5\",\n    \"javascript\",\n    \"js\",\n    \"jsmin\",\n    \"min\",\n    \"minification\",\n    \"minifier\",\n    \"minify\",\n    \"optimize\",\n    \"optimizer\",\n    \"pack\",\n    \"packer\",\n    \"parse\",\n    \"parser\",\n    \"uglifier\",\n    \"uglify\"\n  ]\n}\n"
  },
  {
    "path": "test/benchmark.js",
    "content": "#! /usr/bin/env node\n// -*- js -*-\n\n\"use strict\";\n\nrequire(\"../tools/tty\");\nvar createHash = require(\"crypto\").createHash;\nvar fetch = require(\"./fetch\");\nvar spawn = require(\"child_process\").spawn;\nvar zlib = require(\"zlib\");\nvar args = process.argv.slice(2);\nif (!args.length) args.push(\"-mc\");\nargs.unshift(\"bin/uglifyjs\");\nargs.push(\"--timings\");\nvar urls = [\n    \"https://code.jquery.com/jquery-3.4.1.js\",\n    \"https://code.angularjs.org/1.7.8/angular.js\",\n    \"https://unpkg.com/mathjs@6.2.3/dist/math.js\",\n    \"https://unpkg.com/react@15.3.2/dist/react.js\",\n    \"https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.js\",\n    \"https://cdnjs.cloudflare.com/ajax/libs/antd/4.18.7/antd.js\",\n    \"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js\",\n    \"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js\",\n    \"https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js\",\n    \"https://raw.githubusercontent.com/kangax/html-minifier/v4.0.0/dist/htmlminifier.js\",\n];\nvar results = {};\nvar remaining = 2 * urls.length;\nfunction done() {\n    if (!--remaining) {\n        var failures = [];\n        var sum = { input: 0, output: 0, gzip: 0 };\n        urls.forEach(function(url) {\n            var info = results[url];\n            console.log();\n            console.log(url);\n            console.log(info.log);\n            console.log(\"Original:\", info.input, \"bytes\");\n            console.log(\"Uglified:\", info.output, \"bytes\");\n            console.log(\"GZipped: \", info.gzip, \"bytes\");\n            console.log(\"SHA1 sum:\", info.sha1);\n            if (info.code) {\n                failures.push(url);\n            }\n            sum.input += info.input;\n            sum.output += info.output;\n            sum.gzip += info.gzip;\n        });\n        if (failures.length) {\n            console.error(\"Benchmark failed:\");\n            failures.forEach(function(url) {\n                console.error(url);\n            });\n            process.exit(1);\n        } else {\n            console.log();\n            console.log(\"Subtotal\");\n            console.log();\n            console.log(\"Original:\", sum.input, \"bytes\");\n            console.log(\"Uglified:\", sum.output, \"bytes\");\n            console.log(\"GZipped: \", sum.gzip, \"bytes\");\n        }\n    }\n}\nurls.forEach(function(url) {\n    results[url] = {\n        input: 0,\n        output: 0,\n        gzip: 0,\n        log: \"\"\n    };\n    fetch(url, function(err, res) {\n        if (err) throw err;\n        var uglifyjs = spawn(process.argv[0], args, { silent: true });\n        res.on(\"data\", function(data) {\n            results[url].input += data.length;\n        }).pipe(uglifyjs.stdin);\n        var sha1 = createHash(\"sha1\");\n        uglifyjs.stdout.on(\"data\", function(data) {\n            results[url].output += data.length;\n        }).pipe(zlib.createGzip({\n            level: zlib.Z_BEST_COMPRESSION\n        })).on(\"data\", function(data) {\n            results[url].gzip += data.length;\n            sha1.update(data);\n        }).on(\"end\", function() {\n            results[url].sha1 = sha1.digest(\"hex\");\n            done();\n        });\n        uglifyjs.stderr.setEncoding(\"utf8\");\n        uglifyjs.stderr.on(\"data\", function(data) {\n            results[url].log += data;\n        });\n        uglifyjs.on(\"exit\", function(code) {\n            results[url].code = code;\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/compress/annotations.js",
    "content": "issue_2629_1: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/ a();\n        /*@__PURE__*/ (b());\n        (/*@__PURE__*/ c)();\n        (/*@__PURE__*/ d());\n    }\n    expect_exact: \"c();\"\n}\n\nissue_2629_2: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/ a(1)(2)(3);\n        /*@__PURE__*/ (b(1))(2)(3);\n        /*@__PURE__*/ (c(1)(2))(3);\n        /*@__PURE__*/ (d(1)(2)(3));\n        (/*@__PURE__*/ e)(1)(2)(3);\n        (/*@__PURE__*/ f(1))(2)(3);\n        (/*@__PURE__*/ g(1)(2))(3);\n        (/*@__PURE__*/ h(1)(2)(3));\n    }\n    expect_exact: [\n        \"e(1)(2)(3);\",\n        \"f(1)(2)(3);\",\n        \"g(1)(2)(3);\",\n    ]\n}\n\nissue_2629_3: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/ a.x(1).y(2).z(3);\n        /*@__PURE__*/ (b.x)(1).y(2).z(3);\n        /*@__PURE__*/ (c.x(1)).y(2).z(3);\n        /*@__PURE__*/ (d.x(1).y)(2).z(3);\n        /*@__PURE__*/ (e.x(1).y(2)).z(3);\n        /*@__PURE__*/ (f.x(1).y(2).z)(3);\n        /*@__PURE__*/ (g.x(1).y(2).z(3));\n        (/*@__PURE__*/ h).x(1).y(2).z(3);\n        (/*@__PURE__*/ i.x)(1).y(2).z(3);\n        (/*@__PURE__*/ j.x(1)).y(2).z(3);\n        (/*@__PURE__*/ k.x(1).y)(2).z(3);\n        (/*@__PURE__*/ l.x(1).y(2)).z(3);\n        (/*@__PURE__*/ m.x(1).y(2).z)(3);\n        (/*@__PURE__*/ n.x(1).y(2).z(3));\n    }\n    expect_exact: [\n        \"h.x(1).y(2).z(3);\",\n        \"i.x(1).y(2).z(3);\",\n        \"j.x(1).y(2).z(3);\",\n        \"k.x(1).y(2).z(3);\",\n        \"l.x(1).y(2).z(3);\",\n        \"m.x(1).y(2).z(3);\",\n    ]\n}\n\nissue_2629_4: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    input: {\n        (/*@__PURE__*/ x(), y());\n        (w(), /*@__PURE__*/ x(), y());\n    }\n    expect: {\n        y();\n        w(), y();\n    }\n}\n\nissue_2629_5: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    input: {\n        [ /*@__PURE__*/ x() ];\n        [ /*@__PURE__*/ x(), y() ];\n        [ w(), /*@__PURE__*/ x(), y() ];\n    }\n    expect: {\n        y();\n        w(), y();\n    }\n}\n\nissue_2638: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/(g() || h())(x(), y());\n        (/*@__PURE__*/ (a() || b()))(c(), d());\n    }\n    expect_exact: [\n        \"x(),y();\",\n        \"(a()||b())(c(),d());\",\n    ]\n}\n\nissue_2705_1: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/ new a();\n        /*@__PURE__*/ (new b());\n        new (/*@__PURE__*/ c)();\n        (/*@__PURE__*/ new d());\n    }\n    expect_exact: [\n        \"new c;\",\n    ]\n}\n\nissue_2705_2: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/ new a(1)(2)(3);\n        /*@__PURE__*/ new (b(1))(2)(3);\n        /*@__PURE__*/ new (c(1)(2))(3);\n        /*@__PURE__*/ new (d(1)(2)(3));\n        new (/*@__PURE__*/ e)(1)(2)(3);\n        (/*@__PURE__*/ new f(1))(2)(3);\n        (/*@__PURE__*/ new g(1)(2))(3);\n        (/*@__PURE__*/ new h(1)(2)(3));\n    }\n    expect_exact: [\n        \"new e(1)(2)(3);\",\n        \"new f(1)(2)(3);\",\n        \"new g(1)(2)(3);\",\n    ]\n}\n\nissue_2705_3: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/ new a.x(1).y(2).z(3);\n        /*@__PURE__*/ new (b.x)(1).y(2).z(3);\n        /*@__PURE__*/ new (c.x(1)).y(2).z(3);\n        /*@__PURE__*/ new (d.x(1).y)(2).z(3);\n        /*@__PURE__*/ new (e.x(1).y(2)).z(3);\n        /*@__PURE__*/ new (f.x(1).y(2).z)(3);\n        /*@__PURE__*/ new (g.x(1).y(2).z(3));\n        new (/*@__PURE__*/ h).x(1).y(2).z(3);\n        /* */ new (/*@__PURE__*/ i.x)(1).y(2).z(3);\n        (/*@__PURE__*/ new j.x(1)).y(2).z(3);\n        (/*@__PURE__*/ new k.x(1).y)(2).z(3);\n        (/*@__PURE__*/ new l.x(1).y(2)).z(3);\n        (/*@__PURE__*/ new m.x(1).y(2).z)(3);\n        (/*@__PURE__*/ new n.x(1).y(2).z(3));\n    }\n    expect_exact: [\n        \"new h.x(1).y(2).z(3);\",\n        \"/* */new i.x(1).y(2).z(3);\",\n        \"new j.x(1).y(2).z(3);\",\n        \"new k.x(1).y(2).z(3);\",\n        \"new l.x(1).y(2).z(3);\",\n        \"new m.x(1).y(2).z(3);\",\n    ]\n}\n\nissue_2705_4: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    input: {\n        (/*@__PURE__*/ new x(), y());\n        (w(), /*@__PURE__*/ new x(), y());\n    }\n    expect: {\n        y();\n        w(), y();\n    }\n}\n\nissue_2705_5: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    input: {\n        [ /*@__PURE__*/ new x() ];\n        [ /*@__PURE__*/ new x(), y() ];\n        [ w(), /*@__PURE__*/ new x(), y() ];\n    }\n    expect: {\n        y();\n        w(), y();\n    }\n}\n\nissue_2705_6: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        /*@__PURE__*/new (g() || h())(x(), y());\n        /* */ new (/*@__PURE__*/ (a() || b()))(c(), d());\n    }\n    expect_exact: [\n        \"x(),y();\",\n        \"/* */new(a()||b())(c(),d());\",\n    ]\n}\n\nissue_3858: {\n    options = {\n        annotations: true,\n        collapse_vars: true,\n        inline: true,\n        keep_fargs: false,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var f = function(a) {\n            return /*@__PURE__*/ function(b) {\n                console.log(b);\n            }(a);\n        };\n        f(\"PASS\");\n    }\n    expect: {\n        var f = function(a) {\n            return function() {\n                console.log(a);\n            }();\n        };\n        f(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ninline_pure_call_1: {\n    options = {\n        annotations: true,\n        collapse_vars: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function(a) {\n            return /*@__PURE__*/ function(b) {\n                console.log(b);\n            }(a);\n        };\n        f(\"PASS\");\n    }\n    expect: {}\n}\n\ninline_pure_call_2: {\n    options = {\n        annotations: true,\n        collapse_vars: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function(a) {\n            return /*@__PURE__*/ function(b) {\n                console.log(b);\n            }(a);\n        };\n        var a = f(\"PASS\");\n    }\n    expect: {}\n}\n\ninline_pure_call_3: {\n    options = {\n        annotations: true,\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function(a) {\n            return /*@__PURE__*/ function(b) {\n                console.log(b);\n            }(a);\n        };\n        var a = f(\"PASS\");\n        console.log(a);\n    }\n    expect: {\n        var a = function() {\n            console.log(\"PASS\");\n        }();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\ninline_pure_call_4: {\n    options = {\n        annotations: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = /*@__PURE__*/ function() {\n            return console.log(\"PASS\"), 42;\n        }();\n        console.log(a);\n    }\n    expect: {\n        var a = function() {\n            return console.log(\"PASS\"), 42;\n        }();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n}\n\ncompress_and_output_annotations_enabled: {\n    options = {\n        annotations: true,\n        side_effects: true,\n    }\n    beautify = {\n        annotations: true,\n        beautify: true,\n        comments: false,\n    }\n    input: {\n        var top = /*@__PURE__*/ foo();\n        /*@__PURE__*/ a(1)(2)(3);\n        /*@__PURE__*/ (b(1))(2)(3);\n        /*@__PURE__*/ (c(1)(2))(3);\n        /*@__PURE__*/ (d(1)(2)(3));\n        (/*@__PURE__*/ e)(1)(2)(3);\n        (/*@__PURE__*/ f(1))(2)(3);\n        (/*@__PURE__*/ g(1)(2))(3);\n        (/*@__PURE__*/ h(1)(2)(3));\n        /*@__PURE__*/ l(1).p(2);\n        (/*@__PURE__*/ m(1)).p(2);\n        (/*@__PURE__*/ n(1).p)(2);\n        (/*@__PURE__*/ o(1).p(2));\n    }\n    expect_exact: [\n        \"var top = /*@__PURE__*/foo();\",\n        \"\",\n        \"e(1)(2)(3);\",\n        \"\",\n        \"f(1)(2)(3);\",\n        \"\",\n        \"g(1)(2)(3);\",\n        \"\",\n        \"m(1).p(2);\",\n        \"\",\n        \"n(1).p(2);\",\n    ]\n}\n\ncompress_annotations_disabled_output_annotations_enabled: {\n    options = {\n        annotations: false,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    beautify = {\n        annotations: true,\n        comments: true,\n    }\n    input: {\n        /*@__PURE__*/ a(1+2);\n        /*#__PURE__*/ (b(2+3));\n        (/*@__PURE__*/ c)(side_effect);\n        (/*#__PURE__*/ d(effect()));\n    }\n    expect_exact: [\n        \"/*@__PURE__*/a(3),\",\n        \"/*@__PURE__*/b(5),\",\n        \"c(side_effect),\",\n        \"/*@__PURE__*/d(effect());\",\n    ]\n}\n\ncompress_and_output_annotations_disabled: {\n    options = {\n        annotations: false,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    beautify = {\n        annotations: false,\n        comments: true,\n    }\n    input: {\n        /*@__PURE__*/ a(1+2);\n        /*@__PURE__*/ (b(2+3));\n        (/*@__PURE__*/ c)(side_effect);\n        (/*@__PURE__*/ d(effect()));\n    }\n    expect_exact: [\n        \"a(3),\",\n        \"b(5),\",\n        \"c(side_effect),\",\n        \"d(effect());\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/arguments.js",
    "content": "replace_index: {\n    options = {\n        arguments: true,\n        evaluate: true,\n        properties: true,\n    }\n    input: {\n        var arguments = [];\n        console.log(arguments[0]);\n        (function() {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(arguments) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function() {\n            var arguments;\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        var arguments = [];\n        console.log(arguments[0]);\n        (function() {\n            console.log(arguments[1], arguments[1], arguments.foo);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(b, b, arguments.foo);\n        })(\"bar\", 42);\n        (function(arguments) {\n            console.log(arguments[1], arguments[1], arguments.foo);\n        })(\"bar\", 42);\n        (function() {\n            var arguments;\n            console.log(arguments[1], arguments[1], arguments.foo);\n        })(\"bar\", 42);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"42 42 undefined\",\n        \"42 42 undefined\",\n        \"a a undefined\",\n        \"42 42 undefined\",\n    ]\n}\n\nreplace_index_strict: {\n    options = {\n        arguments: true,\n        evaluate: true,\n        properties: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            console.log(arguments[1], arguments[1], arguments.foo);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(b, b, arguments.foo);\n        })(\"bar\", 42);\n    }\n    expect_stdout: [\n        \"42 42 undefined\",\n        \"42 42 undefined\",\n    ]\n}\n\nreplace_index_drop_fargs_1: {\n    options = {\n        arguments: true,\n        evaluate: true,\n        keep_fargs: false,\n        properties: true,\n        reduce_vars: true,\n    }\n    input: {\n        var arguments = [];\n        console.log(arguments[0]);\n        (function() {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(arguments) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function() {\n            var arguments;\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function() {\n            var arguments = {\n                1: \"foo\",\n                foo: \"bar\",\n            };\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        var arguments = [];\n        console.log(arguments[0]);\n        (function(argument_0, argument_1) {\n            console.log(argument_1, argument_1, arguments.foo);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(b, b, arguments.foo);\n        })(\"bar\", 42);\n        (function(arguments) {\n            console.log(\"bar\"[1], \"bar\"[1], \"bar\".foo);\n        })(\"bar\", 42);\n        (function(argument_0, argument_1) {\n            var arguments;\n            console.log(argument_1, argument_1, arguments.foo);\n        })(\"bar\", 42);\n        (function() {\n            var arguments = {\n                1: \"foo\",\n                foo: \"bar\",\n            };\n            console.log(arguments[1], arguments[1], arguments.foo);\n        })(\"bar\", 42);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"42 42 undefined\",\n        \"42 42 undefined\",\n        \"a a undefined\",\n        \"42 42 undefined\",\n        \"foo foo bar\",\n    ]\n}\n\nreplace_index_drop_fargs_2: {\n    options = {\n        arguments: true,\n        evaluate: true,\n        keep_fargs: false,\n        properties: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        \"use strict\";\n        (function(argument_0, argument_1) {\n            console.log(argument_1, argument_1, arguments.foo);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(b, b, arguments.foo);\n        })(\"bar\", 42);\n    }\n    expect_stdout: [\n        \"42 42 undefined\",\n        \"42 42 undefined\",\n    ]\n}\n\nmodified: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(a, b) {\n            var c = arguments[0];\n            var d = arguments[1];\n            var a = \"foo\";\n            b++;\n            arguments[0] = \"moo\";\n            arguments[1] *= 2;\n            console.log(a, b, c, d, arguments[0], arguments[1]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        (function(a, b) {\n            var c = a;\n            var d = b;\n            var a = \"foo\";\n            b++;\n            a = \"moo\";\n            b *= 2;\n            console.log(a, b, c, d, a, b);\n        })(\"bar\", 42);\n    }\n    expect_stdout: \"moo 86 bar 42 moo 86\"\n}\n\nmodified_strict: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a, b) {\n            var c = arguments[0];\n            var d = arguments[1];\n            var a = \"foo\";\n            b++;\n            arguments[0] = \"moo\";\n            arguments[1] *= 2;\n            console.log(a, b, c, d, arguments[0], arguments[1]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        \"use strict\";\n        (function(a, b) {\n            var c = arguments[0];\n            var d = arguments[1];\n            var a = \"foo\";\n            b++;\n            arguments[0] = \"moo\";\n            arguments[1] *= 2;\n            console.log(a, b, c, d, arguments[0], arguments[1]);\n        })(\"bar\", 42);\n    }\n    expect_stdout: \"foo 43 bar 42 moo 84\"\n}\n\nduplicate_argname: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(a, b, a) {\n            console.log(a, b, arguments[0], arguments[1], arguments[2]);\n        })(\"foo\", 42, \"bar\");\n    }\n    expect: {\n        (function(a, b, a) {\n            console.log(a, b, arguments[0], b, a);\n        })(\"foo\", 42, \"bar\");\n    }\n    expect_stdout: \"bar 42 foo 42 bar\"\n}\n\nfraction: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            return arguments[0.3];\n        }(\"FAIL\") || \"PASS\");\n    }\n    expect: {\n        console.log(function() {\n            return arguments[0.3];\n        }(\"FAIL\") || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3273: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(a) {\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect: {\n        (function(a) {\n            console.log(a, a);\n            a++;\n            console.log(a, a);\n        })(0);\n    }\n    expect_stdout: [\n        \"0 0\",\n        \"1 1\",\n    ]\n}\n\nissue_3273_no_call_arg: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(a) {\n            arguments[0] = \"FAIL\";\n            console.log(a);\n        })();\n    }\n    expect: {\n        (function(a) {\n            arguments[0] = \"FAIL\";\n            console.log(a);\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3273_reduce_vars: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect: {\n        (function(a) {\n            console.log(a, a);\n            a++;\n            console.log(a, a);\n        })(0);\n    }\n    expect_stdout: [\n        \"0 0\",\n        \"1 1\",\n    ]\n}\n\nissue_3273_local_strict: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(a) {\n            \"use strict\";\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect: {\n        (function(a) {\n            \"use strict\";\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect_stdout: [\n        \"0 0\",\n        \"1 0\",\n    ]\n}\n\nissue_3273_local_strict_reduce_vars: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            \"use strict\";\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect: {\n        (function(a) {\n            \"use strict\";\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect_stdout: [\n        \"0 0\",\n        \"1 0\",\n    ]\n}\n\nissue_3273_global_strict: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect_stdout: [\n        \"0 0\",\n        \"1 0\",\n    ]\n}\n\nissue_3273_global_strict_reduce_vars: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            console.log(arguments[0], a);\n            arguments[0]++;\n            console.log(arguments[0], a);\n        })(0);\n    }\n    expect_stdout: [\n        \"0 0\",\n        \"1 0\",\n    ]\n}\n\nissue_3273_drop_fargs_1: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        (function() {\n            \"use strict\";\n            arguments[0]++;\n            console.log(arguments[0]);\n        })(0);\n    }\n    expect: {\n        (function(argument_0) {\n            \"use strict\";\n            argument_0++;\n            console.log(argument_0);\n        })(0);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3273_drop_fargs_2: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        (function() {\n            \"use strict\";\n            arguments[0]++;\n            console.log(arguments[0]);\n        })(0);\n    }\n    expect: {\n        (function(argument_0) {\n            \"use strict\";\n            argument_0++;\n            console.log(argument_0);\n        })(0);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3282_1: {\n    options = {\n        arguments: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(t) {\n            return function() {\n                t();\n            };\n        })(function() {\n            'use strict';\n            function e() {\n                return arguments[0];\n            }\n            e();\n            e();\n        })();\n    }\n    expect: {\n        (function() {\n            return function() {\n                (function() {\n                    \"use strict\";\n                    function e() {\n                        return arguments[0];\n                    }\n                    e();\n                    e();\n                })();\n            };\n        })()();\n    }\n    expect_stdout: true\n}\n\nissue_3282_1_passes: {\n    options = {\n        arguments: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(t) {\n            return function() {\n                t();\n            };\n        })(function() {\n            'use strict';\n            function e() {\n                return arguments[0];\n            }\n            e();\n            e();\n        })();\n    }\n    expect: {\n        (function() {\n            return function() {\n                (function() {\n                    \"use strict\";\n                    function e(argument_0) {\n                        return argument_0;\n                    }\n                    e();\n                    e();\n                })();\n            };\n        })()();\n    }\n    expect_stdout: true\n}\n\nissue_3282_2: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(f) {\n            f();\n        })(function() {\n            return (function(t) {\n                return function() {\n                    t();\n                };\n            })(function() {\n                'use strict';\n                function e() {\n                    return arguments[0];\n                }\n                e();\n                e();\n            })();\n        });\n    }\n    expect: {\n        (function() {\n            (function() {\n                return function(t) {\n                    return function() {\n                        t();\n                    };\n                }(function() {\n                    \"use strict\";\n                    function e() {\n                        return arguments[0];\n                    }\n                    e();\n                    e();\n                })();\n            })();\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_3282_2_passes: {\n    options = {\n        arguments: true,\n        passes: 2,\n        reduce_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(f) {\n            f();\n        })(function() {\n            return (function(t) {\n                return function() {\n                    t();\n                };\n            })(function() {\n                'use strict';\n                function e() {\n                    return arguments[0];\n                }\n                e();\n                e();\n            })();\n        });\n    }\n    expect: {\n        (function() {\n            (function() {\n                return function(t) {\n                    return function() {\n                        t();\n                    };\n                }(function() {\n                    \"use strict\";\n                    function e(argument_0) {\n                        return argument_0;\n                    }\n                    e();\n                    e();\n                })();\n            })();\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_3420_1: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            return function() {\n                return arguments[0];\n            };\n        }().length);\n    }\n    expect: {\n        console.log(function() {\n            return function() {\n                return arguments[0];\n            };\n        }().length);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_3420_2: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        var foo = function() {\n            delete arguments[0];\n        };\n        foo();\n    }\n    expect: {\n        var foo = function() {\n            delete arguments[0];\n        };\n        foo();\n    }\n    expect_stdout: true\n}\n\nissue_3420_3: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var foo = function() {\n            delete arguments[0];\n        };\n        foo();\n    }\n    expect: {\n        \"use strict\";\n        var foo = function() {\n            delete arguments[0];\n        };\n        foo();\n    }\n    expect_stdout: true\n}\n\nissue_3420_4: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        !function() {\n            console.log(arguments[0]);\n            delete arguments[0];\n            console.log(arguments[0]);\n        }(42);\n    }\n    expect: {\n        !function(argument_0) {\n            console.log(argument_0);\n            delete arguments[0];\n            console.log(arguments[0]);\n        }(42);\n    }\n    expect_stdout: [\n        \"42\",\n        \"undefined\",\n    ]\n}\n\nissue_3420_5: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        !function() {\n            console.log(arguments[0]);\n            delete arguments[0];\n            console.log(arguments[0]);\n        }(42);\n    }\n    expect: {\n        \"use strict\";\n        !function(argument_0) {\n            console.log(argument_0);\n            delete arguments[0];\n            console.log(arguments[0]);\n        }(42);\n    }\n    expect_stdout: [\n        \"42\",\n        \"undefined\",\n    ]\n}\n\nissue_3420_6: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            return delete arguments[0];\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return delete arguments[0];\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3420_7: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function() {\n            return delete arguments[0];\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            return delete arguments[0];\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_4200: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n    }\n    input: {\n        var o = {\n            get p() {\n                return arguments[0];\n            },\n        };\n        console.log(o.p);\n    }\n    expect: {\n        var o = {\n            get p() {\n                return arguments[0];\n            },\n        };\n        console.log(o.p);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4291_1: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            arguments[0] = \"PASS\";\n            return arguments;\n        }()[0]);\n    }\n    expect: {\n        console.log(function() {\n            arguments[0] = \"PASS\";\n            return arguments;\n        }()[0]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4291_2: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        var a = function() {\n            if (arguments[0])\n                arguments[1] = \"PASS\";\n            return arguments;\n        }(42);\n        console.log(a[1], a[0], a.length);\n    }\n    expect: {\n        var a = function() {\n            if (arguments[0])\n                arguments[1] = \"PASS\";\n            return arguments;\n        }(42);\n        console.log(a[1], a[0], a.length);\n    }\n    expect_stdout: \"PASS 42 1\"\n}\n\nissue_4397: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(typeof function() {\n            arguments += 0;\n            return arguments[0];\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            arguments += 0;\n            return arguments[0];\n        }());\n    }\n    expect_stdout: \"string\"\n}\n\nissue_4410_1: {\n    options = {\n        arguments: true,\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            console.log(arguments[0] === (a = 0) ? \"FAIL\" : \"PASS\");\n        })(1);\n    }\n    expect: {\n        (function(a) {\n            console.log(a === (a = 0) ? \"FAIL\" : \"PASS\");\n        })(1);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4410_2: {\n    options = {\n        arguments: true,\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function f(a) {\n            console.log(arguments[0] === (a = 0) ? \"FAIL\" : \"PASS\");\n        })(1);\n    }\n    expect: {\n        (function f(a) {\n            console.log(arguments[0] === (a = 0) ? \"FAIL\" : \"PASS\");\n        })(1);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4410_3: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        var a = 1;\n        (function f(b) {\n            a-- && f();\n            for (var c = 2; c--;)\n                switch (arguments[0]) {\n                  case b = 42:\n                  case 42:\n                    console.log(\"PASS\");\n                }\n        })(null);\n    }\n    expect: {\n        var a = 1;\n        (function f(b) {\n            a-- && f();\n            for (var c = 2; c--;)\n                switch (arguments[0]) {\n                  case b = 42:\n                  case 42:\n                    console.log(\"PASS\");\n                }\n        })(null);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4432: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            for (a in { FAIL: 42 });\n            return arguments[0];\n        }() || \"PASS\");\n    }\n    expect: {\n        console.log(function(a) {\n            for (a in { FAIL: 42 });\n            return arguments[0];\n        }() || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4696: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n    }\n    input: {\n        console.log(function() {\n            for (arguments in [ 42 ]);\n            for (var a in arguments[0])\n                return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            for (arguments in [ 42 ]);\n            for (var a in arguments[0])\n                return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4809: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        A = 0;\n        (function() {\n            arguments[A] = \"PASS\";\n            console.log(arguments[0]);\n        })();\n    }\n    expect: {\n        A = 0;\n        (function() {\n            arguments[A] = \"PASS\";\n            console.log(arguments[0]);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/arrays.js",
    "content": "holes_and_undefined: {\n    input: {\n        w = [1,,];\n        x = [1, 2, undefined];\n        y = [1, , 2, ];\n        z = [1, undefined, 3];\n    }\n    expect: {\n        w=[1,,];\n        x=[1,2,void 0];\n        y=[1,,2];\n        z=[1,void 0,3];\n    }\n}\n\nconstant_join_1: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        strings: true,\n        unsafe: true,\n    }\n    input: {\n        var a = [ \"foo\", \"bar\", \"baz\" ].join(\"\");\n        var a1 = [ \"foo\", \"bar\", \"baz\" ].join();\n        var a2 = [ \"foo\", \"bar\", \"baz\" ].join(null);\n        var a3 = [ \"foo\", \"bar\", \"baz\" ].join(void 0);\n        var a4 = [ \"foo\", , \"baz\" ].join();\n        var a5 = [ \"foo\", null, \"baz\" ].join();\n        var a6 = [ \"foo\", void 0, \"baz\" ].join();\n        var b = [ \"foo\", 1, 2, 3, \"bar\" ].join(\"\");\n        var c = [ boo(), \"foo\", 1, 2, 3, \"bar\", bar() ].join(\"\");\n        var c1 = [ boo(), bar(), \"foo\", 1, 2, 3, \"bar\", bar() ].join(\"\");\n        var c2 = [ 1, 2, \"foo\", \"bar\", baz() ].join(\"\");\n        var c3 = [ boo() + bar() + \"foo\", 1, 2, 3, \"bar\", bar() + \"foo\" ].join(\"\");\n        var c4 = [ 1, 2, null, undefined, \"foo\", \"bar\", baz() ].join(\"\");\n        var c5 = [ boo() + bar() + \"foo\", 1, 2, 3, \"bar\", bar() + \"foo\" ].join();\n        var c6 = [ 1, 2, null, undefined, \"foo\", \"bar\", baz() ].join();\n        var d = [ \"foo\", 1 + 2 + \"bar\", \"baz\" ].join(\"-\");\n        var e = [].join(foo + bar);\n        var f = [].join(\"\");\n        var g = [].join(\"foo\");\n    }\n    expect: {\n        var a = \"foobarbaz\";\n        var a1 = \"foo,bar,baz\";\n        var a2 = \"foonullbarnullbaz\";\n        var a3 = \"foo,bar,baz\";\n        var a4 = \"foo,,baz\";\n        var a5 = \"foo,,baz\";\n        var a6 = \"foo,,baz\";\n        var b = \"foo123bar\";\n        var c = boo() + \"foo123bar\" + bar();\n        var c1 = \"\" + boo() + bar() + \"foo123bar\" + bar();\n        var c2 = \"12foobar\" + baz();\n        var c3 = boo() + bar() + \"foo123bar\" + bar() + \"foo\";\n        var c4 = \"12foobar\" + baz();\n        var c5 = [ boo() + bar() + \"foo\", 1, 2, 3, \"bar\", bar() + \"foo\" ].join();\n        var c6 = [ \"1,2,,,foo,bar\", baz() ].join();\n        var d = \"foo-3bar-baz\";\n        var e = (foo, bar, \"\");\n        var f = \"\";\n        var g = \"\";\n    }\n}\n\nconstant_join_2: {\n    options = {\n        evaluate: true,\n        strings: true,\n        unsafe: true,\n    }\n    input: {\n        var a = [ \"foo\", \"bar\", boo(), \"baz\", \"x\", \"y\" ].join(\"\");\n        var b = [ \"foo\", \"bar\", boo(), \"baz\", \"x\", \"y\" ].join(\"-\");\n        var c = [ \"foo\", \"bar\", boo(), \"baz\", \"x\", \"y\" ].join(\"really-long-separator\");\n        var d = [ \"foo\", \"bar\", boo(),\n                  [ \"foo\", 1, 2, 3, \"bar\" ].join(\"+\"),\n                  \"baz\", \"x\", \"y\" ].join(\"-\");\n        var e = [ \"foo\", \"bar\", boo(),\n                  [ \"foo\", 1, 2, 3, \"bar\" ].join(\"+\"),\n                  \"baz\", \"x\", \"y\" ].join(\"really-long-separator\");\n        var f = [ \"str\", \"str\" + variable, \"foo\", \"bar\", \"moo\" + foo ].join(\"\");\n    }\n    expect: {\n        var a = \"foobar\" + boo() + \"bazxy\";\n        var b = [ \"foo-bar\", boo(), \"baz-x-y\" ].join(\"-\");\n        var c = [ \"foo\", \"bar\", boo(), \"baz\", \"x\", \"y\" ].join(\"really-long-separator\");\n        var d = [ \"foo-bar\", boo(), \"foo+1+2+3+bar-baz-x-y\" ].join(\"-\");\n        var e = [ \"foo\", \"bar\", boo(),\n                  \"foo+1+2+3+bar\",\n                  \"baz\", \"x\", \"y\" ].join(\"really-long-separator\");\n        var f = \"strstr\" + variable + \"foobarmoo\" + foo;\n    }\n}\n\nconstant_join_3: {\n    options = {\n        evaluate: true,\n        strings: true,\n        unsafe: true,\n    }\n    input: {\n        var foo, bar, baz;\n        var a = [ null ].join();\n        var b = [ , ].join();\n        var c = [ , 1, , 3 ].join();\n        var d = [ foo ].join();\n        var e = [ foo, null, undefined, bar ].join(\"-\");\n        var f = [ foo, bar ].join(\"\");\n        var g = [ null, \"foo\", null, bar + \"baz\" ].join(\"\");\n        var h = [ null, \"foo\", null, bar + \"baz\" ].join(\"-\");\n        var i = [ \"foo\" + bar, null, baz + \"moo\" ].join(\"\");\n        var j = [ foo + \"bar\", baz ].join(\"\");\n        var k = [ foo, \"bar\" + baz ].join(\"\");\n        var l = [ foo, bar + \"baz\" ].join(\"\");\n    }\n    expect: {\n        var foo, bar, baz;\n        var a = \"\";\n        var b = \"\";\n        var c = \",1,,3\";\n        var d = \"\" + foo;\n        var e = [ foo, \"-\", bar ].join(\"-\");\n        var f = \"\" + foo + bar;\n        var g = \"foo\" + bar + \"baz\";\n        var h = [ \"-foo-\", bar + \"baz\" ].join(\"-\");\n        var i = \"foo\" + bar + baz + \"moo\";\n        var j = foo + \"bar\" + baz;\n        var k = foo + \"bar\" + baz;\n        var l = foo + (bar + \"baz\");\n    }\n}\n\nfor_loop: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f0() {\n            var a = [1, 2, 3];\n            var b = 0;\n            for (var i = 0; i < a.length; i++)\n                b += a[i];\n            return b;\n        }\n        function f1() {\n            var a = [1, 2, 3];\n            var b = 0;\n            for (var i = 0, len = a.length; i < len; i++)\n                b += a[i];\n            return b;\n        }\n        function f2() {\n            var a = [1, 2, 3];\n            for (var i = 0; i < a.length; i++)\n                a[i]++;\n            return a[2];\n        }\n        console.log(f0(), f1(), f2());\n    }\n    expect: {\n        function f0() {\n            var a = [1, 2, 3];\n            var b = 0;\n            for (var i = 0; i < 3; i++)\n                b += a[i];\n            return b;\n        }\n        function f1() {\n            var a = [1, 2, 3];\n            var b = 0;\n            for (var i = 0; i < 3; i++)\n                b += a[i];\n            return b;\n        }\n        function f2() {\n            var a = [1, 2, 3];\n            for (var i = 0; i < a.length; i++)\n                a[i]++;\n            return a[2];\n        }\n        console.log(f0(), f1(), f2());\n    }\n    expect_stdout: \"6 6 4\"\n}\n\nindex: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = [ 1, 2 ];\n        console.log(a[0], a[1]);\n    }\n    expect: {\n        console.log(1, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nlength: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = [ 1, 2 ];\n        console.log(a.length);\n    }\n    expect: {\n        console.log(2);\n    }\n    expect_stdout: \"2\"\n}\n\nindex_length: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = [ 1, 2 ];\n        console.log(a[0], a.length);\n    }\n    expect: {\n        console.log(1, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nconstructor_bad: {\n    options = {\n        unsafe: true\n    }\n    input: {\n        try {\n            Array(NaN);\n            console.log(\"FAIL1\");\n        } catch (ex) {\n            try {\n                new Array(NaN);\n                console.log(\"FAIL2\");\n            } catch (ex) {\n                console.log(\"PASS\");\n            }\n        }\n        try {\n            Array(3.14);\n            console.log(\"FAIL1\");\n        } catch (ex) {\n            try {\n                new Array(3.14);\n                console.log(\"FAIL2\");\n            } catch (ex) {\n                console.log(\"PASS\");\n            }\n        }\n    }\n    expect: {\n        try {\n            Array(NaN);\n            console.log(\"FAIL1\");\n        } catch (ex) {\n            try {\n                Array(NaN);\n                console.log(\"FAIL2\");\n            } catch (ex) {\n                console.log(\"PASS\");\n            }\n        }\n        try {\n            Array(3.14);\n            console.log(\"FAIL1\");\n        } catch (ex) {\n            try {\n                Array(3.14);\n                console.log(\"FAIL2\");\n            } catch (ex) {\n                console.log(\"PASS\");\n            }\n        }\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n    expect_warnings: [\n        \"WARN: Invalid array length: 3.14 [test/compress/arrays.js:13,12]\",\n        \"WARN: Invalid array length: 3.14 [test/compress/arrays.js:17,16]\",\n    ]\n}\n\nconstructor_good: {\n    options = {\n        unsafe: true\n    }\n    input: {\n        console.log(Array());\n        console.log(Array(0));\n        console.log(Array(1));\n        console.log(Array(6));\n        console.log(Array(7));\n        console.log(Array(1, 2));\n        console.log(Array(false));\n        console.log(Array(\"foo\"));\n        console.log(Array(Array));\n        console.log(new Array());\n        console.log(new Array(0));\n        console.log(new Array(1));\n        console.log(new Array(6));\n        console.log(new Array(7));\n        console.log(new Array(1, 2));\n        console.log(new Array(false));\n        console.log(new Array(\"foo\"));\n        console.log(new Array(Array));\n    }\n    expect: {\n        console.log([]);\n        console.log([]);\n        console.log([,]);\n        console.log([,,,,,,]);\n        console.log(Array(7));\n        console.log([ 1, 2 ]);\n        console.log([ false ]);\n        console.log([ \"foo\" ]);\n        console.log(Array(Array));\n        console.log([]);\n        console.log([]);\n        console.log([,]);\n        console.log([,,,,,,]);\n        console.log(Array(7));\n        console.log([ 1, 2 ]);\n        console.log([ false ]);\n        console.log([ \"foo\" ]);\n        console.log(Array(Array));\n    }\n    expect_stdout: true\n    expect_warnings: []\n}\n\nunsafe_evaluate_modified_binary: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function(a) {\n            (console && a).push(1);\n            if (a.length)\n                console.log(\"PASS\");\n        })([]);\n    }\n    expect: {\n        (function(a) {\n            (console && a).push(1);\n            if (a.length)\n                console.log(\"PASS\");\n        })([]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nunsafe_evaluate_modified_conditional: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function(a) {\n            (console ? a : []).push(1);\n            if (a.length)\n                console.log(\"PASS\");\n        })([]);\n    }\n    expect: {\n        (function(a) {\n            (console ? a : []).push(1);\n            if (a.length)\n                console.log(\"PASS\");\n        })([]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nunsafe_evaluate_modified_sequence: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function(a) {\n            (0, a).push(1);\n            if (a.length)\n                console.log(\"PASS\");\n        })([]);\n    }\n    expect: {\n        (function(a) {\n            (0, a).push(1);\n            if (a.length)\n                console.log(\"PASS\");\n        })([]);\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/arrows.js",
    "content": "no_funarg: {\n    input: {\n        (() => console.log(42))();\n    }\n    expect_exact: \"(()=>console.log(42))();\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nsingle_funarg: {\n    input: {\n        (a => console.log(a))(42);\n    }\n    expect_exact: \"(a=>console.log(a))(42);\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nmultiple_funargs: {\n    input: {\n        ((a, b) => console.log(a, b))(\"foo\", \"bar\");\n    }\n    expect_exact: '((a,b)=>console.log(a,b))(\"foo\",\"bar\");'\n    expect_stdout: \"foo bar\"\n    node_version: \">=4\"\n}\n\ndestructured_funarg: {\n    input: {\n        (([ a, b, c ]) => console.log(a, b, c))(\"foo\");\n    }\n    expect_exact: '(([a,b,c])=>console.log(a,b,c))(\"foo\");'\n    expect_stdout: \"f o o\"\n    node_version: \">=6\"\n}\n\nawait_parentheses: {\n    input: {\n        async function f() {\n            await (a => a);\n        }\n    }\n    expect_exact: \"async function f(){await(a=>a)}\"\n}\n\nfor_parentheses_init: {\n    input: {\n        for (a => (a in a); console.log(42););\n    }\n    expect_exact: \"for((a=>a in a);console.log(42););\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_parentheses_condition: {\n    input: {\n        for (console.log(42); a => (a in a);)\n            break;\n    }\n    expect_exact: \"for(console.log(42);a=>a in a;)break;\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_parentheses_step: {\n    input: {\n        for (; console.log(42); a => (a in a));\n    }\n    expect_exact: \"for(;console.log(42);a=>a in a);\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_assign_parentheses_init: {\n    input: {\n        for (f = a => (a in a); console.log(42););\n    }\n    expect_exact: \"for((f=a=>a in a);console.log(42););\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_assign_parentheses_condition: {\n    input: {\n        for (console.log(42); f = a => (a in a);)\n            break;\n    }\n    expect_exact: \"for(console.log(42);f=a=>a in a;)break;\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_assign_parentheses_step: {\n    input: {\n        for (; console.log(42); f = a => (a in a));\n    }\n    expect_exact: \"for(;console.log(42);f=a=>a in a);\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_declaration_parentheses_init: {\n    input: {\n        for (var f = a => (a in a); console.log(42););\n    }\n    expect_exact: \"for(var f=(a=>a in a);console.log(42););\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nfor_statement_parentheses_init: {\n    input: {\n        for (a => {\n            a in a;\n        }; console.log(42););\n    }\n    expect_exact: \"for(a=>{a in a};console.log(42););\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nbody_call: {\n    input: {\n        (() => {\n            console.log(\"foo\");\n            console.log(\"bar\");\n        })();\n    }\n    expect_exact: '(()=>{console.log(\"foo\");console.log(\"bar\")})();'\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nbody_conditional: {\n    input: {\n        console.log((a => {}) ? \"PASS\" : \"FAIL\");\n    }\n    expect_exact: 'console.log((a=>{})?\"PASS\":\"FAIL\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndestructured_object_value: {\n    input: {\n        console.log((a => ({} = a))(42));\n    }\n    expect_exact: \"console.log((a=>({}=a))(42));\"\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\nfunction_value: {\n    input: {\n        console.log((a => function() {\n            return a;\n        })(42)());\n    }\n    expect_exact: \"console.log((a=>function(){return a})(42)());\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nin_value: {\n    input: {\n        console.log((a => a in {\n            foo: 42,\n        })(\"foo\"));\n    }\n    expect_exact: 'console.log((a=>a in{foo:42})(\"foo\"));'\n    expect_stdout: \"true\"\n    node_version: \">=4\"\n}\n\nobject_value: {\n    input: {\n        console.log((() => ({\n            4: 2,\n        }))()[4]);\n    }\n    expect_exact: \"console.log((()=>({4:2}))()[4]);\"\n    expect_stdout: \"2\"\n    node_version: \">=4\"\n}\n\nobject_first_in_value: {\n    input: {\n        console.log((a => ({\n            p: a,\n        }.p ? \"FAIL\" : \"PASS\"))());\n    }\n    expect_exact: 'console.log((a=>({p:a}).p?\"FAIL\":\"PASS\")());'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nsequence_value: {\n    input: {\n        console.log((a => (console.log(\"foo\"), a))(\"bar\"));\n    }\n    expect_exact: 'console.log((a=>(console.log(\"foo\"),a))(\"bar\"));'\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nside_effects_value: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console.log((a => function() {\n            return a;\n        })(42)());\n    }\n    expect: {\n        console.log((a => function() {\n            return a;\n        })(42)());\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\narrow_property: {\n    input: {\n        console.log((a => 42).prototype);\n    }\n    expect_exact: \"console.log((a=>42).prototype);\"\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nassign_arrow: {\n    input: {\n        var f = a => a;\n        console.log(f(42));\n    }\n    expect_exact: \"var f=a=>a;console.log(f(42));\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nbinary_arrow: {\n    input: {\n        console.log(4 || (() => 2));\n    }\n    expect_exact: \"console.log(4||(()=>2));\"\n    expect_stdout: \"4\"\n    node_version: \">=4\"\n}\n\nunary_arrow: {\n    input: {\n        console.log(+(() => 42));\n    }\n    expect_exact: \"console.log(+(()=>42));\"\n    expect_stdout: \"NaN\"\n    node_version: \">=4\"\n}\n\ntrailing_comma: {\n    input: {\n        ((a,) => console.log(a))(42);\n    }\n    expect_exact: \"(a=>console.log(a))(42);\"\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\ndrop_arguments: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            return () => arguments[0];\n        }(\"PASS\")(\"FAIL\"));\n    }\n    expect: {\n        console.log(function(argument_0) {\n            return () => argument_0;\n        }(\"PASS\")(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nfunarg_arguments: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log((arguments => arguments)(42));\n    }\n    expect: {\n        console.log(42);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\ninline_arguments: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            return () => arguments[0];\n        }(\"PASS\")(\"FAIL\"));\n    }\n    expect: {\n        console.log(function() {\n            return () => arguments[0];\n        }(\"PASS\")(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nvar_arguments: {\n    options = {\n        inline: true,\n        properties: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return () => {\n                var arguments = [ \"PASS\" ];\n                return arguments;\n            };\n        }(\"FAIL 1\")(\"FAIL 2\")[0]);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nnegate: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (!console ? 0 : () => 1)\n            console.log(\"PASS\");\n    }\n    expect: {\n        (console ? () => 1 : 0) && console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ninline_this: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var p = \"PASS\";\n        console.log({\n            p: \"FAIL\",\n            q: (() => this.p)(),\n        }.q);\n    }\n    expect: {\n        var p = \"PASS\";\n        console.log({\n            p: \"FAIL\",\n            q: this.p,\n        }.q);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndont_inline_this: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var o = {\n            p: function() {\n                return function() {\n                    return () => this.q;\n                }();\n            },\n            q: \"FAIL\",\n        };\n        q = \"PASS\";\n        console.log(o.p()());\n    }\n    expect: {\n        var o = {\n            p: function() {\n                return function() {\n                    return () => this.q;\n                }();\n            },\n            q: \"FAIL\",\n        };\n        q = \"PASS\";\n        console.log(o.p()());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ntrim_body: {\n    options = {\n        arrows: true,\n        if_return: true,\n        side_effects: true,\n    }\n    input: {\n        var f = a => {\n            return a;\n        };\n        var g = b => void b;\n        console.log(f(\"PASS\"), g(\"FAIL\"));\n    }\n    expect: {\n        var f = a => a;\n        var g = b => {};\n        console.log(f(\"PASS\"), g(\"FAIL\"));\n    }\n    expect_stdout: \"PASS undefined\"\n    node_version: \">=4\"\n}\n\ncollapse_value: {\n    options = {\n        arrows: true,\n        collapse_vars: true,\n        keep_fargs: false,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        console.log((b => Math.floor(b))(a));\n    }\n    expect: {\n        var a = 42;\n        console.log((() => Math.floor(a))());\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\ncollapse_property_lambda: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        console.log(function f() {\n            f.g = () => 42;\n            return f.g();\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            return (f.g = () => 42)();\n        }());\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\ndrop_return: {\n    options = {\n        arrows: true,\n        side_effects: true,\n    }\n    input: {\n        (a => {\n            while (!console);\n            return console.log(a);\n        })(42);\n    }\n    expect: {\n        (a => {\n            while (!console);\n            console.log(a);\n        })(42);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\ndrop_value: {\n    options = {\n        arrows: true,\n        side_effects: true,\n    }\n    input: {\n        ((a, b) => a + b)(console.log(42));\n    }\n    expect: {\n        void console.log(42);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nreduce_iife_1: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (a => console.log(a + a))(21);\n    }\n    expect: {\n        (() => console.log(42))();\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nreduce_iife_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 21;\n        (() => console.log(a + a))();\n    }\n    expect: {\n        (() => console.log(42))();\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nreduce_iife_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        (() => {\n            console.log(a);\n            console.log(a);\n        })();\n        a = \"bar\";\n    }\n    expect: {\n        (() => {\n            console.log(\"foo\");\n            console.log(\"foo\");\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_lambda_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = () => {\n            console.log(a, b);\n        };\n        var a = \"foo\", b = 42;\n        f();\n        b = \"bar\";\n        f();\n    }\n    expect: {\n        var f = () => {\n            console.log(\"foo\", b);\n        };\n        var b = 42;\n        f();\n        b = \"bar\";\n        f();\n    }\n    expect_stdout: [\n        \"foo 42\",\n        \"foo bar\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_lambda_2: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(f, a, b) {\n            f = () => {\n                console.log(a, b);\n            };\n            a = \"foo\", b = 42;\n            f();\n            b = \"bar\";\n            f();\n        })();\n    }\n    expect: {\n        (function(f, a, b) {\n            f = () => {\n                console.log(\"foo\", b);\n            };\n            b = 42;\n            f();\n            b = \"bar\";\n            f();\n        })();\n    }\n    expect_stdout: [\n        \"foo 42\",\n        \"foo bar\",\n    ]\n    node_version: \">=4\"\n}\n\nsingle_use_recursive: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return (() => f)();\n        }\n        console.log(typeof f());\n    }\n    expect: {\n        console.log(typeof function f() {\n            return (() => f)();\n        }());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\ninline_iife_within_arrow: {\n    options = {\n        arrows: true,\n        inline: true,\n    }\n    input: {\n        var f = () => console.log(function(a) {\n            return Math.ceil(a);\n        }(Math.random()));\n        f();\n    }\n    expect: {\n        var f = () => {\n            return console.log((a = Math.random(), Math.ceil(a)));\n            var a;\n        };\n        f();\n    }\n    expect_stdout: \"1\"\n    node_version: \">=4\"\n}\n\ninstanceof_lambda_1: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(42 instanceof (() => {}));\n    }\n    expect: {\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n    node_version: \">=4\"\n}\n\ninstanceof_lambda_2: {\n    options = {\n        evaluate: true,\n        side_effects: false,\n    }\n    input: {\n        console.log(null instanceof (() => {}));\n    }\n    expect: {\n        console.log((null, () => {}, false));\n    }\n    expect_stdout: \"false\"\n    node_version: \">=4\"\n}\n\ninstanceof_lambda_3: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log({} instanceof (() => {}));\n    }\n    expect: {\n        console.log({} instanceof (() => {}));\n    }\n    expect_stdout: TypeError(\"Function has non-object prototype 'undefined' in instanceof check\")\n    node_version: \">=4\"\n}\n\ninstanceof_lambda_4: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({ p: \"foo\" }) instanceof (() => {});\n    }\n    expect: {\n        [] instanceof (() => {});\n    }\n    expect_stdout: TypeError(\"Function has non-object prototype 'undefined' in instanceof check\")\n    node_version: \">=4\"\n}\n\nfunc_to_arrow: {\n    options = {\n        arrows: true,\n        module: true,\n    }\n    input: {\n        console.log(function(a, b, c) {\n            return b + a + c + c;\n        }(\"A\", \"P\", \"S\"));\n    }\n    expect: {\n        console.log(((a, b, c) => b + a + c + c)(\"A\", \"P\", \"S\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nfunc_to_arrow_var: {\n    options = {\n        arrows: true,\n        module: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function(a, b, c) {\n            return b + a + c + c;\n        };\n        console.log(f(\"A\", \"P\", \"S\"));\n    }\n    expect: {\n        console.log(((a, b, c) => b + a + c + c)(\"A\", \"P\", \"S\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_new: {\n    options = {\n        arrows: true,\n        module: true,\n    }\n    input: {\n        new function(a, b, c) {\n            console.log(b + a + c + c);\n        }(\"A\", \"P\", \"S\");\n    }\n    expect: {\n        new function(a, b, c) {\n            console.log(b + a + c + c);\n        }(\"A\", \"P\", \"S\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_new_var: {\n    options = {\n        arrows: true,\n        module: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function(a, b, c) {\n            console.log(b + a + c + c);\n        };\n        new f(\"A\", \"P\", \"S\");\n    }\n    expect: {\n        new function(a, b, c) {\n            console.log(b + a + c + c);\n        }(\"A\", \"P\", \"S\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4388: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        (arguments => console.log(arguments && arguments))();\n    }\n    expect: {\n        (arguments => console.log(arguments && arguments))();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_4390: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function log() {\n            console.log.apply(console, arguments);\n        }\n        var a = 42, b = \"FAIL\";\n        b = \"PASS\";\n        (c => log(b, c))(a);\n        log(b);\n    }\n    expect: {\n        function log() {\n            console.log.apply(console, arguments);\n        }\n        var a = 42, b = \"FAIL\";\n        b = \"PASS\";\n        (c => log(b, c))(a);\n        log(b);\n    }\n    expect_stdout: [\n        \"PASS 42\",\n        \"PASS\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4401: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function() {\n            var a = (b => b(a))(console.log || a);\n            var c = console.log;\n            c && c(typeof b);\n        })();\n    }\n    expect: {\n        (function() {\n            var a = (b => b(a))(console.log || a);\n            var c = console.log;\n            c && c(typeof b);\n        })();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4448: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var A;\n        try {\n            (arguments => {\n                arguments[0];\n            })(A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var A;\n        try {\n            (arguments => {\n                arguments[0];\n            })(A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4476: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(a, b) {\n            (a => {\n                console.log(arguments[0], a);\n            })(b);\n        })(\"foo\", \"bar\");\n    }\n    expect: {\n        (function(a, b) {\n            (a => {\n                console.log(arguments[0], a);\n            })(b);\n        })(\"foo\", \"bar\");\n    }\n    expect_stdout: \"foo bar\"\n    node_version: \">=4\"\n}\n\nissue_4666: {\n    input: {\n        console.log((a => /[0-9]/.test(a))(42));\n    }\n    expect_exact: \"console.log((a=>/[0-9]/.test(a))(42));\"\n    expect_stdout: \"true\"\n    node_version: \">=4\"\n}\n\nissue_4685_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        new function(f) {\n            if (f() !== this)\n                console.log(\"PASS\");\n        }(() => this);\n    }\n    expect: {\n        new function(f) {\n            if (f() !== this)\n                console.log(\"PASS\");\n        }(() => this);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4685_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        new function(f) {\n            if (f() !== this)\n                console.log(\"PASS\");\n        }(() => {\n            if (console)\n                return this;\n        });\n    }\n    expect: {\n        new function(f) {\n            if (f() !== this)\n                console.log(\"PASS\");\n        }(() => {\n            if (console)\n                return this;\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4687_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        new function() {\n            console.log(function(f) {\n                return f() === this;\n            }(() => this) || \"PASS\");\n        }\n    }\n    expect: {\n        new function() {\n            console.log(function(f) {\n                return f() === this;\n            }(() => this) || \"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4687_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        new function() {\n            console.log(function(f) {\n                return f() === this;\n            }(() => {\n                if (console)\n                    return this;\n            }) || \"PASS\");\n        }\n    }\n    expect: {\n        new function() {\n            console.log(function(f) {\n                return f() === this;\n            }(() => {\n                if (console)\n                    return this;\n            }) || \"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4772: {\n    input: {\n        var f = a => (a)\n        /**/ console.log(f(\"PASS\"));\n    }\n    expect_exact: 'var f=a=>a;console.log(f(\"PASS\"));'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5251: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        (() => {\n            while (console.log(arguments))\n                var arguments = \"FAIL\";\n        })();\n    }\n    expect: {\n        (() => {\n            while (console.log(arguments))\n                var arguments = \"FAIL\";\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_5342_1: {\n    options = {\n        dead_code: true,\n        inline: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var a in 0) {\n            (() => {\n                while (1);\n            })(new function(NaN) {\n                a.p;\n            }());\n        }\n        console.log(function() {\n            return b;\n            try {\n                b;\n            } catch (e) {\n                var b;\n            }\n        }());\n    }\n    expect: {\n        for (var a in 0) {\n            (function(NaN) {\n                a.p;\n            })();\n            while (1);\n        }\n        console.log(b);\n        var b;\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5342_2: {\n    rename = true\n    options = {\n        dead_code: true,\n        inline: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var a in 0) {\n            (() => {\n                while (1);\n            })(new function(NaN) {\n                a.p;\n            }());\n        }\n        console.log(function() {\n            return b;\n            try {\n                b;\n            } catch (e) {\n                var b;\n            }\n        }());\n    }\n    expect: {\n        for (var a in 0) {\n            a.p;\n            while (1);\n        }\n        console.log(c);\n        var c;\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5356: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log((a => a++)(console));\n    }\n    expect: {\n        console.log((a => +a)(console));\n    }\n    expect_stdout: \"NaN\"\n    node_version: \">=4\"\n}\n\nissue_5414_1: {\n    options = {\n        arrows: true,\n        if_return: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        (() => {\n            (() => {\n                if (!console)\n                    var arguments = 42;\n                while (console.log(arguments));\n            })();\n        })();\n    }\n    expect: {\n        (() => {\n            if (!console)\n                var arguments = 42;\n            while (console.log(arguments));\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_5414_2: {\n    options = {\n        arrows: true,\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (() => {\n            (() => {\n                if (!console)\n                    var arguments = 42;\n                while (console.log(arguments));\n            })();\n        })();\n    }\n    expect: {\n        (() => {\n            if (!console)\n                var arguments = 42;\n            while (console.log(arguments));\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_5416_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var f = () => {\n            while ((() => {\n                console;\n                var a = function g(arguments) {\n                    console.log(arguments);\n                }();\n            })());\n        };\n        f();\n    }\n    expect: {\n        var f = () => {\n            console;\n            arguments = void 0,\n            console.log(arguments);\n            var arguments;\n            return;\n        };\n        f();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5416_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var f = () => {\n            while ((() => {\n                console;\n                var a = function g(arguments) {\n                    while (console.log(arguments));\n                }();\n            })());\n        };\n        f();\n    }\n    expect: {\n        var f = () => {\n            console;\n            var arguments = void 0;\n            for (; console.log(arguments););\n            return;\n        };\n        f();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5416_3: {\n    options = {\n        inline: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var f = () => {\n            (() => {\n                var a = function g(arguments) {\n                    console.log(arguments);\n                }();\n            })();\n        };\n        f();\n    }\n    expect: {\n        var f = () => {\n            arguments = void 0,\n            console.log(arguments);\n            var arguments;\n        };\n        f();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5416_4: {\n    options = {\n        arrows: true,\n        inline: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var f = () => {\n            (() => {\n                var a = function g(arguments) {\n                    while (console.log(arguments));\n                }();\n            })();\n        };\n        f();\n    }\n    expect: {\n        var f = () => {\n            var arguments = void 0;\n            while (console.log(arguments));\n            return;\n        };\n        f();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5495: {\n    input: {\n        console.log((() => {\n            \"use strict\";\n            return function() {\n                return this;\n            }();\n        })());\n    }\n    expect_exact: 'console.log((()=>{\"use strict\";return function(){return this}()})());'\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5653: {\n    options = {\n        arrows: true,\n        hoist_props: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log((a => {\n            a = { p: console };\n            return a++;\n        })());\n    }\n    expect: {\n        console.log((a => +{})());\n    }\n    expect_stdout: \"NaN\"\n    node_version: \">=4\"\n}\n"
  },
  {
    "path": "test/compress/asm.js",
    "content": "asm_mixed: {\n    options = {\n        assignments: true,\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        drop_debugger: true,\n        evaluate: true,\n        hoist_funs: true,\n        hoist_vars: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        keep_fnames: false,\n        loops: true,\n        negate_iife: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        // adapted from http://asmjs.org/spec/latest/\n        function asm_GeometricMean(stdlib, foreign, buffer) {\n          \"use asm\";\n          var exp = stdlib.Math.exp;\n          var log = stdlib.Math.log;\n          var values = new stdlib.Float64Array(buffer);\n          function logSum(start, end) {\n            start = start|0;\n            end = end|0;\n            var sum = 0.0, p = 0, q = 0;\n            // asm.js forces byte addressing of the heap by requiring shifting by 3\n            for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n              sum = sum + +log(values[p>>3]);\n            }\n            return +sum;\n          }\n          function geometricMean(start, end) {\n            start = start|0;\n            end = end|0;\n            return +exp(+logSum(start, end) / +((end - start)|0));\n          }\n          return { geometricMean: geometricMean };\n        }\n        function no_asm_GeometricMean(stdlib, foreign, buffer) {\n          var exp = stdlib.Math.exp;\n          var log = stdlib.Math.log;\n          var values = new stdlib.Float64Array(buffer);\n          function logSum(start, end) {\n            start = start|0;\n            end = end|0;\n            var sum = 0.0, p = 0, q = 0;\n            // asm.js forces byte addressing of the heap by requiring shifting by 3\n            for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n              sum = sum + +log(values[p>>3]);\n            }\n            return +sum;\n          }\n          function geometricMean(start, end) {\n            start = start|0;\n            end = end|0;\n            return +exp(+logSum(start, end) / +((end - start)|0));\n          }\n          return { geometricMean: geometricMean };\n        }\n    }\n    expect: {\n        function asm_GeometricMean(stdlib, foreign, buffer) {\n            \"use asm\";\n            var exp = stdlib.Math.exp;\n            var log = stdlib.Math.log;\n            var values = new stdlib.Float64Array(buffer);\n            function logSum(start, end) {\n                start = start | 0;\n                end = end | 0;\n                var sum = 0.0, p = 0, q = 0;\n                for (p = start << 3, q = end << 3; (p | 0) < (q | 0); p = p + 8 | 0)\n                    sum = sum + +log(values[p >> 3]);\n                return +sum;\n            }\n            function geometricMean(start, end) {\n                start = start | 0;\n                end = end | 0;\n                return +exp(+logSum(start, end) / +(end - start | 0));\n            }\n            return { geometricMean: geometricMean };\n        }\n        function no_asm_GeometricMean(stdlib, foreign, buffer) {\n            function logSum(start, end) {\n                start |= 0, end |= 0;\n                for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0)\n                    sum += +log(values[p >> 3]);\n                return +sum;\n            }\n            function geometricMean(start, end) {\n                return start |= 0, end |= 0, +exp(+logSum(start, end) / (end - start | 0));\n            }\n            var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);\n            return { geometricMean: geometricMean };\n        }\n    }\n}\n\nasm_toplevel: {\n    options = {}\n    input: {\n        \"use asm\";\n        0.0;\n        function f() {\n            0.0;\n            (function(){\n                0.0;\n            });\n        }\n        0.0;\n    }\n    expect_exact: '\"use asm\";0.0;function f(){0.0;(function(){0.0})}0.0;'\n}\n\nasm_function_expression: {\n    options = {}\n    input: {\n        0.0;\n        var a = function() {\n            \"use asm\";\n            0.0;\n        }\n        function f() {\n            0.0;\n            return function(){\n                \"use asm\";\n                0.0;\n            }\n            0.0;\n        }\n        0.0;\n    }\n    expect_exact: '0;var a=function(){\"use asm\";0.0};function f(){0;return function(){\"use asm\";0.0};0}0;'\n}\n\nasm_nested_functions: {\n    options = {}\n    input: {\n        0.0;\n        function a() {\n            \"use asm\";\n            0.0;\n        }\n        0.0;\n        function b() {\n            0.0;\n            function c(){\n                \"use asm\";\n                0.0;\n            }\n            0.0;\n            function d(){\n                0.0;\n            }\n            0.0;\n        }\n        0.0;\n    }\n    expect_exact: '0;function a(){\"use asm\";0.0}0;function b(){0;function c(){\"use asm\";0.0}0;function d(){0}0}0;'\n}\n\nissue_3636_1: {\n    mangle = {}\n    input: {\n        function n(stdlib, foreign, buffer) {\n            \"use asm\";\n            function add(x, y) {\n                x = x | 0;\n                y = y | 0;\n                return x + y | 0;\n            }\n            return {\n                add: add\n            };\n        }\n        console.log(new n().add(\"foo\", 42));\n    }\n    expect: {\n        function n(o, e, u) {\n            \"use asm\";\n            function d(n, o) {\n                n = n | 0;\n                o = o | 0;\n                return n + o | 0;\n            }\n            return {\n                add: d\n            };\n        }\n        console.log(new n().add(\"foo\", 42));\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3636_2: {\n    mangle = {}\n    input: {\n        var n = function(stdlib, foreign, buffer) {\n            \"use asm\";\n            function add(x, y) {\n                x = x | 0;\n                y = y | 0;\n                return x + y | 0;\n            }\n            return {\n                add: add\n            };\n        };\n        console.log(new n().add(\"foo\", 42));\n    }\n    expect: {\n        var n = function(n, o, e) {\n            \"use asm\";\n            function r(n, o) {\n                n = n | 0;\n                o = o | 0;\n                return n + o | 0;\n            }\n            return {\n                add: r\n            };\n        };\n        console.log(new n().add(\"foo\", 42));\n    }\n    expect_stdout: \"42\"\n}\n"
  },
  {
    "path": "test/compress/assignments.js",
    "content": "op_equals_left_local_var: {\n    options = {\n        assignments: true,\n        evaluate: true,\n    }\n    input: {\n        var x;\n\n        x = x +   3;\n        x = x -   3;\n        x = x /   3;\n        x = x *   3;\n        x = x >>  3;\n        x = x <<  3;\n        x = x >>> 3;\n        x = x |   3;\n        x = x ^   3;\n        x = x %   3;\n        x = x &   3;\n\n        x = x +   g();\n        x = x -   g();\n        x = x /   g();\n        x = x *   g();\n        x = x >>  g();\n        x = x <<  g();\n        x = x >>> g();\n        x = x |   g();\n        x = x ^   g();\n        x = x %   g();\n        x = x &   g();\n    }\n    expect: {\n        var x;\n\n        x   += 3;\n        x   -= 3;\n        x   /= 3;\n        x   *= 3;\n        x  >>= 3;\n        x  <<= 3;\n        x >>>= 3;\n        x   |= 3;\n        x   ^= 3;\n        x   %= 3;\n        x   &= 3;\n\n        x   += g();\n        x   -= g();\n        x   /= g();\n        x   *= g();\n        x  >>= g();\n        x  <<= g();\n        x >>>= g();\n        x   |= g();\n        x   ^= g();\n        x   %= g();\n        x   &= g();\n    }\n}\n\nop_equals_right_local_var: {\n    options = {\n        assignments: true,\n        evaluate: true,\n    }\n    input: {\n        var x;\n\n        x = (x -= 2) ^ x;\n\n        x = 3 +   x;\n        x = 3 -   x;\n        x = 3 /   x;\n        x = 3 *   x;\n        x = 3 >>  x;\n        x = 3 <<  x;\n        x = 3 >>> x;\n        x = 3 |   x;\n        x = 3 ^   x;\n        x = 3 %   x;\n        x = 3 &   x;\n\n        x = g() +   x;\n        x = g() -   x;\n        x = g() /   x;\n        x = g() *   x;\n        x = g() >>  x;\n        x = g() <<  x;\n        x = g() >>> x;\n        x = g() |   x;\n        x = g() ^   x;\n        x = g() %   x;\n        x = g() &   x;\n    }\n    expect: {\n        var x;\n\n        x = (x -= 2) ^ x;\n\n        x = 3 + x;\n        x = 3 - x;\n        x = 3 / x;\n        x *= 3;\n        x = 3 >> x;\n        x = 3 << x;\n        x = 3 >>> x;\n        x |= 3;\n        x ^= 3;\n        x = 3 % x;\n        x &= 3;\n\n        x = g() +   x;\n        x = g() -   x;\n        x = g() /   x;\n        x = g() *   x;\n        x = g() >>  x;\n        x = g() <<  x;\n        x = g() >>> x;\n        x = g() |   x;\n        x = g() ^   x;\n        x = g() %   x;\n        x = g() &   x;\n    }\n}\nop_equals_left_global_var: {\n    options = {\n        assignments: true,\n        evaluate: true,\n    }\n    input: {\n        x = x +   3;\n        x = x -   3;\n        x = x /   3;\n        x = x *   3;\n        x = x >>  3;\n        x = x <<  3;\n        x = x >>> 3;\n        x = x |   3;\n        x = x ^   3;\n        x = x %   3;\n        x = x &   3;\n\n        x = x +   g();\n        x = x -   g();\n        x = x /   g();\n        x = x *   g();\n        x = x >>  g();\n        x = x <<  g();\n        x = x >>> g();\n        x = x |   g();\n        x = x ^   g();\n        x = x %   g();\n        x = x &   g();\n    }\n    expect: {\n        x   += 3;\n        x   -= 3;\n        x   /= 3;\n        x   *= 3;\n        x  >>= 3;\n        x  <<= 3;\n        x >>>= 3;\n        x   |= 3;\n        x   ^= 3;\n        x   %= 3;\n        x   &= 3;\n\n        x   += g();\n        x   -= g();\n        x   /= g();\n        x   *= g();\n        x  >>= g();\n        x  <<= g();\n        x >>>= g();\n        x   |= g();\n        x   ^= g();\n        x   %= g();\n        x   &= g();\n    }\n}\n\nop_equals_right_global_var: {\n    options = {\n        assignments: true,\n        evaluate: true,\n    }\n    input: {\n        x = (x -= 2) ^ x;\n\n        x = 3 +   x;\n        x = 3 -   x;\n        x = 3 /   x;\n        x = 3 *   x;\n        x = 3 >>  x;\n        x = 3 <<  x;\n        x = 3 >>> x;\n        x = 3 |   x;\n        x = 3 ^   x;\n        x = 3 %   x;\n        x = 3 &   x;\n\n        x = g() +   x;\n        x = g() -   x;\n        x = g() /   x;\n        x = g() *   x;\n        x = g() >>  x;\n        x = g() <<  x;\n        x = g() >>> x;\n        x = g() |   x;\n        x = g() ^   x;\n        x = g() %   x;\n        x = g() &   x;\n    }\n    expect: {\n        x = (x -= 2) ^ x;\n\n        x = 3 +   x;\n        x = 3 -   x;\n        x = 3 /   x;\n        x *= 3;\n        x = 3 >>  x;\n        x = 3 <<  x;\n        x = 3 >>> x;\n        x |= 3;\n        x ^= 3;\n        x = 3 %   x;\n        x &= 3;\n\n        x = g() +   x;\n        x = g() -   x;\n        x = g() /   x;\n        x = g() *   x;\n        x = g() >>  x;\n        x = g() <<  x;\n        x = g() >>> x;\n        x = g() |   x;\n        x = g() ^   x;\n        x = g() %   x;\n        x = g() &   x;\n    }\n}\n\nincrement_decrement_1: {\n    options = {\n        assignments: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            a += 1;\n            a -= 1;\n            return a;\n        }(42));\n    }\n    expect: {\n        console.log(function(a){\n            ++a;\n            --a;\n            return a;\n        }(42));\n    }\n    expect_stdout: \"42\"\n}\n\nincrement_decrement_2: {\n    options = {\n        assignments: true,\n        passes: 2,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            a = a + 1;\n            a = a - 1;\n            a += 1;\n            a -= 1;\n            return a;\n        }(42));\n    }\n    expect: {\n        console.log(function(a){\n            ++a;\n            --a;\n            ++a;\n            --a;\n            return a;\n        }(42));\n    }\n    expect_stdout: \"42\"\n}\n\nlazily_chained_assignments: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        conditionals: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            if (a = console.log(\"foo\"))\n                a = console.log(\"bar\");\n            return a;\n        }\n        function g(b) {\n            if (b = console.log(\"baz\"))\n                ;\n            else\n                b = console.log(\"moo\");\n            return b;\n        }\n        console.log(f(), g());\n    }\n    expect: {\n        function f(a) {\n            return console.log(\"foo\") && console.log(\"bar\");\n        }\n        function g(b) {\n            return console.log(\"baz\") || console.log(\"moo\");\n        }\n        console.log(f(), g());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"moo\",\n        \"undefined undefined\",\n    ]\n}\n\nissue_3375_1: {\n    options = {\n        assignments: true,\n        reduce_vars: true,\n    }\n    input: {\n        function p(o) {\n            console.log(typeof o, o);\n        }\n        p(function(b) {\n            var a = b += 1;\n            --b;\n            return a;\n        }(\"object\"));\n    }\n    expect: {\n        function p(o) {\n            console.log(typeof o, o);\n        }\n        p(function(b) {\n            var a = b += 1;\n            --b;\n            return a;\n        }(\"object\"));\n    }\n    expect_stdout: \"string object1\"\n}\n\nissue_3375_2: {\n    options = {\n        assignments: true,\n        reduce_vars: true,\n    }\n    input: {\n        function p(o) {\n            console.log(typeof o, o);\n        }\n        p(function(b) {\n            var a = b -= 1;\n            --b;\n            return a;\n        }(\"object\"));\n    }\n    expect: {\n        function p(o) {\n            console.log(typeof o, o);\n        }\n        p(function(b) {\n            var a = --b;\n            --b;\n            return a;\n        }(\"object\"));\n    }\n    expect_stdout: \"number NaN\"\n}\n\nissue_3427: {\n    options = {\n        assignments: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            a || (a = {});\n        })();\n    }\n    expect: {}\n}\n\nissue_3429_1: {\n    options = {\n        assignments: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(b) {\n            b && (b = a = \"FAIL\");\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b) {\n            b = b && (a = \"FAIL\");\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3429_2: {\n    options = {\n        assignments: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b) {\n            b || (b = a = \"FAIL\");\n        })(42);\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (function(b) {\n            b = b || (a = \"FAIL\");\n        })(42);\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3949_1: {\n    options = {\n        assignments: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 42;\n        function f() {\n            var b = a;\n            b = b >> 2;\n            return 100 + b;\n        }\n        console.log(f());\n    }\n    expect: {\n        var a = 42;\n        function f() {\n            var b = a;\n            b >>= 2;\n            return 100 + b;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"110\"\n}\n\nissue_3949_2: {\n    options = {\n        assignments: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 42;\n        function f() {\n            var b = a;\n            b = 5 & b;\n            return 100 + b;\n        }\n        console.log(f());\n    }\n    expect: {\n        var a = 42;\n        function f() {\n            var b = a;\n            b &= 5;\n            return 100 + b;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"100\"\n}\n\nissue_4521: {\n    options = {\n        assignments: true,\n        dead_code: true,\n    }\n    input: {\n        var a = (a = 42 | a) ? console.log(a) : 0;\n    }\n    expect: {\n        var a = (a |= 42) ? console.log(a) : 0;\n    }\n    expect_stdout: \"42\"\n}\n\nlogical_assignments: {\n    input: {\n        var a = 42, b = null, c;\n        a &&= \"foo\";\n        b ||= \"bar\";\n        c ??= \"baz\";\n        console.log(a, b, c);\n    }\n    expect_exact: 'var a=42,b=null,c;a&&=\"foo\";b||=\"bar\";c??=\"baz\";console.log(a,b,c);'\n    expect_stdout: \"foo bar baz\"\n    node_version: \">=15\"\n}\n\nlogical_collapse_vars_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\", b = false;\n        a = \"PASS\";\n        b ??= a;\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\", b = false;\n        a = \"PASS\";\n        b ??= a;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nlogical_collapse_vars_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(b) {\n            b ||= (a = \"FAIL\", {});\n            return b;\n        })(console).log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b) {\n            return b ||= (a = \"FAIL\", {});\n        })(console).log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nlogical_collapse_vars_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 6;\n        a *= 7;\n        a ??= \"FAIL\";\n        console.log(a);\n    }\n    expect: {\n        var a = 6;\n        a = a * 7 ?? \"FAIL\";\n        console.log(a);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=15\"\n}\n\nlogical_reduce_vars: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\", b = 42;\n        b ??= a = \"FAIL\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\", b = 42;\n        b ??= a = \"FAIL\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nlogical_side_effects: {\n    options = {\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\", b = 42;\n        b ??= a = \"FAIL\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\", b = 42;\n        b ??= a = \"FAIL\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nevaluate_lazy_assignment: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        console.log(a &&= \"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4815_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        42..p &&= a = \"FAIL\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        42..p &&= a = \"FAIL\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4815_2: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        42..p &&= a = \"FAIL\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        42..p &&= a = \"FAIL\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4819: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        console.log(void 0 === ([].p &&= 42));\n    }\n    expect: {\n        console.log(void 0 === ([].p &&= 42));\n    }\n    expect_stdout: \"true\"\n    node_version: \">=15\"\n}\n\nissue_4827_1: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        A = \"FAIL\";\n        var a = A, b = \"PASS\", c;\n        c &&= b = a, console.log(b);\n    }\n    expect: {\n        var a = A = \"FAIL\", b = \"PASS\", c;\n        c &&= b = a, console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4827_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = \"PASS\";\n        function f(c) {\n            a++,\n            c &&= b = a;\n        }\n        f();\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b = \"PASS\";\n        a++,\n        c &&= b = a;\n        var c;\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4827_3: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b, c;\n        a++;\n        c &&= b = a;\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b, c;\n        a++;\n        c &&= b = a;\n        console.log(b);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=15\"\n}\n\nissue_4876: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            var a = null;\n            var b = a &&= 42;\n            b.p;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            var a = null;\n            var b = a &&= 42;\n            b.p;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4924_1: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b;\n        console.log(\"PASS\");\n        a = function() {};\n        b = function() {}(b ||= a);\n    }\n    expect: {\n        var b;\n        console.log(\"PASS\");\n        b = void (b ||= function() {});\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_4924_2: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        passes: 2,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b;\n        console.log(\"PASS\");\n        a = function() {};\n        b = function() {}(b ||= a);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nissue_5670: {\n    options = {\n        assignments: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a, b) {\n            a && a && (a = b += \"\") || console.log(\"PASS\");\n        })();\n    }\n    expect: {\n        (function(a, b) {\n            a = a,\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5941: {\n    options = {\n        assignments: true,\n        conditionals: true,\n        dead_code: true,\n    }\n    input: {\n        var a = 1;\n        a = a &&= (a = console) && console.log(typeof a);\n    }\n    expect: {\n        var a = 1;\n        a = (a = a && console) && console.log(typeof a);\n    }\n    expect_stdout: \"object\"\n    node_version: \">=15\"\n}\n"
  },
  {
    "path": "test/compress/awaits.js",
    "content": "async_arrow: {\n    input: {\n        (async a => console.log(a))(\"PASS\");\n        console.log(typeof (async () => 42)());\n    }\n    expect_exact: '(async a=>console.log(a))(\"PASS\");console.log(typeof(async()=>42)());'\n    expect_stdout: [\n        \"PASS\",\n        \"object\",\n    ]\n    node_version: \">=8\"\n}\n\nasync_computed: {\n    input: {\n        var o = {\n            async [42]() {\n                return this.p;\n            },\n            p: \"PASS\",\n        };\n        o[42]().then(console.log);\n    }\n    expect_exact: 'var o={async[42](){return this.p},p:\"PASS\"};o[42]().then(console.log);'\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nasync_label: {\n    input: {\n        (async function() {\n            async: console.log(\"PASS\");\n        })();\n    }\n    expect_exact: '(async function(){async:console.log(\"PASS\")})();'\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nawait_await: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            await await {\n                then(resolve) {\n                    resolve({\n                        then() {\n                            console.log(\"PASS\");\n                        },\n                    });\n                },\n            };\n        })();\n    }\n    expect: {\n        (async function() {\n            await {\n                then(resolve) {\n                    resolve({\n                        then() {\n                            console.log(\"PASS\");\n                        },\n                    });\n                },\n            };\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ndefun_name: {\n    input: {\n        async function await() {\n            console.log(\"PASS\");\n        }\n        await();\n    }\n    expect: {\n        async function await() {\n            console.log(\"PASS\");\n        }\n        await();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ndrop_fname: {\n    rename = true\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        async function await() {\n            console.log(\"PASS\");\n        }\n        await();\n    }\n    expect: {\n        (async function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nkeep_fname: {\n    options = {\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        async function await() {\n            console.log(\"PASS\");\n        }\n        await();\n    }\n    expect: {\n        async function await() {\n            console.log(\"PASS\");\n        }\n        await();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nnested_await: {\n    input: {\n        (async function() {\n            console.log(function(await) {\n                return await;\n            }(\"PASS\"));\n        })();\n    }\n    expect: {\n        (async function() {\n            console.log(function(await) {\n                return await;\n            }(\"PASS\"));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nreduce_single_use_defun: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        async function f(a) {\n            console.log(a);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        (async function(a) {\n            console.log(a);\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ndont_inline: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function() {\n            A;\n        })().catch(function() {});\n        console.log(\"PASS\");\n    }\n    expect: {\n        (async function() {\n            A;\n        })().catch(function() {});\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ndont_inline_nested: {\n    options = {\n        inline: true,\n    }\n    input: {\n        function await() {\n            return \"PASS\";\n        }\n        (async function() {\n            (function() {\n                console.log(await(\"FAIL\"));\n            })();\n        })();\n    }\n    expect: {\n        function await() {\n            return \"PASS\";\n        }\n        (async function() {\n            (function() {\n                console.log(await(\"FAIL\"));\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_1: {\n    options = {\n        awaits: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f() {\n                await 42;\n            }\n            return await f();\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        (async function() {\n            return await void await 42;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_1_trim: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f() {\n                await 42;\n            }\n            return await f();\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        0;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_2: {\n    options = {\n        awaits: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f(a) {\n                await a;\n            }\n            return await f(console);\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        (async function() {\n            return await void await console;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_2_trim: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f(a) {\n                await a.log;\n            }\n            return await f(console);\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        (async function() {\n            await console.log;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_3: {\n    options = {\n        awaits: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f(a, b) {\n                return await b(a);\n            }\n            return await f(\"PASS\", console.log);\n        })();\n    }\n    expect: {\n        (async function() {\n            return await (a = \"PASS\", b = console.log, await b(a));\n            var a, b;\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_3_trim: {\n    options = {\n        awaits: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f(a, b) {\n                return await b(a);\n            }\n            return await f(\"PASS\", console.log);\n        })();\n    }\n    expect: {\n        (async function() {\n            return a = \"PASS\", b = console.log, b(a);\n            var a, b;\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_await_this: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var p = \"FAIL\";\n        ({\n            p: \"PASS\",\n            async f() {\n                return await (async () => this.p)();\n            },\n        }).f().then(console.log);\n    }\n    expect: {\n        var p = \"FAIL\";\n        ({\n            p: \"PASS\",\n            async f() {\n                return await this.p;\n            },\n        }).f().then(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ninline_block: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            (async function() {\n                for (var a of [ \"baz\" ])\n                    return a;\n            })();\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            for (var a of [ \"baz\" ])\n                return void await a;\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n        \"undefined\",\n    ]\n    node_version: \">=8\"\n}\n\ninline_block_async: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            (async function() {\n                for (var a of [ \"baz\" ])\n                    return {\n                        then(r) {\n                            console.log(\"moo\");\n                            r(a);\n                        },\n                    };\n            })();\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            for (var a of [ \"baz\" ])\n                return void await {\n                    then(r) {\n                        console.log(\"moo\");\n                        r(a);\n                    },\n                };\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moz\",\n        \"moo\",\n        \"undefined\",\n    ]\n    node_version: \">=8\"\n}\n\ninline_block_await: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            await async function() {\n                for (var a of [ \"baz\" ])\n                    return a;\n            }();\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            for (var a of [ \"baz\" ])\n                return void await a;\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n        \"undefined\",\n    ]\n    node_version: \">=8\"\n}\n\ninline_block_await_async: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            console.log(\"foo\");\n            await (async function() {\n                while (await console.log(\"bar\"));\n                console.log(\"baz\");\n            })();\n            console.log(\"moo\");\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect: {\n        (async function() {\n            console.log(\"foo\");\n            while (await console.log(\"bar\"));\n            console.log(\"baz\");\n            await 0;\n            console.log(\"moo\");\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moz\",\n        \"baz\",\n        \"moo\",\n        \"undefined\",\n    ]\n    node_version: \">=8\"\n}\n\ninline_block_await_async_return: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            await async function() {\n                for (var a of [ \"baz\" ])\n                    return {\n                        then(r) {\n                            console.log(\"moo\");\n                            r(a);\n                        },\n                    };\n            }();\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            for (var a of [ \"baz\" ])\n                return void await {\n                    then(r) {\n                        console.log(\"moo\");\n                        r(a);\n                    },\n                };;\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moz\",\n        \"moo\",\n        \"undefined\",\n    ]\n    node_version: \">=8\"\n}\n\ninline_block_return: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            return async function() {\n                for (var a of [ \"baz\" ])\n                    return a;\n            }();\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            for (var a of [ \"baz\" ])\n                return a;\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\ninline_block_return_async: {\n    options = {\n        awaits: true,\n        if_return: true,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            return async function() {\n                for (var a of [ \"baz\" ])\n                    return {\n                        then(r) {\n                            console.log(\"moo\");\n                            r(a);\n                        },\n                    };\n            }();\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            console.log(\"bar\");\n            for (var a of [ \"baz\" ])\n                return {\n                    then(r) {\n                        console.log(\"moo\");\n                        r(a);\n                    },\n                };\n        })().then(console.log);\n        console.log(\"moz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moz\",\n        \"moo\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nawait_then: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            f(), await 42;\n            while (console.log(a));\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await !f();\n            while (console.log(a));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nawait_unary_1: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await !f();\n            while (console.log(a));\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await !f();\n            while (console.log(a));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nawait_unary_2: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await ~f();\n            while (console.log(a));\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await !f();\n            while (console.log(a));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nawait_unary_3: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        (async function() {\n            a = \"PASS\";\n            await delete a.p;\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (async function() {\n            a = \"PASS\";\n            await delete a.p;\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nawait_void_1: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await void f();\n            while (console.log(a));\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        function f() {\n            return {\n                then: function(r) {\n                    a = \"FAIL\";\n                    r();\n                },\n            };\n        }\n        (async function() {\n            await !f();\n            while (console.log(a));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nawait_void_2: {\n    options = {\n        awaits: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            console.log(\"PASS\");\n            return await void 42;\n        })();\n    }\n    expect: {\n        (async function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nevaluate: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = async function() {}();\n        console.log(typeof a);\n    }\n    expect: {\n        var a = async function() {}();\n        console.log(typeof a);\n    }\n    expect_stdout: \"object\"\n    node_version: \">=8\"\n}\n\nnegate: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console && async function() {} && console.log(\"PASS\");\n    }\n    expect: {\n        console && async function() {} && console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nnegate_iife: {\n    options = {\n        negate_iife: true,\n    }\n    input: {\n        (async function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect: {\n        !async function() {\n            console.log(\"PASS\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nobject_function: {\n    options = {\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        ({\n            async f() {\n                console.log(\"PASS\");\n            },\n        }).f();\n    }\n    expect: {\n        (async () => {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncollapse_vars_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (async function() {\n            a = \"PASS\";\n            await 42;\n            return \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (async function() {\n            a = \"PASS\";\n            await 42;\n            return \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncollapse_vars_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (async function() {\n            await (a = \"PASS\");\n            return \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (async function() {\n            await (a = \"PASS\");\n            return \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncollapse_vars_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (async function() {\n            await (a = \"PASS\", 42);\n            return \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (async function() {\n            await (a = \"PASS\", 42);\n            return \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncollapse_funarg_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        var a = \"PASS\";\n        (async function({}, b) {\n            return b;\n        })(null, A = a);\n        console.log(A);\n    }\n    expect: {\n        A = \"FAIL\";\n        var a = \"PASS\";\n        (async function({}, b) {\n            return b;\n        })(null, A = a);\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncollapse_funarg_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        B = \"PASS\";\n        (async function() {\n            console.log(function({}, a) {\n                return a;\n            }(null, A = B));\n        })();\n        console.log(A);\n    }\n    expect: {\n        A = \"FAIL\";\n        B = \"PASS\";\n        (async function() {\n            console.log(function({}, a) {\n                return a;\n            }(null, A = B));\n        })();\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncollapse_property_lambda: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        (async function f() {\n            f.g = () => 42;\n            return f.g();\n        })().then(console.log);\n    }\n    expect: {\n        (async function f() {\n            return (f.g = () => 42)();\n        })().then(console.log);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=8\"\n}\n\ndrop_async_1: {\n    options = {\n        awaits: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a) {\n            (async function() {\n                a *= 7;\n            })();\n            return a;\n        }(6));\n    }\n    expect: {\n        console.log(function(a) {\n            a *= 7;\n            return a;\n        }(6));\n    }\n    expect_stdout: \"42\"\n    node_version: \">=8\"\n}\n\ndrop_async_2: {\n    options = {\n        awaits: true,\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a) {\n            (async b => await (a *= b))(7);\n            return a;\n        }(6));\n    }\n    expect: {\n        console.log(42);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=8\"\n}\n\ndrop_return: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (async function(a) {\n            while (!console);\n            return !console.log(a);\n        })(42);\n    }\n    expect: {\n        (async function(a) {\n            while (!console);\n            console.log(a);\n        })(42);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=8\"\n}\n\nfunctions: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !async function() {\n            var a = async function a() {\n                return a && \"a\";\n            };\n            var b = async function x() {\n                return !!x;\n            };\n            var c = async function(c) {\n                return c;\n            };\n            if (await c(await b(await a()))) {\n                var d = async function() {};\n                var e = async function y() {\n                    return typeof y;\n                };\n                var f = async function(f) {\n                    return f;\n                };\n                console.log(await a(await d()), await b(await e()), await c(await f(42)), typeof d, await e(), typeof f);\n            }\n        }();\n    }\n    expect: {\n        !async function() {\n            async function a() {\n                return a && \"a\";\n            }\n            async function b() {\n                return !!b;\n            }\n            async function c(c) {\n                return c;\n            }\n            if (await c(await b(await a()))) {\n                var d = async function() {};\n                var e = async function y() {\n                    return typeof y;\n                };\n                var f = async function(f) {\n                    return f;\n                };\n                console.log(await a(await d()), await b(await e()), await c(await f(42)), typeof d, await e(), typeof f);\n            }\n        }();\n    }\n    expect_stdout: \"a true 42 function function function\"\n    node_version: \">=8\"\n}\n\nfunctions_use_strict: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        !async function() {\n            var a = async function a() {\n                return a && \"a\";\n            };\n            var b = async function x() {\n                return !!x;\n            };\n            var c = async function(c) {\n                return c;\n            };\n            if (await c(await b(await a()))) {\n                var d = async function() {};\n                var e = async function y() {\n                    return typeof y;\n                };\n                var f = async function(f) {\n                    return f;\n                };\n                console.log(await a(await d()), await b(await e()), await c(await f(42)), typeof d, await e(), typeof f);\n            }\n        }();\n    }\n    expect: {\n        \"use strict\";\n        !async function() {\n            async function a() {\n                return a && \"a\";\n            }\n            async function b() {\n                return !!b;\n            }\n            async function c(c) {\n                return c;\n            }\n            if (await c(await b(await a()))) {\n                var d = async function() {};\n                var e = async function y() {\n                    return typeof y;\n                };\n                var f = async function(f) {\n                    return f;\n                };\n                console.log(await a(await d()), await b(await e()), await c(await f(42)), typeof d, await e(), typeof f);\n            }\n        }();\n    }\n    expect_stdout: \"a true 42 function function function\"\n    node_version: \">=8\"\n}\n\nfunctions_anonymous: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var await = async function() {\n            console.log(\"PASS\");\n        };\n        await(await);\n    }\n    expect: {\n        async function await() {\n            console.log(\"PASS\");\n        }\n        await();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nfunctions_inner_var: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var await = function a() {\n            var a;\n            console.log(a, a);\n        };\n        await(await);\n    }\n    expect: {\n        function await() {\n            var a;\n            console.log(a, a);\n        }\n        await();\n    }\n    expect_stdout: \"undefined undefined\"\n    node_version: \">=8\"\n}\n\ninstanceof_lambda_1: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(42 instanceof async function() {});\n    }\n    expect: {\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n    node_version: \">=8\"\n}\n\ninstanceof_lambda_2: {\n    options = {\n        evaluate: true,\n        side_effects: false,\n    }\n    input: {\n        console.log(null instanceof async function() {});\n    }\n    expect: {\n        console.log((null, async function() {}, false));\n    }\n    expect_stdout: \"false\"\n    node_version: \">=8\"\n}\n\ninstanceof_lambda_3: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log({} instanceof async function() {});\n    }\n    expect: {\n        console.log({} instanceof async function() {});\n    }\n    expect_stdout: TypeError(\"Function has non-object prototype 'undefined' in instanceof check\")\n    node_version: \">=8\"\n}\n\ninstanceof_lambda_4: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({ p: \"foo\" }) instanceof async function() {};\n    }\n    expect: {\n        [] instanceof async function() {};\n    }\n    expect_stdout: TypeError(\"Function has non-object prototype 'undefined' in instanceof check\")\n    node_version: \">=8\"\n}\n\nasync_to_arrow: {\n    options = {\n        arrows: true,\n        module: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            var f = async function(a, b, c) {\n                return b + a + c + c;\n            };\n            console.log(await f(\"A\", \"P\", \"S\"));\n        })();\n    }\n    expect: {\n        (async () => {\n            console.log(await (async (a, b, c) => b + a + c + c)(\"A\", \"P\", \"S\"));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4335_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var await = \"PASS\";\n        (async function() {\n            console.log(function() {\n                return await;\n            }());\n        })();\n    }\n    expect: {\n        var await = \"PASS\";\n        (async function() {\n            console.log(function() {\n                return await;\n            }());\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4335_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function() {\n            console.log(function() {\n                function await() {}\n                return \"PASS\";\n            }());\n        })();\n    }\n    expect: {\n        (async function() {\n            console.log(function() {\n                function await() {}\n                return \"PASS\";\n            }());\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4337: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            a();\n        })(async function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect: {\n        (function(a) {\n            (async function() {\n                console.log(\"PASS\");\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4340: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (async function a(a) {\n            console.log(a || \"PASS\");\n        })();\n    }\n    expect: {\n        (async function a(a) {\n            console.log(a || \"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\ncall_expression: {\n    input: {\n        console.log(typeof async function(log) {\n            (await log)(\"foo\");\n        }(console.log).then);\n        console.log(\"bar\");\n    }\n    expect_exact: 'console.log(typeof async function(log){(await log)(\"foo\")}(console.log).then);console.log(\"bar\");'\n    expect_stdout: [\n        \"function\",\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=8\"\n}\n\nproperty_access_expression: {\n    input: {\n        console.log(typeof async function(con) {\n            (await con).log(\"foo\");\n        }(console).then);\n        console.log(\"bar\");\n    }\n    expect_exact: 'console.log(typeof async function(con){(await con).log(\"foo\")}(console).then);console.log(\"bar\");'\n    expect_stdout: [\n        \"function\",\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=8\"\n}\n\nreduce_iife_1: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (async function(a) {\n            console.log(a + a);\n        })(21);\n    }\n    expect: {\n        (async function() {\n            console.log(42);\n        })();\n    }\n    expect_stdout: \"42\"\n    node_version: \">=8\"\n}\n\nreduce_iife_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 21;\n        (async function() {\n            console.log(a + a);\n        })();\n    }\n    expect: {\n        (async function() {\n            console.log(42);\n        })();\n    }\n    expect_stdout: \"42\"\n    node_version: \">=8\"\n}\n\nreduce_iife_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            console.log(a, await a, a, await a);\n        })();\n        a = \"bar\";\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            console.log(a, await a, a, await a);\n        })();\n        a = \"bar\";\n    }\n    expect_stdout: \"foo foo bar bar\"\n    node_version: \">=8\"\n}\n\nissue_4347_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        f();\n        a = \"bar\";\n        f();\n        async function f() {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"foo\";\n        f();\n        a = \"bar\";\n        f();\n        async function f() {\n            console.log(a);\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_4347_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (async function() {\n            throw 42;\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (async function() {\n            throw 42;\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4349_1: {\n    input: {\n        console.log(typeof async function() {\n            await /abc/;\n        }().then);\n    }\n    expect_exact: \"console.log(typeof async function(){await/abc/}().then);\"\n    expect_stdout: \"function\"\n    node_version: \">=8\"\n}\n\nissue_4349_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof async function() {\n            (function(a) {\n                this[a];\n            }(await 0));\n        }().then);\n    }\n    expect: {\n        console.log(typeof async function() {\n            (function(a) {\n                this[a];\n            }(await 0));\n        }().then);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=8\"\n}\n\nissue_4349_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function(await) {\n            return async function(a) {\n                this[a];\n            }(await);\n        }(this).then);\n    }\n    expect: {\n        console.log(typeof function(await) {\n            return async function(a) {\n                this[a];\n            }(await);\n        }(this).then);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=8\"\n}\n\nissue_4359: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        try {\n            (async function(a) {\n                return a;\n            })(A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (async function(a) {\n                return a;\n            })(A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4377: {\n    options = {\n        dead_code: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(typeof function() {\n            return function() {\n                f;\n                async function f() {}\n                return f();\n            }();\n        }().then);\n    }\n    expect: {\n        console.log(typeof function() {\n            return f();\n            async function f() {}\n        }().then);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=8\"\n}\n\nissue_4406: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        A = \"PASS\";\n        B = \"FAIL\";\n        (function() {\n            var a, b;\n            a = A;\n            (async function({\n                [console.log(a)]: {},\n            }) {})((b = B) && { undefined: b });\n        })();\n    }\n    expect: {\n        A = \"PASS\";\n        B = \"FAIL\";\n        (function() {\n            var a, b;\n            a = A;\n            (async function({\n                [console.log(a)]: {},\n            }) {})((b = B) && { undefined: b });\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4417: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function() {\n            console.log(function() {\n                return await => 0;\n            }().prototype);\n        })();\n    }\n    expect: {\n        (async function() {\n            console.log(function() {\n                return await => 0;\n            }().prototype);\n        })();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=8\"\n}\n\nissue_4454_1: {\n    rename = false\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            (async function(b = console.log(a)) {})();\n            var await = 42..toString();\n            console.log(await);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function f(a) {\n            (async function(b = console.log(a)) {})();\n            var await = 42..toString();\n            console.log(await);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_4454_2: {\n    rename = true\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            (async function(b = console.log(a)) {})();\n            var await = 42..toString();\n            console.log(await);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function f(a) {\n            (async function(c = console.log(a)) {})();\n            var b = 42..toString();\n            console.log(b);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_4534: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        (function(await) {\n            (async () => console.log(arguments[0]))();\n        })(\"PASS\");\n    }\n    expect: {\n        (function(await) {\n            (async () => console.log(arguments[0]))();\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4581: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (async () => (A, a = \"FAIL\"))();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (async () => (A, a = \"FAIL\"))();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4595: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await async function f() {\n                console.log(f.length);\n            }();\n        })();\n    }\n    expect: {\n        (async function() {\n            await async function f() {\n                console.log(f.length);\n            }();\n        })();\n    }\n    expect_stdout: \"0\"\n    node_version: \">=8\"\n}\n\nissue_4598: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (console.log(\"PASS\")) {\n            async function f() {}\n        }\n    }\n    expect: {\n        async function f() {}\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4618: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            var await = async function f() {\n                console || f();\n            };\n            console.log;\n            return await;\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            var await = async function f() {\n                console || f();\n            };\n            console.log;\n            return await;\n        }());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=8\"\n}\n\nissue_4717: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            async function f() {\n                var a = function() {\n                    await;\n                }();\n                return \"FAIL\";\n            }\n            return f();\n        })().then(console.log).catch(function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect: {\n        (async function() {\n            return function() {\n                await;\n            }(), \"FAIL\";\n        })().then(console.log).catch(function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4738_1: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            await {\n                then() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect: {\n        (async function() {\n            await {\n                then() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4738_2: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            await {\n                get then() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect: {\n        (async function() {\n            await {\n                get then() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4738_3: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            await {\n                then: function() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect: {\n        (async function() {\n            await {\n                then: function() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4747: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            async function f() {\n                a = \"PASS\";\n                null.p += \"PASS\";\n            }\n            f();\n            return a;\n        }(\"FAIL\"));\n    }\n    expect: {\n        console.log(function(a) {\n            (async function() {\n                a = \"PASS\";\n                null.p += \"PASS\";\n            })();\n            return a;\n        }(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4764_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            return {\n                then() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect: {\n        (async function() {\n            return {\n                then() {\n                    console.log(\"PASS\");\n                },\n            };\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4764_2: {\n    options = {\n        arrows: true,\n        side_effects: true,\n    }\n    input: {\n        (async () => ({\n            get then() {\n                console.log(\"PASS\");\n            },\n        }))();\n    }\n    expect: {\n        (async () => ({\n            get then() {\n                console.log(\"PASS\");\n            },\n        }))();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4764_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (async function(o) {\n            return o;\n        })({\n            then() {\n                console.log(\"PASS\");\n            },\n        });\n    }\n    expect: {\n        (async function(o) {\n            return o;\n        })({\n            then() {\n                console.log(\"PASS\");\n            },\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4972_1: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            try {\n                return await \"bar\";\n            } finally {\n                console.log(\"baz\");\n            }\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            try {\n                return await \"bar\";\n            } finally {\n                console.log(\"baz\");\n            }\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"moo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_4972_2: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        (async function() {\n            try {\n                console.log(\"bar\");\n            } finally {\n                return await \"baz\";\n            }\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\");\n        (async function() {\n            try {\n                console.log(\"bar\");\n            } finally {\n                return \"baz\";\n            }\n        })().then(console.log);\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_4972_3: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\"foo\");\n        try {\n            (async function() {\n                return await \"bar\";\n            })().then(console.log);\n        } finally {\n            console.log(\"baz\");\n        }\n        console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\");\n        try {\n            (async function() {\n                return \"bar\";\n            })().then(console.log);\n        } finally {\n            console.log(\"baz\");\n        }\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"moo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_4974: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function f() {\n            return 42 in f();\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        (async function f() {\n            return 42 in f();\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: true\n    node_version: \">=8\"\n}\n\nissue_4975: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function f(a) {\n            try {\n                if (a) console.log(typeof f());\n            } catch (e) {}\n        })(42);\n    }\n    expect: {\n        (async function f(a) {\n            try {\n                if (a) console.log(typeof f());\n            } catch (e) {}\n        })(42);\n    }\n    expect_stdout: \"object\"\n    node_version: \">=8\"\n}\n\nissue_4987: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            try {\n                await 42;\n            } finally {\n                console.log(\"foo\");\n            }\n        })();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function() {\n            try {\n                await 0;\n            } finally {\n                console.log(\"foo\");\n            }\n        })();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5001: {\n    options = {\n        awaits: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 0;\n        (async function() {\n            a++ | await 42;\n        })();\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = 0;\n        a++;\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5019_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        (function(a) {\n            (async function() {\n                await 42;\n                console.log(a);\n            })();\n            a = \"PASS\";\n        })(\"FAIL\");\n    }\n    expect: {\n        (function(a) {\n            (async function() {\n                await 42;\n                console.log(a);\n            })();\n            a = \"PASS\";\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5019_2: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(\"sync\", function(a) {\n            (async function() {\n                console.log(await \"async\", a);\n            })();\n            return a = \"PASS\";\n        }(\"FAIL\"));\n    }\n    expect: {\n        console.log(\"sync\", function(a) {\n            (async function() {\n                console.log(await \"async\", a);\n            })();\n            return a = \"PASS\";\n        }(\"FAIL\"));\n    }\n    expect_stdout: [\n        \"sync PASS\",\n        \"async PASS\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5019_3: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var i in \"foo\") {\n            (function(a) {\n                (async function() {\n                    console.log(await \"async\", a);\n                })();\n            })(i);\n            console.log(\"sync\", i);\n        }\n    }\n    expect: {\n        for (var i in \"foo\") {\n            (function(a) {\n                (async function() {\n                    console.log(await \"async\", a);\n                })();\n            })(i);\n            console.log(\"sync\", i);\n        }\n    }\n    expect_stdout: [\n        \"sync 0\",\n        \"sync 1\",\n        \"sync 2\",\n        \"async 0\",\n        \"async 1\",\n        \"async 2\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5023_1: {\n    options = {\n        awaits: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            let a = a;\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        (async function() {\n            let a = a;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5023_2: {\n    options = {\n        awaits: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            let a;\n            a = a;\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        (function() {\n            let a;\n            a = a;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5034: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var await = function f() {\n                return async function() {\n                    return f;\n                };\n            };\n            await()().then(function(value) {\n                console.log(value === await ? \"PASS\" : \"FAIL\");\n            });\n        })();\n    }\n    expect: {\n        (function() {\n            var await = function f() {\n                return async function() {\n                    return f;\n                };\n            };\n            await()().then(function(value) {\n                console.log(value === await ? \"PASS\" : \"FAIL\");\n            });\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5070: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            try {\n                for await (var a of console.log(\"PASS\"));\n            } catch (e) {}\n        })();\n    }\n    expect: {\n        (async function() {\n            try {\n                for await (var a of console.log(\"PASS\"));\n            } catch (e) {}\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5157_async_function: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        async function f() {\n            throw \"FAIL\";\n        }\n        (async function() {\n            try {\n                return await f();\n            } catch (e) {\n                return \"PASS\";\n            }\n        })().then(console.log);\n    }\n    expect: {\n        async function f() {\n            throw \"FAIL\";\n        }\n        (async function() {\n            try {\n                return await f();\n            } catch (e) {\n                return \"PASS\";\n            }\n        })().then(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5157_async_iife: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            try {\n                return await async function() {\n                    throw \"FAIL\";\n                }();\n            } catch (e) {\n                return \"PASS\";\n            }\n        })().then(console.log);\n    }\n    expect: {\n        (async function() {\n            try {\n                return await async function() {\n                    throw \"FAIL\";\n                }();\n            } catch (e) {\n                return \"PASS\";\n            }\n        })().then(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5157_promise: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var p = new Promise(function(resolve, reject) {\n            reject(\"FAIL\");\n        });\n        (async function() {\n            try {\n                return await p;\n            } catch (e) {\n                return \"PASS\";\n            }\n        })().then(console.log);\n    }\n    expect: {\n        var p = new Promise(function(resolve, reject) {\n            reject(\"FAIL\");\n        });\n        (async function() {\n            try {\n                return await p;\n            } catch (e) {\n                return \"PASS\";\n            }\n        })().then(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5159_1: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            try {\n                throw \"foo\";\n            } catch (e) {\n                return await \"bar\";\n            } finally {\n                console.log(\"baz\");\n            }\n        })().catch(console.log).then(console.log);\n        console.log(\"moo\");\n    }\n    expect: {\n        (async function() {\n            try {\n                throw \"foo\";\n            } catch (e) {\n                return await \"bar\";\n            } finally {\n                console.log(\"baz\");\n            }\n        })().catch(console.log).then(console.log);\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"moo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5159_2: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        (async function() {\n            try {\n                throw \"foo\";\n            } catch (e) {\n                return await \"bar\";\n            }\n        })().catch(console.log).then(console.log);\n        console.log(\"baz\");\n    }\n    expect: {\n        (async function() {\n            try {\n                throw \"foo\";\n            } catch (e) {\n                return \"bar\";\n            }\n        })().catch(console.log).then(console.log);\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5177: {\n    options = {\n        properties: true,\n    }\n    input: {\n        (async function() {\n            return {\n                p(await) {},\n            }.p;\n        })().then(function(a) {\n            console.log(typeof a);\n        });\n    }\n    expect: {\n        (async function() {\n            return {\n                p(await) {},\n            }.p;\n        })().then(function(a) {\n            console.log(typeof a);\n        });\n    }\n    expect_stdout: \"function\"\n    node_version: \">=8\"\n}\n\nissue_5250: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await function() {\n                while (console.log(\"foo\"));\n            }();\n            console.log(\"bar\");\n        })();\n        console.log(\"baz\");\n    }\n    expect: {\n        (async function() {\n            while (console.log(\"foo\"));\n            await 0;\n            console.log(\"bar\");\n        })();\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5258_1: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            (async function() {\n                throw \"FAIL\";\n            })();\n            return \"PASS\";\n        })().catch(console.log).then(console.log);\n    }\n    expect: {\n        (async function() {\n            (async function() {\n                throw \"FAIL\";\n            })();\n            return \"PASS\";\n        })().catch(console.log).then(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5258_2: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        function f() {\n            throw \"FAIL\";\n        }\n        (async function() {\n            (async function() {\n                f();\n            })();\n            return \"PASS\";\n        })().catch(console.log).then(console.log);\n    }\n    expect: {\n        function f() {\n            throw \"FAIL\";\n        }\n        (async function() {\n            (async function() {\n                f();\n            })();\n            return \"PASS\";\n        })().catch(console.log).then(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5298: {\n    options = {\n        awaits: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (async function() {\n            for (a in [ 42 in null ]);\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (async function() {\n            for (a in [ 42 in null ]);\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5305_1: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (async function() {\n            try {\n                return await function() {\n                    while (!console);\n                }();\n            } finally {\n                a = \"FAIL\";\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (async function() {\n            try {\n                while (!console);\n                return await void 0;\n            } finally {\n                a = \"FAIL\";\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5305_2: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (async function() {\n            try {\n                throw null;\n            } catch (e) {\n                return await function() {\n                    while (!console);\n                }();\n            } finally {\n                a = \"FAIL\";\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (async function() {\n            try {\n                throw null;\n            } catch (e) {\n                while (!console);\n                return await void 0;\n            } finally {\n                a = \"FAIL\";\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5305_3: {\n    options = {\n        awaits: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (async function() {\n            try {\n                await function() {\n                    while (!console);\n                }();\n            } catch (e) {\n                a = \"FAIL\";\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        try {\n            while (!console);\n        } catch (e) {\n            a = \"FAIL\";\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5456: {\n    options = {\n        inline: true,\n        merge_vars: true,\n    }\n    input: {\n        var a = true;\n        (function() {\n            (function(b, c) {\n                var d = async function() {\n                    c = await null;\n                }();\n                var e = function() {\n                    if (c)\n                        console.log(typeof d);\n                    while (b);\n                }();\n            })(function(i) {\n                return console.log(\"foo\") && i;\n            }(a));\n        })();\n    }\n    expect: {\n        var a = true;\n        (function() {\n            b = (i = a, console.log(\"foo\") && i),\n            d = async function() {\n                c = await null;\n            }(),\n            e = function() {\n                if (c) console.log(typeof d);\n                while (b);\n            }(),\n            void 0;\n            var b, c, d, e;\n            var i;\n        })();\n    }\n    expect_stdout: \"foo\"\n    node_version: \">=8\"\n}\n\nissue_5478: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        A = {\n            get then() {\n                a = \"FAIL\";\n            },\n        };\n        var a = \"PASS\";\n        (async function() {\n            for (var b in \"foo\")\n                return void A;\n        })();\n        console.log(a);\n    }\n    expect: {\n        A = {\n            get then() {\n                a = \"FAIL\";\n            },\n        };\n        var a = \"PASS\";\n        (async function() {\n            for (var b in \"foo\")\n                return !A;\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5493: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        (async function(a) {\n            var b = await [ 42 || b, a = b ];\n            console.log(a);\n        })();\n    }\n    expect: {\n        (async function(a) {\n            var b = await [ 42 || b, a = b ];\n            console.log(a);\n        })();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=8\"\n}\n\nissue_5506: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function(a) {\n            (async function() {\n                a = null in (a = \"PASS\");\n            })();\n            return a;\n        }(\"FAIL\"));\n    }\n    expect: {\n        console.log(function(a) {\n            (async function() {\n                a = null in (a = \"PASS\");\n            })();\n            return a;\n        }(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5528_1: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await function() {\n                try {\n                    return;\n                } finally {\n                    console.log(\"foo\");\n                }\n            }();\n        })();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function() {\n            await function() {\n                try {\n                    return;\n                } finally {\n                    console.log(\"foo\");\n                }\n            }();\n        })();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5528_2: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await function() {\n                try {\n                    return 42;\n                } finally {\n                    console.log(\"foo\");\n                }\n            }();\n        })();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function() {\n            await function() {\n                try {\n                    return 42;\n                } finally {\n                    console.log(\"foo\");\n                }\n            }();\n        })();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5528_3: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await function() {\n                try {\n                    FAIL;\n                } catch (e) {\n                    return console.log(\"foo\");\n                } finally {\n                    console.log(\"bar\");\n                }\n            }();\n        })();\n        console.log(\"baz\");\n    }\n    expect: {\n        (async function() {\n            await function() {\n                try {\n                    FAIL;\n                } catch (e) {\n                    return console.log(\"foo\");\n                } finally {\n                    console.log(\"bar\");\n                }\n            }();\n        })();\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5528_4: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await function() {\n                try {\n                    return {\n                        then() {\n                            console.log(\"foo\");\n                        },\n                    };\n                } finally {\n                    console.log(\"bar\");\n                }\n            }();\n        })();\n        console.log(\"baz\");\n    }\n    expect: {\n        (async function() {\n            await function() {\n                try {\n                    return {\n                        then() {\n                            console.log(\"foo\");\n                        },\n                    };\n                } finally {\n                    console.log(\"bar\");\n                }\n            }();\n        })();\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"bar\",\n        \"baz\",\n        \"foo\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5634_1: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            (async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            })();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            (async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            })();\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5634_1_side_effects: {\n    options = {\n        awaits: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            (async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            })();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            try {\n                return {\n                    then(resolve) {\n                        console.log(\"bar\");\n                        resolve();\n                        console.log(\"baz\");\n                    },\n                };\n            } finally {\n                a = \"moo\";\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5634_2: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            await async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            }();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            await async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            }();\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5634_2_side_effects: {\n    options = {\n        awaits: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            await async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            }();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            try {\n                return {\n                    then(resolve) {\n                        console.log(\"bar\");\n                        resolve();\n                        console.log(\"baz\");\n                    },\n                };\n            } finally {\n                a = \"moo\";\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5634_3: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            return async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            }();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            return async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            }();\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5634_3_side_effects: {\n    options = {\n        awaits: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"foo\";\n        (async function() {\n            return async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            console.log(\"bar\");\n                            resolve();\n                            console.log(\"baz\");\n                        },\n                    };\n                } finally {\n                    a = \"moo\";\n                }\n            }();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (async function() {\n            try {\n                return {\n                    then(resolve) {\n                        console.log(\"bar\");\n                        resolve();\n                        console.log(\"baz\");\n                    },\n                };\n            } finally {\n                a = \"moo\";\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5692_1: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            (async function() {\n                for await (var k of []);\n            })();\n            console.log(\"foo\");\n        })();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function() {\n            (async function() {\n                for await (var k of []);\n            })();\n            console.log(\"foo\");\n        })();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5692_2: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            (async function() {\n                for (var k of []);\n            })();\n            console.log(\"foo\");\n        })();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function() {\n            for (var k of []);\n            console.log(\"foo\");\n        })();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5791: {\n    options = {\n        awaits: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (async function() {\n            async function f() {\n                try {\n                    await {\n                        then(resolve) {\n                            setImmediate(() => {\n                                console.log(\"foo\");\n                                resolve();\n                            });\n                        },\n                    };\n                } catch (e) {\n                    console.log(\"FAIL\", e);\n                }\n            }\n            async function g() {\n                try {\n                    await f();\n                } catch (e) {}\n            }\n            await g();\n            console.log(\"bar\");\n        })();\n    }\n    expect: {\n        (async function() {\n            await async function() {\n                try {\n                    await async function() {\n                        try {\n                            await {\n                                then(resolve) {\n                                    setImmediate(() => {\n                                        console.log(\"foo\");\n                                        resolve();\n                                    });\n                                },\n                            };\n                        } catch (e) {\n                            console.log(\"FAIL\", e);\n                        }\n                    }();\n                } catch (e) {}\n            }();\n            console.log(\"bar\");\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5842: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (async function() {\n            await function() {\n                try {\n                    try {\n                        return console;\n                    } finally {\n                        a = \"PASS\";\n                    }\n                } catch (e) {}\n                FAIL;\n            }();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (async function() {\n            await function() {\n                try {\n                    try {\n                        return console;\n                    } finally {\n                        a = \"PASS\";\n                    }\n                } catch (e) {}\n                FAIL;\n            }();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_5956: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function() {\n            await function() {\n                try {\n                    FAIL;\n                } finally {\n                    try {\n                        return 42;\n                    } finally {\n                        console.log(\"foo\");\n                    }\n                }\n            }();\n        })();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function() {\n            await function() {\n                try {\n                    FAIL;\n                } finally {\n                    try {\n                        return 42;\n                    } finally {\n                        console.log(\"foo\");\n                    }\n                }\n            }();\n        })();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8\"\n}\n"
  },
  {
    "path": "test/compress/bigint.js",
    "content": "arithmetic: {\n    input: {\n        console.log(((1n + 0x2n) * (0o3n - -4n)) >> (5n - 6n));\n    }\n    expect_exact: \"console.log((1n+0x2n)*(0o3n- -4n)>>5n-6n);\"\n    expect_stdout: \"42n\"\n    node_version: \">=10.4.0\"\n}\n\nminus_dot: {\n    input: {\n        console.log(typeof -42n.toString(), typeof (-42n).toString());\n    }\n    expect_exact: \"console.log(typeof-42n.toString(),typeof(-42n).toString());\"\n    expect_stdout: \"number string\"\n    node_version: \">=10.4.0\"\n}\n\nevaluate: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log((0xDEAD_BEEFn).toString(16));\n    }\n    expect: {\n        console.log(0xdeadbeefn.toString(16));\n    }\n    expect_stdout: \"deadbeef\"\n    node_version: \">=10.4.0\"\n}\n\nNumber: {\n    options = {\n        unsafe: true,\n    }\n    input: {\n        console.log(Number(-0xfeed_dead_beef_badn));\n    }\n    expect: {\n        console.log(+(\"\" + -0xfeed_dead_beef_badn));\n    }\n    expect_stdout: \"-1148098955808013200\"\n    node_version: \">=10.4.0\"\n}\n\nissue_4590: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        A = 1;\n        0n || console.log(\"PASS\");\n    }\n    expect: {\n        A = 1;\n        0n || console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10.4.0\"\n}\n\nissue_4801: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        try {\n            (function(a) {\n                A = 42;\n                a || A;\n            })(!(0 == 42 >> 0o644n));\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function(a) {\n                0 != (A = 42) >> 0o644n || A;\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10.4.0\"\n}\n\nissue_5728: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\"\" + 4n + 2);\n    }\n    expect: {\n        console.log(\"42\");\n    }\n    expect_stdout: \"42\"\n    node_version: \">=10.4.0\"\n}\n"
  },
  {
    "path": "test/compress/blocks.js",
    "content": "remove_blocks: {\n    input: {\n        {;}\n        foo();\n        {};\n        {\n            {};\n        };\n        bar();\n        {}\n    }\n    expect: {\n        foo();\n        bar();\n    }\n}\n\nkeep_some_blocks: {\n    input: {\n        // 1.\n        if (foo) {\n            {{{}}}\n            if (bar) { baz(); }\n            {{}}\n        } else {\n            stuff();\n        }\n\n        // 2.\n        if (foo) {\n            for (var i = 0; i < 5; ++i)\n                if (bar) baz();\n        } else {\n            stuff();\n        }\n    }\n    expect: {\n        // 1.\n        if (foo) {\n            if (bar) baz();\n        } else stuff();\n\n        // 2.\n        if (foo) {\n            for (var i = 0; i < 5; ++i)\n                if (bar) baz();\n        } else stuff();\n    }\n}\n\nissue_1666: {\n    input: {\n        var a = 42;\n        {\n            function a() {}\n            a();\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        var a = 42;\n        {\n            function a() {}\n            a();\n        }\n        console.log(\"PASS\");\n    }\n    expect_stdout: true\n}\n\nissue_1666_strict: {\n    input: {\n        \"use strict\";\n        var a = 42;\n        {\n            function a() {}\n            a();\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        var a = 42;\n        {\n            function a() {}\n            a();\n        }\n        console.log(\"PASS\");\n    }\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/booleans.js",
    "content": "iife_boolean_context: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        console.log(function() {\n            return Object(1) || false;\n        }() ? \"PASS\" : \"FAIL\");\n        console.log(function() {\n            return [].length || true;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function() {\n            return Object(1);\n        }() ? \"PASS\" : \"FAIL\");\n        console.log(function() {\n            return [].length, 1;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n    expect_warnings: [\n        \"WARN: Dropping side-effect-free || [test/compress/booleans.js:2,19]\",\n        \"WARN: Boolean || always true [test/compress/booleans.js:5,19]\",\n    ]\n}\n\nde_morgan_1a: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        function f(a) {\n            return a || a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect: {\n        function f(a) {\n            return a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect_stdout: \"null 42\"\n}\n\nde_morgan_1b: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        function f(a) {\n            return a && a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect: {\n        function f(a) {\n            return a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect_stdout: \"null 42\"\n}\n\nde_morgan_1c: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        console.log(delete (NaN && NaN));\n    }\n    expect: {\n        console.log(delete (0, NaN));\n    }\n    expect_stdout: \"true\"\n}\n\nde_morgan_1d: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        function f(a) {\n            return (a = false) || a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect: {\n        function f(a) {\n            return a = !1;\n        }\n        console.log(f(null), f(42));\n    }\n    expect_stdout: \"false false\"\n}\n\nde_morgan_1e: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        function f(a) {\n            return a.p || a.p;\n        }\n        console.log(f({ p: null }), f({ p: 42 }));\n    }\n    expect: {\n        function f(a) {\n            return a.p;\n        }\n        console.log(f({ p: null }), f({ p: 42 }));\n    }\n    expect_stdout: \"null 42\"\n}\n\nde_morgan_1f: {\n    options = {\n        booleans: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a, b) {\n            return a.p + b.q;\n        }\n        console.log(f({ p: null }, { q: false }) || f({ p: null }, { q: false }));\n        console.log(f({ p: \"foo\" }, { q: 42 }) && f({ p: \"foo\" }, { q: 42 }));\n    }\n    expect: {\n        function f(a, b) {\n            return a.p + b.q;\n        }\n        console.log(f({ p: null }, { q: !1 }));\n        console.log(f({ p: \"foo\" }, { q: 42 }));\n    }\n    expect_stdout: [\n        \"0\",\n        \"foo42\",\n    ]\n}\n\nde_morgan_2a: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        function f(a, b) {\n            return a || (a || b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a || b;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"undefined {}\",\n        \"42 42\",\n    ]\n}\n\nde_morgan_2b: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b) {\n            return a || (a && b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"null null\",\n        \"42 42\",\n    ]\n}\n\nde_morgan_2c: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b) {\n            return a && (a || b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"null null\",\n        \"42 42\",\n    ]\n}\n\nde_morgan_2d: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            return a && (a && b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a && b;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"null null\",\n        \"undefined {}\",\n    ]\n}\n\nde_morgan_2e: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        function f(a, b) {\n            return (a && b) && b;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a && b;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"null null\",\n        \"undefined {}\",\n    ]\n}\n\nde_morgan_3a: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a || ((a || b) || c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a || b || c;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"undefined {} true true\",\n        \"42 42 42 42\",\n    ]\n}\n\nde_morgan_3b: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a || ((a || b) && c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a || b && c;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"false false undefined {}\",\n        \"42 42 42 42\",\n    ]\n}\n\nde_morgan_3c: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a || ((a && b) || c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a || c;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"undefined {} undefined {}\",\n        \"42 42 42 42\",\n    ]\n}\n\nde_morgan_3d: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a || ((a && b) && c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"null null null null\",\n        \"42 42 42 42\",\n    ]\n}\n\nde_morgan_3e: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a && ((a || b) || c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"null null null null\",\n        \"42 42 42 42\",\n    ]\n}\n\nde_morgan_3f: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a && ((a || b) && c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a && c;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"null null null null\",\n        \"undefined {} undefined {}\",\n    ]\n}\n\nde_morgan_3g: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a && ((a && b) || c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a && (b || c);\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"null null null null\",\n        \"undefined {} true true\",\n    ]\n}\n\nde_morgan_3h: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        function f(a, b, c) {\n            return a && ((a && b) && c);\n        }\n        console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));\n        console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));\n    }\n    expect: {\n        function f(a, b, c) {\n            return a && b && c;\n        }\n        console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));\n        console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));\n    }\n    expect_stdout: [\n        \"null null null null\",\n        \"false false undefined {}\",\n    ]\n}\n\nconditional_chain: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b) {\n            return a ? a : b ? b : 42;\n        }\n        console.log(f(\"PASS\", \"FAIL\"));\n    }\n    expect: {\n        function f(a, b) {\n            return a || b || 42;\n        }\n        console.log(f(\"PASS\", \"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nnegated_if: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a) {\n            if (!a)\n                return a ? \"FAIL\" : \"PASS\";\n        }(!console));\n    }\n    expect: {\n        console.log(function(a) {\n            if (!a)\n                return \"PASS\";\n        }(!console));\n    }\n    expect_stdout: \"PASS\"\n}\n\nconcat_truthy: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        console.log(\"foo\") + (console.log(\"bar\"), \"baz\") || console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\") + (console.log(\"bar\"), \"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    expect_warnings: [\n        \"WARN: + in boolean context always true [test/compress/booleans.js:1,8]\",\n        \"WARN: Condition left of || always true [test/compress/booleans.js:1,8]\",\n    ]\n}\n\nprocess_returns: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        (function() {\n            return 42;\n        })() && console.log(\"PASS\");\n    }\n    expect: {\n        (function() {\n            return 42;\n        })() && console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3465_1: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        console.log(function(a) {\n            return typeof a;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function(a) {\n            return 1;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3465_2: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        console.log(function f(a) {\n            if (!a) console.log(f(42));\n            return typeof a;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function f(a) {\n            if (!a) console.log(f(42));\n            return typeof a;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: [\n        \"number\",\n        \"PASS\",\n    ]\n}\n\nissue_3465_3: {\n    options = {\n        booleans: true,\n        passes: 2,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            return typeof a;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function(a) {\n            return 1;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2737_2: {\n    options = {\n        booleans: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(bar) {\n            for (;bar();) break;\n        })(function qux() {\n            return console.log(\"PASS\"), qux;\n        });\n    }\n    expect: {\n        (function(bar) {\n            for (;bar();) break;\n        })(function() {\n            return console.log(\"PASS\"), 1;\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3658: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function f() {\n            console || f();\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            console || f();\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3690: {\n    options = {\n        booleans: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            return function() {\n                return a = [ this ];\n            }() ? \"PASS\" : \"FAIL\";\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            return function() {\n                return 1;\n            }() ? \"PASS\" : \"FAIL\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4374: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            console.log(f());\n            function f(a) {\n                if (null) return 0;\n                if (a) return 1;\n                return 0;\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(function(a) {\n                return !null && a ? 1 : 0;\n            }());\n        })();\n    }\n    expect_stdout: \"0\"\n}\n\nissue_5028_1: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        var a = 1;\n        console.log(function() {\n            return a-- ? a-- ? \"FAIL 1\" : \"PASS\" : \"FAIL 2\";\n        }());\n    }\n    expect: {\n        var a = 1;\n        console.log(function() {\n            return a-- ? a-- ? \"FAIL 1\" : \"PASS\" : \"FAIL 2\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5028_2: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        var a = 1;\n        (function() {\n            if (a--)\n                if (a--)\n                    a = \"FAIL\";\n                else\n                    return;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        (function() {\n            a-- && a-- && (a = \"FAIL\");\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"-1\"\n}\n\nissue_5028_3: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        if_return: true,\n    }\n    input: {\n        var a = 1;\n        (function() {\n            if (a--)\n                if (a--)\n                    a = \"FAIL\";\n                else\n                    return;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        (function() {\n            a-- && a-- && (a = \"FAIL\");\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"-1\"\n}\n\nissue_5041_1: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        var a = 42;\n        if (a)\n            if ([ a = null ])\n                if (a)\n                    console.log(\"FAIL\");\n                else\n                    console.log(\"PASS\");\n    }\n    expect: {\n        var a = 42;\n        a && [ a = null ] && (a ? console.log(\"FAIL\") : console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5041_2: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        var a;\n        if (!a)\n            if (a = 42)\n                if (a)\n                    console.log(\"PASS\");\n                else\n                    console.log(\"FAIL\");\n    }\n    expect: {\n        var a;\n        a || (a = 42) && (a ? console.log(\"PASS\") : console.log(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5228: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n    }\n    input: {\n        console.log(function() {\n            return !function() {\n                do {\n                    return null;\n                } while (console);\n            }();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            do {\n                return !0;\n            } while (console);\n            return !0;\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_5469: {\n    options = {\n        assignments: true,\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        console.log(function f(a) {\n            a && 42[a = A && null];\n        }());\n    }\n    expect: {\n        console.log(function f(a) {\n            a && A,\n            0;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5694_1: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        var Infinity;\n        // Node.js v0.12~6 (vm): 42\n        console.log((Infinity = 42) && Infinity);\n    }\n    expect: {\n        var Infinity;\n        console.log((Infinity = 42) && Infinity);\n    }\n    expect_stdout: true\n}\n\nissue_5694_2: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        var undefined;\n        // Node.js v0.12~6 (vm): NaN\n        console.log((\"foo\", ++undefined) || undefined);\n    }\n    expect: {\n        var undefined;\n        console.log((\"foo\", ++undefined) || undefined);\n    }\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/classes.js",
    "content": "constructor_1: {\n    input: {\n        \"use strict\";\n        console.log(new class {\n            constructor(a) {\n                this.a = a;\n            }\n        }(\"PASS\").a);\n    }\n    expect_exact: '\"use strict\";console.log(new class{constructor(a){this.a=a}}(\"PASS\").a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nconstructor_2: {\n    input: {\n        \"use strict\";\n        console.log(new class {\n            \"constructor\"(a) {\n                this.a = a;\n            }\n        }(\"PASS\").a);\n    }\n    expect_exact: '\"use strict\";console.log(new class{constructor(a){this.a=a}}(\"PASS\").a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nconstructor_3: {\n    input: {\n        \"use strict\";\n        console.log(new class {\n            [\"constructor\"](a) {\n                this.a = a;\n            }\n        }(\"FAIL\").a || \"PASS\");\n    }\n    expect_exact: '\"use strict\";console.log(new class{[\"constructor\"](a){this.a=a}}(\"FAIL\").a||\"PASS\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nconstructor_4: {\n    input: {\n        \"use strict\";\n        class A {\n            static constructor(a) {\n                console.log(a);\n            }\n        }\n        A.constructor(\"PASS\");\n    }\n    expect_exact: '\"use strict\";class A{static constructor(a){console.log(a)}}A.constructor(\"PASS\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nfields: {\n    input: {\n        var o = new class A {\n            \"#p\";\n            static #p = \"PASS\";\n            async\n            get\n            q() {\n                return A.#p;\n            }\n            ;\n            [6 * 7] = console ? \"foo\" : \"bar\"\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n        console.log(o.q);\n    }\n    expect_exact: 'var o=new class A{\"#p\";static#p=\"PASS\";async;get q(){return A.#p}[6*7]=console?\"foo\":\"bar\"};for(var k in o)console.log(k,o[k]);console.log(o.q);'\n    expect_stdout: [\n        \"42 foo\",\n        \"#p undefined\",\n        \"async undefined\",\n        \"PASS\",\n    ]\n    node_version: \">=12\"\n}\n\nmodifier_as_field_name: {\n    input: {\n        for (var k in new class { async; static = 42 })\n            console.log(k);\n    }\n    expect_exact: \"for(var k in new class{async;static=42})console.log(k);\"\n    expect_stdout: [\n        \"async\",\n        \"static\",\n    ]\n    node_version: \">=12\"\n}\n\nmethods: {\n    input: {\n        \"use strict\";\n        class A {\n            static f() {\n                return \"foo\";\n            }\n            *g() {\n                yield A.f();\n                yield \"bar\";\n            }\n        }\n        for (var a of new A().g())\n            console.log(a);\n    }\n    expect_exact: '\"use strict\";class A{static f(){return\"foo\"}*g(){yield A.f();yield\"bar\"}}for(var a of(new A).g())console.log(a);'\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nprivate_methods: {\n    input: {\n        new class A {\n            static *#f() {\n                yield A.#p * 3;\n            }\n            async #g() {\n                for (var a of A.#f())\n                    return a * await 2;\n            }\n            static get #p() {\n                return 7;\n            }\n            get q() {\n                return this.#g();\n            }\n        }().q.then(console.log);\n    }\n    expect_exact: \"(new class A{static*#f(){yield 3*A.#p}async#g(){for(var a of A.#f())return a*await 2}static get#p(){return 7}get q(){return this.#g()}}).q.then(console.log);\"\n    expect_stdout: \"42\"\n    node_version: \">=14.6\"\n}\n\nawait: {\n    input: {\n        var await = \"PASS\";\n        (async function() {\n            return await new class extends (await function() {}) { [await 42] = await };\n        })().then(function(o) {\n            console.log(o[42]);\n        });\n    }\n    expect_exact: 'var await=\"PASS\";(async function(){return await new class extends(await function(){}){[await 42]=await}})().then(function(o){console.log(o[42])});'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nyield: {\n    input: {\n        var a = function*() {\n            yield new class { [yield \"foo\"] = \"bar\" };\n        }();\n        console.log(a.next().value);\n        console.log(a.next(42).value[42]);\n    }\n    expect_exact: 'var a=function*(){yield new class{[yield\"foo\"]=\"bar\"}}();console.log(a.next().value);console.log(a.next(42).value[42]);'\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=12\"\n}\n\nconditional_parentheses: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        \"use strict\";\n        if (class {})\n            console.log(\"PASS\");\n    }\n    expect_exact: '\"use strict\";(class{})&&console.log(\"PASS\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nclass_super: {\n    input: {\n        \"use strict\";\n        class A {\n            static get p() {\n                return \"Foo\";\n            }\n            static get q() {\n                return super.p || 42;\n            }\n            constructor() {\n                console.log(\"a.p\", super.p, this.p);\n                console.log(\"a.q\", super.q, this.q);\n            }\n            get p() {\n                return \"foo\";\n            }\n            get q() {\n                return super.p || null;\n            }\n        }\n        class B extends A {\n            static get p() {\n                return \"Bar\";\n            }\n            static get q() {\n                return super.p;\n            }\n            constructor() {\n                super();\n                console.log(\"b.p\", super.p, this.p);\n                console.log(\"b.q\", super.q, this.q);\n            }\n            get p() {\n                return \"bar\";\n            }\n            get q() {\n                return super.p;\n            }\n        }\n        console.log(\"A\", A.p, A.q);\n        console.log(\"B\", B.p, B.q);\n        new B();\n    }\n    expect_exact: '\"use strict\";class A{static get p(){return\"Foo\"}static get q(){return super.p||42}constructor(){console.log(\"a.p\",super.p,this.p);console.log(\"a.q\",super.q,this.q)}get p(){return\"foo\"}get q(){return super.p||null}}class B extends A{static get p(){return\"Bar\"}static get q(){return super.p}constructor(){super();console.log(\"b.p\",super.p,this.p);console.log(\"b.q\",super.q,this.q)}get p(){return\"bar\"}get q(){return super.p}}console.log(\"A\",A.p,A.q);console.log(\"B\",B.p,B.q);new B;'\n    expect_stdout: [\n        \"A Foo 42\",\n        \"B Bar Foo\",\n        \"a.p undefined bar\",\n        \"a.q undefined foo\",\n        \"b.p foo bar\",\n        \"b.q null foo\",\n    ]\n    node_version: \">=4\"\n}\n\nstatic_newline_1: {\n    input: {\n        class A {\n            static\n            P\n        }\n        console.log(\"P\" in A, \"static\" in A);\n        console.log(\"P\" in new A(), \"static\" in new A());\n    }\n    expect_exact: 'class A{static P}console.log(\"P\"in A,\"static\"in A);console.log(\"P\"in new A,\"static\"in new A);'\n    expect_stdout: [\n        \"true false\",\n        \"false false\",\n    ]\n    node_version: \">=12\"\n}\n\nstatic_newline_2: {\n    input: {\n        class A {\n            static\n            static\n            P\n        }\n        console.log(\"P\" in A, \"static\" in A);\n        console.log(\"P\" in new A(), \"static\" in new A());\n    }\n    expect_exact: 'class A{static static;P}console.log(\"P\"in A,\"static\"in A);console.log(\"P\"in new A,\"static\"in new A);'\n    expect_stdout: [\n        \"false true\",\n        \"true false\",\n    ]\n    node_version: \">=12\"\n}\n\nstatic_newline_3: {\n    input: {\n        class A {\n            static\n            static\n            static\n            P\n        }\n        console.log(\"P\" in A, \"static\" in A);\n        console.log(\"P\" in new A(), \"static\" in new A());\n    }\n    expect_exact: 'class A{static static;static P}console.log(\"P\"in A,\"static\"in A);console.log(\"P\"in new A,\"static\"in new A);'\n    expect_stdout: [\n        \"true true\",\n        \"false false\",\n    ]\n    node_version: \">=12\"\n}\n\nstatic_newline_4: {\n    input: {\n        class A {\n            static\n            static\n            static\n            static\n            P\n        }\n        console.log(\"P\" in A, \"static\" in A);\n        console.log(\"P\" in new A(), \"static\" in new A());\n    }\n    expect_exact: 'class A{static static;static static;P}console.log(\"P\"in A,\"static\"in A);console.log(\"P\"in new A,\"static\"in new A);'\n    expect_stdout: [\n        \"false true\",\n        \"true false\",\n    ]\n    node_version: \">=12\"\n}\n\nstatic_newline_init: {\n    input: {\n        class A {\n            static\n            {\n                console.log(\"PASS\");\n            }\n        }\n    }\n    expect_exact: 'class A{static{console.log(\"PASS\")}}'\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nstatic_init: {\n    input: {\n        var a = \"foo\";\n        var b = null;\n        class A {\n            static {\n                var a = \"bar\";\n                b = true;\n                var c = 42;\n                console.log(a, b, c);\n            }\n        }\n        console.log(a, b, typeof c);\n    }\n    expect_exact: 'var a=\"foo\";var b=null;class A{static{var a=\"bar\";b=true;var c=42;console.log(a,b,c)}}console.log(a,b,typeof c);'\n    expect_stdout: [\n        \"bar true 42\",\n        \"foo true undefined\",\n    ]\n    node_version: \">=16\"\n}\n\nstatic_field_init: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (class {\n            static [console.log(\"foo\")] = console.log(\"bar\");\n            static {\n                console.log(\"baz\");\n            }\n            static [console.log(\"moo\")] = console.log(\"moz\");\n        });\n    }\n    expect: {\n        (class {\n            static [(console.log(\"foo\"), console.log(\"moo\"))] = (\n                console.log(\"bar\"),\n                (() => {\n                    console.log(\"baz\");\n                })(),\n                console.log(\"moz\")\n            );\n        });\n    }\n    expect_stdout: [\n        \"foo\",\n        \"moo\",\n        \"bar\",\n        \"baz\",\n        \"moz\",\n    ]\n    node_version: \">=16\"\n}\n\nstatic_field_init_strict: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (class {\n            static [console.log(\"foo\")] = console.log(\"bar\");\n            static {\n                console.log(\"baz\");\n            }\n            static [console.log(\"moo\")] = console.log(\"moz\");\n        });\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"foo\"),\n        console.log(\"moo\"),\n        (() => (\n            console.log(\"bar\"),\n            (() => {\n                console.log(\"baz\");\n            })(),\n            console.log(\"moz\")\n        ))();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"moo\",\n        \"bar\",\n        \"baz\",\n        \"moz\",\n    ]\n    node_version: \">=16\"\n}\n\nstatic_init_side_effects_1: {\n    options = {\n        merge_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (class {\n            static {\n                a = \"PASS\";\n            }\n        });\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (class {\n            static {\n                a = \"PASS\";\n            }\n        });\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nstatic_init_side_effects_1_strict: {\n    options = {\n        merge_vars: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL\";\n        (class {\n            static {\n                a = \"PASS\";\n            }\n        });\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL\";\n        (() => (() => {\n            a = \"PASS\";\n        })())();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nstatic_init_side_effects_2: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (class {\n            static {\n                a = \"PASS\";\n            }\n        });\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (class {\n            static {\n                a = \"PASS\";\n            }\n        });\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nstatic_init_side_effects_2_strict: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL\";\n        (class {\n            static {\n                a = \"PASS\";\n            }\n        });\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL\";\n        (() => (() => {\n            a = \"PASS\";\n        })())();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nblock_scoped: {\n    options = {\n        evaluate: true,\n        dead_code: true,\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        while (0) {\n            class A {}\n        }\n        if (console) {\n            class B {}\n        }\n        console.log(typeof A, typeof B);\n    }\n    expect: {\n        \"use strict\";\n        0;\n        {\n            class A {}\n        }\n        if (console) {\n            class B {}\n        }\n        console.log(typeof A, typeof B);\n    }\n    expect_stdout: \"undefined undefined\"\n    node_version: \">=4\"\n}\n\nretain_declaration: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL\";\n        try {\n            console.log(function() {\n                return a;\n                class a {}\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL\";\n        try {\n            console.log(function() {\n                return a;\n                class a {}\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndrop_extends: {\n    options = {\n        inline: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var f = () => {};\n                class A extends f {\n                    get p() {}\n                }\n                A.q = 42;\n                return class B extends A {};\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (class extends (() => {}) {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_extends_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            class A extends 42 {}\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (class extends 42 {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_extends_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (class extends Function {});\n        console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        (class extends Function {});\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_extends_3: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A extends Function {}\n        console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        (class extends Function {});\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndrop_name: {\n    options = {\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            console.log(class A extends 42 {})\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            console.log(class extends 42 {})\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nseparate_name: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            constructor(v) {\n                this.p = v;\n            }\n        }\n        var a = new A(\"PASS\");\n        console.log(a.p);\n    }\n    expect: {\n        \"use strict\";\n        class A {\n            constructor(v) {\n                this.p = v;\n            }\n        }\n        var a = new A(\"PASS\");\n        console.log(a.p);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nstatic_getter: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (class {\n            static get p() {\n                console.log(\"PASS\");\n            };\n        }).p;\n    }\n    expect: {\n        \"use strict\";\n        (class {\n            static get p() {\n                console.log(\"PASS\");\n            };\n        }).p;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nstatic_setter: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (class {\n            static set p(v) {\n                console.log(v);\n            };\n        }).p = \"PASS\";\n    }\n    expect: {\n        \"use strict\";\n        (class {\n            static set p(v) {\n                console.log(v);\n            };\n        }).p = \"PASS\";\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nstatic_side_effects: {\n    options = {\n        inline: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL 1\";\n        class A {\n            static p = a = \"PASS\";\n            q = a = \"FAIL 2\";\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL 1\";\n        (class {\n            static c = a = \"PASS\";\n        });\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nstatic_side_effects_strict: {\n    options = {\n        inline: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL 1\";\n        class A {\n            static p = a = \"PASS\";\n            q = a = \"FAIL 2\";\n        }\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL 1\";\n        a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nsingle_use_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        console.log(typeof new A());\n    }\n    expect: {\n        \"use strict\";\n        console.log(typeof new class {}());\n    }\n    expect_stdout: \"object\"\n    node_version: \">=4\"\n}\n\nsingle_use_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            f(a) {\n                console.log(a);\n            }\n        }\n        new A().f(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        new class {\n            f(a) {\n                console.log(a);\n            }\n        }().f(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nsingle_use_3: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            f() {\n                return A;\n            }\n        }\n        console.log(typeof new A().f());\n    }\n    expect: {\n        \"use strict\";\n        console.log(typeof new class A {\n            f() {\n                return A;\n            }\n        }().f());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nsingle_use_4: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(new class A {\n            f() {\n                return typeof A;\n            }\n        }().f());\n    }\n    expect: {\n        \"use strict\";\n        console.log(new class A {\n            f() {\n                return typeof A;\n            }\n        }().f());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nsingle_use_5: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(\"foo\");\n        }\n        (function() {\n            \"use strict\";\n            class A extends f {\n                f() {\n                    console.log(\"bar\");\n                }\n            }\n            console.log(\"baz\");\n            new A().f();\n        })();\n    }\n    expect: {\n        function f() {\n            console.log(\"foo\");\n        }\n        (function() {\n            \"use strict\";\n            class A extends f {\n                f() {\n                    console.log(\"bar\");\n                }\n            }\n            console.log(\"baz\");\n            new A().f();\n        })();\n    }\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nsingle_use_6: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            [(console.log(\"foo\"), \"f\")]() {\n                console.log(\"bar\");\n            }\n        }\n        console.log(\"baz\");\n        new A().f();\n    }\n    expect: {\n        \"use strict\";\n        class A {\n            [(console.log(\"foo\"), \"f\")]() {\n                console.log(\"bar\");\n            }\n        }\n        console.log(\"baz\");\n        new A().f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nsingle_use_7: {\n    options = {\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            static foo() {}\n        }\n        var a = \"foo\" in A;\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"foo\" in class {\n            static foo() {}\n        });\n    }\n    expect_stdout: \"true\"\n    node_version: \">=4\"\n}\n\nsingle_use_extends: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A extends class B {\n            f() {\n                return \"PASS\";\n            }\n        } {}\n        console.log(new A().f());\n    }\n    expect: {\n        \"use strict\";\n        console.log(new class extends class {\n            f() {\n                return \"PASS\";\n            }\n        } {}().f());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nsingle_use_extends_non_strict: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        class A extends class B {\n            f() {\n                return \"PASS\";\n            }\n        } {}\n        console.log(new A().f());\n    }\n    expect: {\n        console.log(new class extends class {\n            f() {\n                return \"PASS\";\n            }\n        } {}().f());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_non_strict: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 42..p++;\n        new class extends (a || function() {\n            console.log(\"PASS\");\n        }) {}\n    }\n    expect: {\n        var a = 42..p++;\n        new class extends (a || function() {\n            console.log(\"PASS\");\n        }) {}\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_rhs: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL\";\n        a = \"PASS\";\n        class A {\n            p = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL\";\n        class A {\n            p = \"PASS\";\n        }\n        console.log(a = \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\ncollapse_rhs_static: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL\";\n        a = \"PASS\";\n        class A {\n            static p = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL\";\n        class A {\n            static p = \"PASS\";\n        }\n        console.log(a = \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\ninline_non_strict: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            return a.p = \"PASS\";\n        }\n        class A {\n            g() {\n                return f(42);\n            }\n        }\n        console.log(new A().g());\n    }\n    expect: {\n        function f(a) {\n            return a.p = \"PASS\";\n        }\n        console.log(new class {\n            g() {\n                return f(42);\n            }\n        }().g());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nself_comparison: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        console.log(A == A, A != A);\n        console.log(A === A, A !== A);\n    }\n    expect: {\n        \"use strict\";\n        console.log(!0, !1);\n        console.log(!0, !1);\n    }\n    expect_stdout: [\n        \"true false\",\n        \"true false\",\n    ]\n    node_version: \">=4\"\n}\n\nproperty_side_effects: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function f(a, b) {\n            class A {\n                [a.log(\"PASS\")]() {\n                    b.log(\"FAIL\");\n                }\n            }\n        })(console, console);\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            a.log(\"PASS\");\n        })(console, console);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nproperty_side_effects_static: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function f(a, b) {\n            class A {\n                static [a.log(\"PASS\")]() {\n                    b.log(\"FAIL\");\n                }\n            }\n        })(console, console);\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            a.log(\"PASS\");\n        })(console, console);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nunused_await: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        var await = \"PASS\";\n        (async function() {\n            class A {\n                static p = console.log(await);\n            }\n        })();\n    }\n    expect: {\n        var await = \"PASS\";\n        (async function() {\n            (class {\n                static c = console.log(await);\n            });\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=12 <16\"\n}\n\nunused_await_strict: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var await = \"PASS\";\n        (async function() {\n            class A {\n                static p = console.log(await);\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        var await = \"PASS\";\n        (async function() {\n            (() => console.log(await))();\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=12 <16\"\n}\n\ncomputed_key_side_effects: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 0;\n        class A {\n            [(a++, 0)]() {}\n        }\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n    node_version: \">=4\"\n}\n\ncomputed_key_generator: {\n    options = {\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a = function*() {\n            class A {\n                static [console.log(yield)]() {}\n            }\n        }();\n        a.next(\"FAIL\");\n        a.next(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        var a = function*() {\n            console.log(yield);\n        }();\n        a.next(\"FAIL\");\n        a.next(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_fnames: {\n    options = {\n        keep_fnames: true,\n        toplevel: true,\n    }\n    mangle = {\n        keep_fnames: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        class Foo {}\n        console.log(Foo.name, class Bar {}.name);\n    }\n    expect: {\n        \"use strict\";\n        class Foo {}\n        console.log(Foo.name, class Bar {}.name);\n    }\n    expect_stdout: \"Foo Bar\"\n    node_version: \">=4\"\n}\n\ninstanceof_lambda: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(42 instanceof class {});\n    }\n    expect: {\n        \"use strict\";\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n    node_version: \">=4\"\n}\n\ndrop_instanceof: {\n    options = {\n        booleans: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect: {\n        \"use strict\";\n        console.log(!1, (Math, !1));\n    }\n    expect_stdout: \"false false\"\n    node_version: \">=4\"\n}\n\nkeep_instanceof_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        var A;\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect: {\n        \"use strict\";\n        class A {}\n        var A;\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect_stdout: SyntaxError(\"Identifier has already been declared\")\n    node_version: \">=4\"\n}\n\nkeep_instanceof_2: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var A = Object;\n        class A {}\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect: {\n        \"use strict\";\n        var A = Object;\n        class A {}\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect_stdout: SyntaxError(\"Identifier has already been declared\")\n    node_version: \">=4\"\n}\n\nkeep_instanceof_3: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        A = Object;\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect: {\n        \"use strict\";\n        class A {}\n        A = Object;\n        console.log({} instanceof A, Math instanceof A);\n    }\n    expect_stdout: \"true true\"\n    node_version: \">=4\"\n}\n\nkeep_field_reference_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {}\n        class A {\n            p = f;\n        }\n        console.log(new A().p === new A().p ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        function f() {}\n        class A {\n            p = f;\n        }\n        console.log(new A().p === new A().p ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_field_reference_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {}\n        var A = class {\n            p = f;\n        };\n        console.log(new A().p === new A().p ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        function f() {}\n        var A = class {\n            p = f;\n        };\n        console.log(new A().p === new A().p ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_field_reference_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        class B {\n            p = A;\n        }\n        console.log(new B().p === new B().p ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        class A {}\n        class B {\n            p = A;\n        }\n        console.log(new B().p === new B().p ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_field_reference_4: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var A = class {};\n        var B = class {\n            p = A;\n        };\n        console.log(new B().p === new B().p ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        var A = class {};\n        var B = class {\n            p = A;\n        };\n        console.log(new B().p === new B().p ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_static_field_reference_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {}\n        class A {\n            static P = f;\n        }\n        console.log(A.P === A.P ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        class A {\n            static P = function() {};\n        }\n        console.log(A.P === A.P ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_static_field_reference_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {}\n        var A = class {\n            static P = f;\n        };\n        console.log(A.P === A.P ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        var A = class {\n            static P = function() {};\n        };\n        console.log(A.P === A.P ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_static_field_reference_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        class B {\n            static P = A;\n        }\n        console.log(B.P === B.P ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        class B {\n            static P = class {};\n        }\n        console.log(B.P === B.P ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nkeep_static_field_reference_4: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var A = class {};\n        var B = class {\n            static P = A;\n        };\n        console.log(B.P === B.P ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        var B = class {\n            static P = class {};\n        };\n        console.log(B.P === B.P ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_805_1: {\n    options = {\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            var unused = class {};\n            unused.prototype[a()] = 42;\n            (unused.prototype.bar = function() {\n                console.log(\"bar\");\n            })();\n            return unused;\n        })(function() {\n            console.log(\"foo\");\n            return \"foo\";\n        });\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"foo\"),\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_805_2: {\n    options = {\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            class unused {}\n            unused.prototype[a()] = 42;\n            (unused.prototype.bar = function() {\n                console.log(\"bar\");\n            })();\n            return unused;\n        })(function() {\n            console.log(\"foo\");\n            return \"foo\";\n        });\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"foo\"),\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4681: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            class A {\n                static p = a = this;\n            }\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            (class {\n                static p = a = this;\n            });\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_4683: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        for (class extends null {}; void console.log(\"PASS\"); );\n    }\n    expect: {\n        \"use strict\";\n        (class extends null {});\n        void console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4685_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        new class {\n            f() {\n                (function(g) {\n                    if (g() !== this)\n                        console.log(\"PASS\");\n                })(() => this);\n            }\n        }().f();\n    }\n    expect: {\n        \"use strict\";\n        new class {\n            f() {\n                (function(g) {\n                    if (g() !== this)\n                        console.log(\"PASS\");\n                })(() => this);\n            }\n        }().f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4685_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        new class {\n            f() {\n                (function(g) {\n                    if (g() !== this)\n                        console.log(\"PASS\");\n                })(() => {\n                    if (console)\n                        return this;\n                });\n            }\n        }().f();\n    }\n    expect: {\n        \"use strict\";\n        new class {\n            f() {\n                (function(g) {\n                    if (g() !== this)\n                        console.log(\"PASS\");\n                })(() => {\n                    if (console)\n                        return this;\n                });\n            }\n        }().f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4687_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        new class {\n            f() {\n                console.log(function(g) {\n                    return g() === this;\n                }(() => this) || \"PASS\");\n            }\n        }().f();\n    }\n    expect: {\n        \"use strict\";\n        new class {\n            f() {\n                console.log(function(g) {\n                    return g() === this;\n                }(() => this) || \"PASS\");\n            }\n        }().f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4687_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        new class {\n            f() {\n                console.log(function(g) {\n                    return g() === this;\n                }(() => {\n                    if (console)\n                        return this;\n                }) || \"PASS\");\n            }\n        }().f();\n    }\n    expect: {\n        \"use strict\";\n        new class {\n            f() {\n                console.log(function(g) {\n                    return g() === this;\n                }(() => {\n                    if (console)\n                        return this;\n                }) || \"PASS\");\n            }\n        }().f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4705: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        class A {\n            p = a = \"FAIL\";\n            [console.log(a)];\n        }\n    }\n    expect: {\n        (class {\n            [console.log(\"PASS\")]() {}\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_4705_strict: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"PASS\";\n        class A {\n            p = a = \"FAIL\";\n            [console.log(a)];\n        }\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_4720: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        class A {\n            static p = function f() {};\n        }\n        console.log(typeof A.p, typeof f);\n    }\n    expect: {\n        class A {\n            static p = function f() {};\n        }\n        console.log(typeof A.p, typeof f);\n    }\n    expect_stdout: \"function undefined\"\n    node_version: \">=12\"\n}\n\nissue_4721: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"foo\";\n        try {\n            (class extends 42 {\n                [a = \"bar\"]() {}\n            })\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = \"foo\";\n        try {\n            (class extends 42 {\n                [a = \"bar\"]() {}\n            });\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_4722_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (class extends function*() {} {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (class extends function*() {} {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4722_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (class extends async function() {} {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (class extends async function() {} {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4722_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (class extends async function*() {} {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (class extends async function*() {} {});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_4725_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(typeof new class {\n            f() {\n                return function g() {\n                    return g;\n                }();\n            }\n        }().f());\n    }\n    expect: {\n        \"use strict\";\n        console.log(typeof new class {\n            f() {\n                return function g() {\n                    return g;\n                }();\n            }\n        }().f());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_4725_2: {\n    options = {\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        \"use strict\";\n        new class {\n            f() {\n                return function() {\n                    while (console.log(\"PASS\"));\n                }();\n            }\n        }().f();\n    }\n    expect: {\n        \"use strict\";\n        new class {\n            f() {\n                while (console.log(\"PASS\"));\n            }\n        }().f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nnew_target: {\n    input: {\n        console.log(typeof new class {\n            constructor() {\n                this.f = () => new.target;\n            }\n        }().f());\n    }\n    expect: {\n        console.log(typeof new class {\n            constructor() {\n                this.f = () => new.target;\n            }\n        }().f());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_4756: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            class A extends 42 {\n                static [console.log(\"foo\")] = console.log(\"bar\");\n            }\n        } catch (e) {\n            console.log(\"baz\");\n        }\n    }\n    expect: {\n        try {\n            (class extends 42 {\n                static [console.log(\"foo\")] = console.log(\"bar\");\n            });\n        } catch (e) {\n            console.log(\"baz\");\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n    ]\n    node_version: \">=12\"\n}\n\nissue_4756_strict: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            class A extends 42 {\n                static [console.log(\"foo\")] = console.log(\"bar\");\n            }\n        } catch (e) {\n            console.log(\"baz\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (class extends 42 {\n                static [console.log(\"foo\")] = console.log(\"bar\");\n            });\n        } catch (e) {\n            console.log(\"baz\");\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n    ]\n    node_version: \">=12\"\n}\n\nissue_4821_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        class A {\n            static p = void (a = this);\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        var a;\n        (class {\n            static p = void (a = this);\n        });\n        console.log(typeof a);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_4821_2: {\n    options = {\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        class A {\n            static p = void (a = this);\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        var a;\n        (class {\n            static p = void (a = this);\n        });\n        console.log(typeof a);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_4829_1: {\n    options = {\n        properties: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            class A extends { f() {} }.f {}\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            class A extends [ () => {} ][0] {}\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4829_2: {\n    options = {\n        properties: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            class A extends {\n                f() {\n                    return arguments;\n                },\n            }.f {}\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            class A extends {\n                f() {\n                    return arguments;\n                },\n            }.f {}\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nmangle_properties: {\n    mangle = {\n        properties: {\n            domprops: true,\n            keep_quoted: true,\n        },\n    }\n    input: {\n        class A {\n            static #P = \"PASS\";\n            static get Q() {\n                return this.#P;\n            }\n            #p(n) {\n                return (this[\"q\"] = n) * this.r;\n            }\n            set q(v) {\n                this.r = v + 1;\n            }\n            r = this.#p(6);\n        }\n        console.log(A.Q, new A().r);\n    }\n    expect: {\n        class A {\n            static #t = \"PASS\";\n            static get t() {\n                return this.#t;\n            }\n            #s(t) {\n                return (this[\"q\"] = t) * this.s;\n            }\n            set q(t) {\n                this.s = t + 1;\n            }\n            s = this.#s(6);\n        }\n        console.log(A.t, new A().s);\n    }\n    expect_stdout: \"PASS 42\"\n    expect_warnings: [\n        \"INFO: Preserving reserved property q\",\n        \"INFO: Mapping property #P to #t\",\n        \"INFO: Mapping property Q to t\",\n        \"INFO: Mapping property #p to #s\",\n        \"INFO: Mapping property r to s\",\n        \"INFO: Preserving reserved property log\",\n    ]\n    node_version: \">=14.6\"\n}\n\nmangle_private_local: {\n    mangle = {\n        properties: {\n            domprops: true,\n        },\n    }\n    input: {\n        class A {\n            p = \"foo\";\n            #q = \"bar\";\n            f() {\n                console.log(this.p, this.#q);\n            }\n        }\n        class B {\n            #r = \"moo\";\n            #g() {\n                return \"baz\";\n            }\n            h() {\n                console.log(this.#r, this.#g());\n            }\n        }\n        new A().f();\n        new B().h();\n    }\n    expect: {\n        class A {\n            s = \"foo\";\n            #s = \"bar\";\n            o() {\n                console.log(this.s, this.#s);\n            }\n        }\n        class B {\n            #s = \"moo\";\n            #o() {\n                return \"baz\";\n            }\n            e() {\n                console.log(this.#s, this.#o());\n            }\n        }\n        new A().o();\n        new B().e();\n    }\n    expect_stdout: [\n        \"foo bar\",\n        \"moo baz\",\n    ]\n    expect_warnings: [\n        \"INFO: Mapping property p to s\",\n        \"INFO: Mapping property #q to #s\",\n        \"INFO: Mapping property f to o\",\n        \"INFO: Preserving reserved property log\",\n        \"INFO: Mapping property #r to #s\",\n        \"INFO: Mapping property #g to #o\",\n        \"INFO: Mapping property h to e\",\n    ]\n    node_version: \">=14.6\"\n}\n\nissue_4848: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            a(function() {\n                new A();\n            });\n            if (!console)\n                return;\n            class A {\n                constructor() {\n                    console.log(\"PASS\");\n                }\n            }\n        }\n        var g;\n        f(function(h) {\n            g = h;\n        });\n        g();\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            a(function() {\n                new A();\n            });\n            if (!console)\n                return;\n            class A {\n                constructor() {\n                    console.log(\"PASS\");\n                }\n            }\n        }\n        var g;\n        f(function(h) {\n            g = h;\n        });\n        g();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndrop_unused_self_reference: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {}\n        (A.p = A).q = console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4951_1: {\n    input: {\n        class A {\n            static#p = console.log(\"PASS\");\n        }\n    }\n    expect_exact: 'class A{static#p=console.log(\"PASS\")}'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_4951_2: {\n    input: {\n        new class {\n            constructor() {\n                this.#f().then(console.log);\n            }\n            async#f() {\n                return await \"PASS\";\n            }\n        }();\n    }\n    expect_exact: 'new class{constructor(){this.#f().then(console.log)}async#f(){return await\"PASS\"}};'\n    expect_stdout: \"PASS\"\n    node_version: \">=14.6\"\n}\n\nissue_4962_1: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                while (console.log(typeof g));\n            }\n            class A {\n                static p = f();\n            }\n        })(function g() {});\n    }\n    expect: {\n        (function() {\n            function f() {\n                while (console.log(typeof g));\n            }\n            (class {\n                static c = f();\n            });\n        })(function g() {});\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4962_1_strict: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            function f() {\n                while (console.log(typeof g));\n            }\n            class A {\n                static p = f();\n            }\n        })(function g() {});\n    }\n    expect: {\n        \"use strict\";\n        (function g() {});\n        while (console.log(typeof g));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4962_1_strict_direct: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                \"use strict\";\n                while (console.log(typeof g));\n            }\n            class A {\n                static p = f();\n            }\n        })(function g() {});\n    }\n    expect: {\n        (function g() {}),\n        void class {\n            static c = function() {\n                \"use strict\";\n                while (console.log(typeof g));\n            }();\n        };\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4962_2: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {}(function g() {\n            function h() {\n                f;\n            }\n            class A {\n                static p = h();\n            }\n        }, typeof g));\n    }\n    expect: {\n        console.log(function f() {}(function g() {\n            function h() {\n                f;\n            }\n            (class {\n                static c = h();\n            });\n        }));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4962_2_strict: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function f() {}(function g() {\n            function h() {\n                f;\n            }\n            class A {\n                static p = h();\n            }\n        }, typeof g));\n    }\n    expect: {\n        \"use strict\";\n        console.log(function f() {}(function g() {\n            f;\n        }));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4962_2_strict_direct: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {}(function g() {\n            function h() {\n                \"use strict\";\n                f;\n            }\n            class A {\n                static p = h();\n            }\n        }, typeof g));\n    }\n    expect: {\n        console.log(function f() {}(function g() {\n            (class {\n                static c = function() {\n                    \"use strict\";\n                    f;\n                }();\n            });\n        }));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4962_2_strict_direct_inline: {\n    options = {\n        directives: true,\n        ie: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {}(function g() {\n            function h() {\n                \"use strict\";\n                f;\n            }\n            class A {\n                static p = h();\n            }\n        }, typeof g));\n    }\n    expect: {\n        console.log(function f() {}(function g() {\n            (class {\n                static c = f;\n            });\n        }));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_4982_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        \"use strict\";\n        try {} catch (e) {\n            class A extends 42 {}\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        {\n            class A {}\n        }\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4982_2: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {} catch (e) {\n            class A {\n                static p = a = \"FAIL\";\n            }\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        {\n            class A {}\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_4992: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        class A {\n            static P = this;\n            get p() {}\n        }\n        console.log(typeof A.P);\n    }\n    expect: {\n        console.log(typeof class {\n            static P = this;\n            get p() {}\n        }.P);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_4996_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        console.log(new class A {\n            p = a-- && new A();\n        }().p.p);\n    }\n    expect: {\n        var a = 1;\n        console.log(new class A {\n            p = a-- && new A();\n        }().p.p);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=12\"\n}\n\nissue_4996_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        console.log(new class A {\n            p = a-- && new A();\n        }().p.p);\n    }\n    expect: {\n        var a = 1;\n        console.log(new class A {\n            p = a-- && new A();\n        }().p.p);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=12\"\n}\n\nissue_5015_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        try {\n            (class a {\n                [a]() {}\n            });\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a;\n        try {\n            (class a {\n                [a]() {}\n            });\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5015_2: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            new class A {\n                [(A, 42)]() {}\n            }();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            new class A {\n                [(A, 42)]() {}\n            }();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5015_3: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        (class A {\n            static f() {\n                return A;\n            }\n        });\n        console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        (class A {});\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5015_4: {\n    options = {\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (class A {\n            static f() {\n                return A;\n            }\n        });\n        console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5053_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            console.log(new class A {\n                constructor() {\n                    A = 42;\n                }\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            console.log(new class A {\n                constructor() {\n                    A = 42;\n                }\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5053_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            console.log(new class A {\n                f() {\n                    A = 42;\n                }\n            }().f());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            console.log(new class A {\n                f() {\n                    A = 42;\n                }\n            }().f());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5053_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            console.log(new class A {\n                p = A = 42;\n            }().p);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            console.log(new class A {\n                p = A = 42;\n            }().p);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5053_4: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            constructor() {\n                A = 42;\n            }\n        }\n        try {\n            console.log(new A());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        class A {\n            constructor() {\n                A = 42;\n            }\n        }\n        try {\n            console.log(new A());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5082_1: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            class B {\n                static P = new A();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            (class {\n                static c = new A();\n            });\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5082_1_strict: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            class B {\n                static P = new A();\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            new A();\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5082_2: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            class B {\n                static P = new A();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            (class {\n                static c = new A();\n            });\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5082_2_strict: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            class A {\n                p = console.log(\"PASS\");\n                q() {}\n            }\n            class B {\n                static P = new A();\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        void new class {\n            p = console.log(\"PASS\");\n            q() {}\n        }();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5142: {\n    options = {\n        evaluate: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b;\n        if (++a)\n            new class {\n                p = b = null;\n                constructor(c) {\n                    console.log(c ? \"FAIL\" : \"PASS\");\n                }\n            }(b, a);\n    }\n    expect: {\n        var a = 0, b;\n        if (++a)\n            new class {\n                p = b = null;\n                constructor(c) {\n                    console.log(c ? \"FAIL\" : \"PASS\");\n                }\n            }(b, 1);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5294_1: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (class A {\n            static p = console.log(typeof A);\n        });\n    }\n    expect: {\n        (class A {\n            static c = console.log(typeof A);\n        });\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_5294_2: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        class A {\n            static p = console.log(typeof A);\n        }\n    }\n    expect: {\n        class A {\n            static p = console.log(typeof A);\n        }\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_5294_3: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = this;\n        (class A {\n            static p = console.log(a === A ? \"FAIL\" : \"PASS\");\n        });\n    }\n    expect: {\n        var a = this;\n        (class A {\n            static p = console.log(a === A ? \"FAIL\" : \"PASS\");\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5294_4: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        (class A {\n            static p = function() {\n                var a = this;\n                console.log(a === A ? \"FAIL\" : \"PASS\");\n            }();\n        });\n    }\n    expect: {\n        (class A {\n            static p = function() {\n                console.log(this === A ? \"FAIL\" : \"PASS\");\n            }();\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5322: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 41;\n        class A {\n            static p() {\n                console.log(++a);\n            }\n            static q = this.p();\n        }\n    }\n    expect: {\n        var a = 41;\n        (class {\n            static p() {\n                console.log(++a);\n            }\n            static q = this.p();\n        });\n    }\n    expect_stdout: \"42\"\n    node_version: \">=12\"\n}\n\nissue_5352: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            new class {\n                [b = console.log(a)] = b;\n            }(a.p);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function f(a) {\n            var b;\n            new class {\n                [b = console.log(a)] = b;\n            }(a.p);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5387: {\n    options = {\n        properties: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            try {\n                class A extends a {}\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })({\n            f() {\n                return this;\n            }\n        }.f);\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            try {\n                class A extends a {}\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })({\n            f() {\n                return this;\n            }\n        }.f);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5389_1: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function log(m, n) {\n            console.log(m, n);\n        }\n        var a = log;\n        class A {\n            [a = \"FAIL\"] = a = \"PASS\";\n        }\n        var b = new A();\n        log(a, b.FAIL);\n    }\n    expect: {\n        function log(m, n) {\n            console.log(m, n);\n        }\n        var a = log;\n        class A {\n            [a = \"FAIL\"] = a = \"PASS\";\n        }\n        var b = new A();\n        log(a, b.FAIL);\n    }\n    expect_stdout: \"PASS PASS\"\n    node_version: \">=12\"\n}\n\nissue_5389_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function log(m, n) {\n            console.log(m, n);\n        }\n        var a = log;\n        var A = class {\n            [a = \"FAIL\"] = a = \"PASS\";\n        };\n        var b = new A();\n        log(a, b.FAIL);\n    }\n    expect: {\n        function log(m, n) {\n            console.log(m, n);\n        }\n        var a = log;\n        var A;\n        var b = new class {\n            [a = \"FAIL\"] = a = \"PASS\";\n        }();\n        log(a, b.FAIL);\n    }\n    expect_stdout: \"PASS PASS\"\n    node_version: \">=12\"\n}\n\nissue_5436: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            class A {\n                p = a;\n            }\n            var b = \"FAIL\";\n            A == b && b();\n            return new A();\n        }\n        console.log(f(\"PASS\").p);\n    }\n    expect: {\n        function f(a) {\n            class A {\n                p = a;\n            }\n            var b = \"FAIL\";\n            A == b && b();\n            return new A();\n        }\n        console.log(f(\"PASS\").p);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5481: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL 1\", log = console.log;\n        try {\n            a = \"PASS\";\n            (class extends 42 {});\n            log(\"FAIL 2\", a);\n        } catch (e) {\n            log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL 1\", log = console.log;\n        try {\n            a = \"PASS\";\n            (class extends 42 {});\n            log(\"FAIL 2\", a);\n        } catch (e) {\n            log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5489: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (class {\n            [console.log(\"foo\")];\n            static {\n                console.log(\"bar\");\n            }\n            static [console.log(\"baz\")]() {}\n        });\n    }\n    expect: {\n        (class {\n            [(console.log(\"foo\"), console.log(\"baz\"))];\n            static {\n                console.log(\"bar\");\n            }\n        });\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=16\"\n}\n\nissue_5489_strict: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (class {\n            [console.log(\"foo\")];\n            static {\n                console.log(\"bar\");\n            }\n            static [console.log(\"baz\")]() {}\n        });\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"foo\"),\n        console.log(\"baz\"),\n        (() => (() => {\n            console.log(\"bar\");\n        })())();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=16\"\n}\n\nissue_5502: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"FAIL\";\n        class A {\n            static p = a;\n            [a = \"PASS\"];\n        }\n        try {\n            b++;\n        } finally {\n            var a, b = 42;\n        }\n        console.log(a, b);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"FAIL\";\n        class A {\n            static p = a;\n            [a = \"PASS\"];\n        }\n        try {\n            b++;\n        } finally {\n            var a, b = 42;\n        }\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=12\"\n}\n\nissue_5504: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        console.log((a = 42, class {\n            static p;\n        }).p);\n    }\n    expect: {\n        \"use strict\";\n        var a;\n        console.log((a = 42, class {\n            static p;\n        }).p);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=12\"\n}\n\nissue_5512: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        a = \"PASS\";\n        class A {\n            static {\n                console.log(a);\n            }\n            static p = \"PASS\";\n        }\n        var a;\n    }\n    expect: {\n        \"use strict\";\n        a = \"PASS\";\n        class A {\n            static {\n                console.log(a);\n            }\n            static p = \"PASS\";\n        }\n        var a;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nissue_5531_1: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        class A {\n            p = function() {\n                var a = function f() {\n                    if (!a)\n                        console.log(\"foo\");\n                    return 42;\n                }(a++);\n            }();\n        }\n        new A();\n        new A();\n    }\n    expect: {\n        class A {\n            p = function() {\n                var a = function f() {\n                    if (!a)\n                        console.log(\"foo\");\n                    return 42;\n                }(a++);\n            }();\n        }\n        new A();\n        new A();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n    node_version: \">=12\"\n}\n\nissue_5531_2: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        class A {\n            static p = function() {\n                var a = function f() {\n                    if (!a)\n                        console.log(\"foo\");\n                    return 42;\n                }(a++);\n            }();\n        }\n        new A();\n        new A();\n    }\n    expect: {\n        class A {\n            static p = (a = function f() {\n                if (!a)\n                    console.log(\"foo\");\n                return 42;\n            }(a++), void 0);\n        }\n        var a;\n        new A();\n        new A();\n    }\n    expect_stdout: \"foo\"\n    node_version: \">=12\"\n}\n\nissue_5531_3: {\n    options = {\n        inline: true,\n    }\n    input: {\n        class A {\n            static {\n                (function() {\n                    var a = function f() {\n                        if (!a)\n                            console.log(\"foo\");\n                        return 42;\n                    }(a++);\n                })();\n            }\n        }\n        new A();\n        new A();\n    }\n    expect: {\n        class A {\n            static {\n                a = function f() {\n                    if (!a)\n                        console.log(\"foo\");\n                    return 42;\n                }(a++),\n                void 0;\n                var a;\n            }\n        }\n        new A();\n        new A();\n    }\n    expect_stdout: \"foo\"\n    node_version: \">=16\"\n}\n\nissue_5662: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(new (function() {\n            var g = function(a) {\n                return a;\n            };\n            return class {\n                h(b) {\n                    return g(b);\n                }\n            };\n        }())().h(\"PASS\"));\n    }\n    expect: {\n        console.log(new (function() {\n            var g = function(a) {\n                return a;\n            };\n            return class {\n                h(b) {\n                    return g(b);\n                }\n            };\n        }())().h(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5682_class_key: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            return \"foo\" in a;\n        }\n        class A {\n            foo() {}\n        }\n        console.log(f(new A()) ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        function f(o) {\n            return \"o\" in o;\n        }\n        class A {\n            o() {}\n        }\n        console.log(f(new A()) ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5682_class_key_computed: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            return \"foo\" in a;\n        }\n        class A {\n            [\"foo\"]() {}\n        }\n        console.log(f(new A()) ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        \"use strict\";\n        function f(o) {\n            return \"o\" in o;\n        }\n        class A {\n            [\"o\"]() {}\n        }\n        console.log(f(new A()) ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5724: {\n    options = {\n        arrows: true,\n        inline: true,\n        keep_fargs: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        class A {\n            static P = function(a) {\n                console.log(a, a);\n            }(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            console.log(a, a);\n        })(a);\n    }\n    expect_stdout: ReferenceError(\"a is not defined\")\n    node_version: \">=12\"\n}\n\nissue_5735_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(typeof function(a) {\n            return class {\n                static P = { ...a };\n            };\n        }([ 42..p ] = []));\n    }\n    expect: {\n        console.log(typeof function(a) {\n            return class {\n                static P = { ...a };\n            };\n        }([ 42..p ] = []));\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_5735_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(typeof function(a) {\n            return class {\n                p = a;\n            };\n        }(console.log(\"PASS\")));\n    }\n    expect: {\n        console.log(typeof function(a) {\n            return class {\n                p = a;\n            };\n        }(console.log(\"PASS\")));\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"function\",\n    ]\n    node_version: \">=12\"\n}\n\nissue_5747_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (async function() {\n            var a = await 42;\n            class A {\n                static P = a && console.log(typeof this);\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (async function() {\n            var a = await 42;\n            class A {\n                static P = a && console.log(typeof this);\n            }\n        })();\n    }\n    expect_stdout: \"function\"\n    node_version: \">=12\"\n}\n\nissue_5747_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (async function() {\n            var a = await 42;\n            class A {\n                static {\n                    a && console.log(typeof this);\n                }\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (async function() {\n            var a = await 42;\n            class A {\n                static {\n                    a && console.log(typeof this);\n                }\n            }\n        })();\n    }\n    expect_stdout: \"function\"\n    node_version: \">=16\"\n}\n\nissue_5874: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        console.log(Object.keys(function() {\n            class A {\n                [a];\n            }\n            a = \"FAIL\";\n            return new A();\n        }())[0]);\n    }\n    expect: {\n        var a = \"PASS\";\n        console.log(Object.keys(function() {\n            class A {\n                [a];\n            }\n            a = \"FAIL\";\n            return new A();\n        }())[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5876_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        class A {\n            static p = this.q;\n            f() {}\n        }\n        if (A)\n            console.log(\"PASS\");\n    }\n    expect: {\n        class A {\n            static p = this.q;\n            f() {}\n        }\n        if (A)\n            console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5876_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        class A {\n            static p = console.log(\"foo\");\n        }\n        if (A)\n            console.log(\"bar\");\n    }\n    expect: {\n        class A {\n            static p = console.log(\"foo\");\n        }\n        if (A)\n            console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=12\"\n}\n\nissue_5878_1: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        new class {\n            p = {};\n            in = console.log(\"PASS\");\n        }();\n    }\n    expect_exact: 'new class{p={};in=console.log(\"PASS\")}\\n'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5878_2: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        class A {\n            static p = console.log(\"PASS\");\n            instanceof() {}\n        }\n    }\n    expect_exact: 'class A{static p=console.log(\"PASS\");instanceof(){}}'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5878_3: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        new class {\n            p;\n            in = console.log(\"PASS\");\n        }();\n    }\n    expect_exact: 'new class{p;in=console.log(\"PASS\")}\\n'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5878_4: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        \"use strict\";\n        console.log(typeof class {\n            f() {}\n            instanceof() {}\n        });\n    }\n    expect_exact: [\n        '\"use strict\"',\n        \"console.log(typeof class{f(){}instanceof(){}})\",\n        \"\",\n    ]\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_5880_1: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        new class {\n            get;\n            p = console.log(\"PASS\");\n        }();\n    }\n    expect_exact: 'new class{get;p=console.log(\"PASS\")}\\n'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_5880_2: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        class A {\n            set;\n            static {\n                console.log(\"PASS\");\n            }\n        }\n    }\n    expect_exact: 'class A{set;static{console.log(\"PASS\")}}'\n    expect_stdout: \"PASS\"\n    node_version: \">=16\"\n}\n\nissue_5880_3: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        new class {\n            static;\n            f() {\n                console.log(\"PASS\");\n            }\n        }().f();\n    }\n    expect_exact: '(new class{static;f(){console.log(\"PASS\")}}).f()\\n'\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n"
  },
  {
    "path": "test/compress/collapse_vars.js",
    "content": "collapse_vars_side_effects_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var e = 7;\n            var s = \"abcdef\";\n            var i = 2;\n            var log = console.log.bind(console);\n            var x = s.charAt(i++);\n            var y = s.charAt(i++);\n            var z = s.charAt(i++);\n            log(x, y, z, e);\n        }\n        function f2() {\n            var e = 7;\n            var log = console.log.bind(console);\n            var s = \"abcdef\";\n            var i = 2;\n            var x = s.charAt(i++);\n            var y = s.charAt(i++);\n            var z = s.charAt(i++);\n            log(x, i, y, z, e);\n        }\n        function f3() {\n            var e = 7;\n            var s = \"abcdef\";\n            var i = 2;\n            var log = console.log.bind(console);\n            var x = s.charAt(i++);\n            var y = s.charAt(i++);\n            var z = s.charAt(i++);\n            log(x, z, y, e);\n        }\n        function f4() {\n            var log = console.log.bind(console),\n                i = 10,\n                x = i += 2,\n                y = i += 3,\n                z = i += 4;\n            log(x, z, y, i);\n        }\n        f1(), f2(), f3(), f4();\n    }\n    expect: {\n        function f1() {\n            var s = \"abcdef\", i = 2;\n            console.log.bind(console)(s.charAt(i++), s.charAt(+i), s.charAt(4), 7);\n        }\n        function f2() {\n            var s = \"abcdef\", i = 2;\n            console.log.bind(console)(s.charAt(i++), 5, s.charAt(i++), s.charAt(+i), 7);\n        }\n        function f3() {\n            var s = \"abcdef\",\n                i = 2,\n                log = console.log.bind(console),\n                x = s.charAt(i++),\n                y = s.charAt(+i);\n            log(x, s.charAt(4), y, 7);\n        }\n        function f4() {\n            var i = 10;\n            i += 2,\n            i += 3,\n            i += 4;\n            console.log.bind(console)(12, 19, 15, 19);\n        }\n        f1(), f2(), f3(), f4();\n    }\n    expect_stdout: true\n}\n\ncollapse_vars_side_effects_2: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function fn(x) { return console.log(x), x; }\n\n        function p1() { var a = foo(), b = bar(), c = baz(); return a + b + c; }\n        function p2() { var a = foo(), c = bar(), b = baz(); return a + b + c; }\n        function p3() { var b = foo(), a = bar(), c = baz(); return a + b + c; }\n        function p4() { var b = foo(), c = bar(), a = baz(); return a + b + c; }\n        function p5() { var c = foo(), a = bar(), b = baz(); return a + b + c; }\n        function p6() { var c = foo(), b = bar(), a = baz(); return a + b + c; }\n\n        function q1() { var a = foo(), b = bar(), c = baz(); return fn(a + b + c); }\n        function q2() { var a = foo(), c = bar(), b = baz(); return fn(a + b + c); }\n        function q3() { var b = foo(), a = bar(), c = baz(); return fn(a + b + c); }\n        function q4() { var b = foo(), c = bar(), a = baz(); return fn(a + b + c); }\n        function q5() { var c = foo(), a = bar(), b = baz(); return fn(a + b + c); }\n        function q6() { var c = foo(), b = bar(), a = baz(); return fn(a + b + c); }\n\n        function r1() { var a = foo(), b = bar(), c = baz(); return fn(a) + fn(b) + fn(c); }\n        function r2() { var a = foo(), c = bar(), b = baz(); return fn(a) + fn(b) + fn(c); }\n        function r3() { var b = foo(), a = bar(), c = baz(); return fn(a) + fn(b) + fn(c); }\n        function r4() { var b = foo(), c = bar(), a = baz(); return fn(a) + fn(b) + fn(c); }\n        function r5() { var c = foo(), a = bar(), b = baz(); return fn(a) + fn(b) + fn(c); }\n        function r6() { var c = foo(), b = bar(), a = baz(); return fn(a) + fn(b) + fn(c); }\n\n        function s1() { var a = foo(), b = bar(), c = baz(); return g(a + b + c); }\n        function s6() { var c = foo(), b = bar(), a = baz(); return g(a + b + c); }\n\n        function t1() { var a = foo(), b = bar(), c = baz(); return g(a) + g(b) + g(c); }\n        function t6() { var c = foo(), b = bar(), a = baz(); return g(a) + g(b) + g(c); }\n    }\n    expect: {\n        function fn(x) { return console.log(x), x; }\n\n        function p1() { return foo() + bar() + baz(); }\n        function p2() { var a = foo(), c = bar(); return a + baz() + c; }\n        function p3() { var b = foo(); return bar() + b + baz(); }\n        function p4() { var b = foo(), c = bar(); return baz() + b + c; }\n        function p5() { var c = foo(); return bar() + baz() + c; }\n        function p6() { var c = foo(), b = bar(); return baz() + b + c; }\n\n        function q1() { return fn(foo() + bar() + baz()); }\n        function q2() { var a = foo(), c = bar(); return fn(a + baz() + c); }\n        function q3() { var b = foo(); return fn(bar() + b + baz()); }\n        function q4() { var b = foo(), c = bar(); return fn(baz() + b + c); }\n        function q5() { var c = foo(); return fn(bar() + baz() + c); }\n        function q6() { var c = foo(), b = bar(); return fn(baz() + b + c); }\n\n        function r1() { var a = foo(), b = bar(), c = baz(); return fn(a) + fn(b) + fn(c); }\n        function r2() { var a = foo(), c = bar(), b = baz(); return fn(a) + fn(b) + fn(c); }\n        function r3() { var b = foo(), a = bar(), c = baz(); return fn(a) + fn(b) + fn(c); }\n        function r4() { var b = foo(), c = bar(); return fn(baz()) + fn(b) + fn(c); }\n        function r5() { var c = foo(), a = bar(), b = baz(); return fn(a) + fn(b) + fn(c); }\n        function r6() { var c = foo(), b = bar(); return fn(baz()) + fn(b) + fn(c); }\n\n        function s1() { var a = foo(), b = bar(), c = baz(); return g(a + b + c); }\n        function s6() { var c = foo(), b = bar(), a = baz(); return g(a + b + c); }\n\n        function t1() { var a = foo(), b = bar(), c = baz(); return g(a) + g(b) + g(c); }\n        function t6() { var c = foo(), b = bar(), a = baz(); return g(a) + g(b) + g(c); }\n    }\n}\n\ncollapse_vars_issue_721: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        passes: 2,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        define([\"require\", \"exports\", 'handlebars'], function(require, exports, hb) {\n            var win = window;\n            var _hb = win.Handlebars = hb;\n            return _hb;\n        });\n        def(function(hb) {\n            var win = window;\n            var prop = 'Handlebars';\n            var _hb = win[prop] = hb;\n            return _hb;\n        });\n        def(function(hb) {\n            var prop = 'Handlebars';\n            var win = window;\n            var _hb = win[prop] = hb;\n            return _hb;\n        });\n        def(function(hb) {\n            var prop = 'Handlebars';\n            var win = g();\n            var _hb = win[prop] = hb;\n            return _hb;\n        });\n        def(function(hb) {\n            var prop = g1();\n            var win = g2();\n            var _hb = win[prop] = hb;\n            return _hb;\n        });\n        def(function(hb) {\n            var win = g2();\n            var prop = g1();\n            var _hb = win[prop] = hb;\n            return _hb;\n        });\n    }\n    expect: {\n        define([ \"require\", \"exports\", \"handlebars\" ], function(require, exports, hb) {\n            return window.Handlebars = hb;\n        }),\n        def(function(hb) {\n            return window.Handlebars = hb;\n        }),\n        def(function(hb) {\n            return window.Handlebars = hb;\n        }),\n        def(function(hb) {\n            return g().Handlebars = hb;\n        }),\n        def(function(hb) {\n            var prop = g1();\n            return g2()[prop] = hb;\n        }),\n        def(function(hb) {\n            return g2()[g1()] = hb;\n        });\n    }\n}\n\ncollapse_vars_properties: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1(obj) {\n            var prop = 'LiteralProperty';\n            return !!-+obj[prop];\n        }\n        function f2(obj) {\n            var prop1 = 'One';\n            var prop2 = 'Two';\n            return ~!!-+obj[prop1 + prop2];\n        }\n    }\n    expect: {\n        function f1(obj) {\n            return !!-+obj.LiteralProperty;\n        }\n        function f2(obj) {\n            return ~!!-+obj.OneTwo;\n        }\n    }\n}\n\ncollapse_vars_if: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var not_used = sideeffect(), x = g1 + g2;\n            var y = x / 4, z = 'Bar' + y;\n            if ('x' != z) { return g9; }\n            else return g5;\n        }\n        function f2() {\n            var  x = g1 + g2, not_used = sideeffect();\n            var y = x / 4\n            var z = 'Bar' + y;\n            if ('x' != z) { return g9; }\n            else return g5;\n        }\n        function f3(x) {\n            if (x) {\n                var a = 1;\n                return a;\n            }\n            else {\n                var b = 2;\n                return b;\n            }\n        }\n    }\n    expect: {\n        function f1() {\n            sideeffect();\n            return \"x\" != \"Bar\" + (g1 + g2) / 4 ? g9 : g5;\n        }\n        function f2() {\n            var x = g1 + g2;\n            sideeffect();\n            return \"x\" != \"Bar\" + x / 4 ? g9 : g5;\n        }\n        function f3(x) {\n            return x ? 1 : 2;\n        }\n    }\n}\n\ncollapse_vars_while: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: false,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1(y) {\n            // Neither the non-constant while condition `c` will be\n            // replaced, nor the non-constant `x` in the body.\n            var x = y, c = 3 - y;\n            while (c) { return x; }\n            var z = y * y;\n            return z;\n        }\n        function f2(y) {\n            // The constant `x` will be replaced in the while body.\n            var x = 7;\n            while (y) { return x; }\n            var z = y * y;\n            return z;\n        }\n        function f3(y) {\n            // The non-constant `n` will not be replaced in the while body.\n            var n = 5 - y;\n            while (y) { return n; }\n            var z = y * y;\n            return z;\n        }\n    }\n    expect: {\n        function f1(y) {\n            var x = y, c = 3 - y;\n            while (c) return x;\n            return y * y;\n        }\n        function f2(y) {\n            while (y) return 7;\n            return y * y\n        }\n        function f3(y) {\n            var n = 5 - y;\n            while (y) return n;\n            return y * y;\n        }\n    }\n}\n\ncollapse_vars_do_while: {\n    options = {\n        booleans: false,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: false,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: \"keep_assign\",\n    }\n    input: {\n        function f1(y) {\n            // The constant do-while condition `c` will not be replaced.\n            var c = 9;\n            do {} while (c === 77);\n        }\n        function f2(y) {\n            // The non-constant do-while condition `c` will not be replaced.\n            var c = 5 - y;\n            do { } while (c);\n        }\n        function f3(y) {\n            // The constant `x` will be replaced in the do loop body.\n            function fn(n) { console.log(n); }\n            var a = 2, x = 7;\n            do {\n                fn(a = x);\n                break;\n            } while (y);\n        }\n        function f4(y) {\n            // The non-constant `a` will not be replaced in the do loop body.\n            var a = y / 4;\n            do {\n                return a;\n            } while (y);\n        }\n        function f5(y) {\n            function p(x) { console.log(x); }\n            do {\n                // The non-constant `a` will be replaced in p(a)\n                // because it is declared in same block.\n                var a = y - 3;\n                p(a);\n            } while (--y);\n        }\n    }\n    expect: {\n        function f1(y) {\n            var c = 9;\n            do ; while (77 === c);\n        }\n        function f2(y) {\n            var c = 5 - y;\n            do ; while (c);\n        }\n        function f3(y) {\n            function fn(n) { console.log(n); }\n            var a = 2, x = 7;\n            do {\n                fn(a = x);\n                break;\n            } while (y);\n        }\n        function f4(y) {\n            var a = y / 4;\n            do\n                return a;\n            while (y);\n        }\n        function f5(y) {\n            function p(x) { console.log(x); }\n            do {\n                p(y - 3);\n            } while (--y);\n        }\n    }\n}\n\ncollapse_vars_do_while_drop_assign: {\n    options = {\n        booleans: false,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: false,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1(y) {\n            // The constant do-while condition `c` will be not replaced.\n            var c = 9;\n            do {} while (c === 77);\n        }\n        function f2(y) {\n            // The non-constant do-while condition `c` will not be replaced.\n            var c = 5 - y;\n            do { } while (c);\n        }\n        function f3(y) {\n            // The constant `x` will be replaced in the do loop body.\n            function fn(n) { console.log(n); }\n            var a = 2, x = 7;\n            do {\n                fn(a = x);\n                break;\n            } while (y);\n        }\n        function f4(y) {\n            // The non-constant `a` will not be replaced in the do loop body.\n            var a = y / 4;\n            do {\n                return a;\n            } while (y);\n        }\n        function f5(y) {\n            function p(x) { console.log(x); }\n            do {\n                // The non-constant `a` will be replaced in p(a)\n                // because it is declared in same block.\n                var a = y - 3;\n                p(a);\n            } while (--y);\n        }\n    }\n    expect: {\n        function f1(y) {\n            var c = 9;\n            do ; while (77 === c);\n        }\n        function f2(y) {\n            var c = 5 - y;\n            do ; while (c);\n        }\n        function f3(y) {\n            function fn(n) { console.log(n); }\n            var x = 7;\n            do {\n                fn(x);\n                break;\n            } while (y);\n        }\n        function f4(y) {\n            var a = y / 4;\n            do\n                return a;\n            while (y);\n        }\n        function f5(y) {\n            function p(x) { console.log(x); }\n            do {\n                p(y - 3);\n            } while (--y);\n        }\n    }\n}\n\ncollapse_vars_seq: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var f1 = function(x, y) {\n            var a, b, r = x + y, q = r * r, z = q - r;\n            a = z, b = 7;\n            return a + b;\n        };\n        console.log(f1(1, 2));\n    }\n    expect: {\n        var f1 = function(x, y) {\n            var r = x + y;\n            return r * r - r + 7;\n        };\n        console.log(f1(1, 2));\n    }\n    expect_stdout: \"13\"\n}\n\ncollapse_vars_throw: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var f1 = function(x, y) {\n            var a, b, r = x + y, q = r * r, z = q - r;\n            a = z, b = 7;\n            throw a + b;\n        };\n        try {\n            f1(1, 2);\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        var f1 = function(x, y) {\n            var r = x + y;\n            throw r * r - r + 7;\n        };\n        try {\n            f1(1, 2);\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"13\"\n}\n\ncollapse_vars_switch_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var not_used = sideeffect(), x = g1 + g2;\n            var y = x / 4, z = 'Bar' + y;\n            switch (z) { case 0: return g9; }\n        }\n        function f2() {\n            var  x = g1 + g2, not_used = sideeffect();\n            var y = x / 4\n            var z = 'Bar' + y;\n            switch (z) { case 0: return g9; }\n        }\n        function f3(x) {\n            switch(x) { case 1: var a = 3 - x; return a; }\n        }\n    }\n    expect: {\n        function f1() {\n            sideeffect();\n            switch (\"Bar\" + (g1 + g2) / 4) { case 0: return g9 }\n        }\n        function f2() {\n            var x = g1 + g2;\n            sideeffect();\n            switch (\"Bar\" + x / 4) { case 0: return g9 }\n        }\n        function f3(x) {\n            // verify no extraneous semicolon in case block before return\n            // when the var definition was eliminated\n            switch(x) { case 1: return 3 - x; }\n        }\n    }\n}\n\ncollapse_vars_switch_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = 0;\n        (function(b) {\n            switch (b && [ b = 0, (c++, 0) ]) {\n              case c = 1 + c:\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(b) {\n            switch (b && [ b = 0, (c++, 0) ]) {\n              case c = 1 + c:\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\ncollapse_vars_assignment: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function log(x) { return console.log(x), x; }\n        function f0(c) {\n            var a = 3 / c;\n            return a = a;\n        }\n        function f1(c) {\n            var a = 3 / c;\n            var b = 1 - a;\n            return b;\n        }\n        function f2(c) {\n            var a = 3 / c;\n            var b = a - 7;\n            return log(c = b);\n        }\n        function f3(c) {\n            var a = 3 / c;\n            var b = a - 7;\n            return log(c |= b);\n        }\n        function f4(c) {\n            var a = 3 / c;\n            var b = 2;\n            return log(b += a);\n        }\n        function f5(c) {\n            var b = 2;\n            var a = 3 / c;\n            return log(b += a);\n        }\n        function f6(c) {\n            var b = g();\n            var a = 3 / c;\n            return log(b += a);\n        }\n    }\n    expect: {\n        function log(x) { return console.log(x), x; }\n        function f0(c) {\n            return 3 / c;\n        }\n        function f1(c) {\n            return 1 - 3 / c;\n        }\n        function f2(c) {\n            return log(c = 3 / c - 7);\n        }\n        function f3(c) {\n            return log(c |= 3 / c - 7);\n        }\n        function f4(c) {\n            var b = 2;\n            return log(b += 3 / c);\n        }\n        function f5(c) {\n            var b = 2;\n            return log(b += 3 / c);\n        }\n        function f6(c) {\n            var b = g();\n            return log(b += 3 / c);\n        }\n    }\n}\n\ncollapse_vars_lvalues: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: \"keep_assign\",\n    }\n    input: {\n        function f0(x) { var i = ++x; return x += i; }\n        function f1(x) { var a = (x -= 3); return x += a; }\n        function f2(x) { var z = x, a = ++z; return z += a; }\n        function f3(x) { var a = (x -= 3), b = x + a; return b; }\n        function f4(x) { var a = (x -= 3); return x + a; }\n        function f5(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return b - c; }\n        function f6(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return c - b; }\n        function f7(x) { var w = e1(), v = e2(), c = v - x, b = w = x; return b - c; }\n        function f8(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return b - c; }\n        function f9(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return c - b; }\n    }\n    expect: {\n        function f0(x) { var i = ++x; return x += i; }\n        function f1(x) { var a = (x -= 3); return x += a; }\n        function f2(x) { var z = x, a = ++z; return z += a; }\n        function f3(x) { var a = (x -= 3); return x + a; }\n        function f4(x) { var a = (x -= 3); return x + a; }\n        function f5(x) { var w = e1(), v = e2(), c = v = --x; return (w = x) - c; }\n        function f6(x) { var w = e1(), v = e2(); return (v = --x) - (w = x); }\n        function f7(x) { var w = e1(); return (w = x) - (e2() - x); }\n        function f8(x) { var w = e1(); return (w = x) - (e2() - x); }\n        function f9(x) { var w = e1(); return e2() - x - (w = x); }\n    }\n}\n\ncollapse_vars_lvalues_drop_assign: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        passes: 3,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f0(x) { var i = ++x; return x += i; }\n        function f1(x) { var a = (x -= 3); return x += a; }\n        function f2(x) { var z = x, a = ++z; return z += a; }\n        function f3(x) { var a = (x -= 3), b = x + a; return b; }\n        function f4(x) { var a = (x -= 3); return x + a; }\n        function f5(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return b - c; }\n        function f6(x) { var w = e1(), v = e2(), c = v = --x, b = w = x; return c - b; }\n        function f7(x) { var w = e1(), v = e2(), c = v - x, b = w = x; return b - c; }\n        function f8(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return b - c; }\n        function f9(x) { var w = e1(), v = e2(), b = w = x, c = v - x; return c - b; }\n    }\n    expect: {\n        function f0(x) { var i = ++x; return x += i; }\n        function f1(x) { var a = (x -= 3); return x += a; }\n        function f2(x) { var z = x, a = ++z; return z += a; }\n        function f3(x) { var a = (x -= 3); return x + a; }\n        function f4(x) { var a = (x -= 3); return x + a; }\n        function f5(x) { e1(), e2(); var c = --x; return x - c; }\n        function f6(x) { return e1(), e2(), --x - x; }\n        function f7(x) { return e1(), x - (e2() - x); }\n        function f8(x) { return e1(), x - (e2() - x); }\n        function f9(x) { return e1(), e2() - x - x; }\n    }\n}\n\ncollapse_vars_misc: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f0(o, a, h) {\n            var b = 3 - a;\n            var obj = o;\n            var seven = 7;\n            var prop = 'run';\n            var t = obj[prop](b)[seven] = h;\n            return t;\n        }\n        function f1(x) { var y = 5 - x; return y; }\n        function f2(x) { var z = foo(), y = z / (5 - x); return y; }\n        function f3(x) { var z = foo(), y = (5 - x) / z; return y; }\n        function f4(x) { var z = foo(), y = (5 - u) / z; return y; }\n        function f5(x) { var z = foo(), y = (5 - window.x) / z; return y; }\n        function f6() { var b = window.a * window.z; return b && zap(); }\n        function f7() { var b = window.a * window.z; return b + b; }\n        function f8() { var b = window.a * window.z; var c = b + 5; return b + c; }\n        function f9() { var b = window.a * window.z; return bar() || b; }\n        function f10(x) { var a = 5, b = 3; return a += b; }\n        function f11(x) { var a = 5, b = 3; return a += --b; }\n    }\n    expect: {\n        function f0(o, a, h) {\n            return o.run(3 - a)[7] = h;\n        }\n        function f1(x) { return 5 - x }\n        function f2(x) { return foo() / (5 - x) }\n        function f3(x) { return (5 - x) / foo() }\n        function f4(x) { var z = foo(); return (5 - u) / z }\n        function f5(x) { var z = foo(); return (5 - window.x) / z }\n        function f6() { return window.a * window.z && zap() }\n        function f7() { var b = window.a * window.z; return b + b }\n        function f8() { var b = window.a * window.z; return b + (5 + b) }\n        function f9() { var b = window.a * window.z; return bar() || b }\n        function f10(x) { return 8; }\n        function f11(x) { return 7; }\n    }\n}\n\ncollapse_vars_self_reference: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: false,\n    }\n    input: {\n        // avoid bug in self-referential declaration.\n        function f1() {\n            var self = {\n                inner: function() { return self; }\n            };\n        }\n        function f2() {\n            var self = { inner: self };\n        }\n    }\n    expect: {\n        // note: `unused` option is false\n        function f1() {\n            var self = {\n                inner: function() { return self }\n            };\n        }\n        function f2() {\n            var self = { inner: self };\n        }\n    }\n}\n\ncollapse_vars_repeated: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var dummy = 3, a = 5, unused = 2, a = 1, a = 3;\n            return -a;\n        }\n        function f2(x) {\n            var a = 3, a = x;\n            return a;\n        }\n        (function(x) {\n             var a = \"GOOD\" + x, e = \"BAD\", k = \"!\", e = a;\n             console.log(e + k);\n        })(\"!\"),\n        (function(x) {\n            var a = \"GOOD\" + x, e = \"BAD\" + x, k = \"!\", e = a;\n            console.log(e + k);\n        })(\"!\");\n    }\n    expect: {\n        function f1() {\n            return -3;\n        }\n        function f2(x) {\n            return x;\n        }\n        (function(x) {\n             console.log(\"GOOD!!\");\n        })(),\n        (function(x) {\n             console.log(\"GOOD!!\");\n        })();\n    }\n    expect_stdout: true\n}\n\ncollapse_vars_closures: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function constant_vars_can_be_replaced_in_any_scope() {\n            var outer = 3;\n            return function() { return outer; }\n        }\n        function non_constant_vars_can_only_be_replace_in_same_scope(x) {\n            var outer = x;\n            return function() { return outer; }\n        }\n    }\n    expect: {\n        function constant_vars_can_be_replaced_in_any_scope() {\n            return function() { return 3 }\n        }\n        function non_constant_vars_can_only_be_replace_in_same_scope(x) {\n            var outer = x\n            return function() { return outer }\n        }\n    }\n}\n\ncollapse_vars_unary: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f0(o, p) {\n            var x = o[p];\n            return delete x;\n        }\n        function f1(n) {\n            var k = !!n;\n            return n > +k;\n        }\n        function f2(n) {\n            // test unary with constant\n            var k = 7;\n            return k--;\n        }\n        function f3(n) {\n            // test unary with constant\n            var k = 7;\n            return ++k;\n        }\n        function f4(n) {\n            // test unary with non-constant\n            var k = 8 - n;\n            return k--;\n        }\n        function f5(n) {\n            // test unary with non-constant\n            var k = 9 - n;\n            return ++k;\n        }\n    }\n    expect: {\n        function f0(o, p) {\n            var x = o[p];\n            return delete x;\n        }\n        function f1(n) {\n            return +!!n < n;\n        }\n        function f2(n) {\n            var k = 7;\n            return k--;\n        }\n        function f3(n) {\n            var k = 7;\n            return ++k;\n        }\n        function f4(n) {\n            var k = 8 - n;\n            return k--;\n        }\n        function f5(n) {\n            var k = 9 - n;\n            return ++k;\n        }\n    }\n}\n\ncollapse_vars_try: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            try {\n                var a = 1;\n                return a;\n            }\n            catch (ex) {\n                var b = 2;\n                return b;\n            }\n            finally {\n                var c = 3;\n                return c;\n            }\n        }\n        function f2() {\n            var t = could_throw(); // shouldn't be replaced in try block\n            try {\n                return t + might_throw();\n            }\n            catch (ex) {\n                return 3;\n            }\n        }\n    }\n    expect: {\n        function f1() {\n            try {\n                return 1;\n            }\n            catch (ex) {\n                return 2;\n            }\n            finally {\n                return 3;\n            }\n        }\n        function f2() {\n            var t = could_throw();\n            try {\n                return t + might_throw();\n            }\n            catch (ex) {\n                return 3;\n            }\n        }\n    }\n}\n\ncollapse_vars_array_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1(x, y) {\n            var z = x + y;\n            return [z];\n        }\n        function f2(x, y) {\n            var z = x + y;\n            return [x, side_effect(), z];\n        }\n        function f3(x, y) {\n            var z = f(x + y);\n            return [ [3], [z, x, y], [g()] ];\n        }\n    }\n    expect: {\n        function f1(x, y) {\n            return [x + y]\n        }\n        function f2(x, y) {\n            var z = x + y\n            return [x, side_effect(), z]\n        }\n        function f3(x, y) {\n            return [ [3], [f(x + y), x, y], [g()] ]\n        }\n    }\n}\n\ncollapse_vars_array_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return [ (b = a, b.g()) ];\n        }\n        console.log(f({\n            g: function() {\n                return \"PASS\";\n            }\n        })[0]);\n    }\n    expect: {\n        function f(a) {\n            return [ a.g() ];\n        }\n        console.log(f({\n            g: function() {\n                return \"PASS\";\n            }\n        })[0]);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_vars_array_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return [ b = a, b, b ];\n        }\n        console.log(f().length);\n    }\n    expect: {\n        function f(a) {\n            return [ a, a, a ];\n        }\n        console.log(f().length);\n    }\n    expect_stdout: \"3\"\n}\n\ncollapse_vars_object_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f0(x, y) {\n            var z = x + y;\n            return {\n                get b() { return 7; },\n                r: z\n            };\n        }\n        function f1(x, y) {\n            var z = x + y;\n            return {\n                r: z,\n                get b() { return 7; }\n            };\n        }\n        function f2(x, y) {\n            var z = x + y;\n            var k = x - y;\n            return {\n                q: k,\n                r: g(x),\n                s: z\n            };\n        }\n        function f3(x, y) {\n            var z = f(x + y);\n            return [{\n                a: {q: x, r: y, s: z},\n                b: g()\n            }];\n        }\n    }\n    expect: {\n        function f0(x, y) {\n            return {\n                get b() { return 7; },\n                r: x + y\n            };\n        }\n        function f1(x, y) {\n            return {\n                r: x + y,\n                get b() { return 7; }\n            };\n        }\n        function f2(x, y) {\n            var z = x + y;\n            return {\n                q: x - y,\n                r: g(x),\n                s: z\n            };\n        }\n        function f3(x, y) {\n            return [{\n                a: {q: x, r: y, s: f(x + y)},\n                b: g()\n            }];\n        }\n    }\n}\n\ncollapse_vars_object_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return {\n                p: (b = a, b.g())\n            };\n        }\n        console.log(f({\n            g: function() {\n                return \"PASS\";\n            }\n        }).p);\n    }\n    expect: {\n        function f(a) {\n            return {\n                p: a.g()\n            };\n        }\n        console.log(f({\n            g: function() {\n                return \"PASS\";\n            }\n        }).p);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_vars_object_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return {\n                p: b = a,\n                q: b,\n                r: b,\n            };\n        }\n        console.log(f(\"PASS\").r);\n    }\n    expect: {\n        function f(a) {\n            return {\n                p: a,\n                q: a,\n                r: a,\n            };\n        }\n        console.log(f(\"PASS\").r);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_vars_eval_and_with: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        // Don't attempt to collapse vars in presence of eval() or with statement.\n        (function f0() {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })();\n        (function f1() {\n            var o = {a: 1}, a = 2;\n            with (o) console.log(a);\n        })();\n        (function f2() {\n            var o = {a: 1}, a = 2;\n            return function() { with (o) console.log(a) };\n        })()();\n    }\n    expect: {\n        (function f0() {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })();\n        (function f1() {\n            var o = {a: 1}, a = 2;\n            with(o) console.log(a);\n        })();\n        (function f2() {\n            var o = {a: 1}, a = 2;\n            return function() { with (o) console.log(a) };\n        })()();\n    }\n    expect_stdout: true\n}\n\ncollapse_vars_constants: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1(x) {\n            var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();\n            return b + (function() { return d - a * e - c; })();\n        }\n        function f2(x) {\n            var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();\n            return b + (function() { return -a * e - c; })();\n        }\n        function f3(x) {\n            var a = 4, b = x.prop, c = 5, not_used = sideeffect1();\n            return b + (function() { return -a - c; })();\n        }\n    }\n    expect: {\n        function f1(x) {\n            var b = x.prop, d = sideeffect1(), e = sideeffect2();\n            return b + (function() { return d - 4 * e - 5; })();\n        }\n        function f2(x) {\n            var b = x.prop, e = (sideeffect1(), sideeffect2());\n            return b + (function() { return -4 * e - 5; })();\n        }\n        function f3(x) {\n            var b = x.prop;\n            sideeffect1();\n            return b + -9;\n        }\n    }\n}\n\ncollapse_vars_arguments_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var outer = function() {\n            // Do not replace `arguments` but do replace the constant `k` before it.\n            var k = 7, arguments = 5, inner = function() { console.log(arguments); }\n            inner(k, 1);\n        }\n        outer();\n    }\n    expect: {\n        (function() {\n            (function(){console.log(arguments);})(7, 1);\n        })();\n    }\n    expect_stdout: true\n}\n\ncollapse_vars_arguments_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function log(a, b) {\n            console.log(b);\n        }\n        function f(c) {\n            var d = arguments[0];\n            c = \"FAIL\";\n            log(c, d);\n        }\n        f();\n        f(\"PASS\");\n    }\n    expect: {\n        function log(a, b) {\n            console.log(b);\n        }\n        function f(c) {\n            var d = arguments[0];\n            log(c = \"FAIL\", d);\n        }\n        f();\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"PASS\",\n    ]\n}\n\ncollapse_vars_arguments_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function log(a, b) {\n            console.log(b);\n        }\n        function f(c) {\n            var args = arguments;\n            console.log(c);\n            var d = args[0];\n            c = \"FAIL\";\n            log(c, d);\n        }\n        f();\n        f(\"PASS\");\n    }\n    expect: {\n        function log(a, b) {\n            console.log(b);\n        }\n        function f(c) {\n            var args = arguments;\n            console.log(c);\n            var d = args[0];\n            log(c = \"FAIL\", d);\n        }\n        f();\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\ncollapse_vars_short_circuit: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f0(x) { var a = foo(), b = bar(); return b || x; }\n        function f1(x) { var a = foo(), b = bar(); return b && x; }\n        function f2(x) { var a = foo(), b = bar(); return x && a && b; }\n        function f3(x) { var a = foo(), b = bar(); return a && x; }\n        function f4(x) { var a = foo(), b = bar(); return a && x && b; }\n        function f5(x) { var a = foo(), b = bar(); return x || a || b; }\n        function f6(x) { var a = foo(), b = bar(); return a || x || b; }\n        function f7(x) { var a = foo(), b = bar(); return a && b && x; }\n        function f8(x,y) { var a = foo(), b = bar(); return (x || a) && (y || b); }\n        function f9(x,y) { var a = foo(), b = bar(); return (x && a) || (y && b); }\n        function f10(x,y) { var a = foo(), b = bar(); return (x - a) || (y - b); }\n        function f11(x,y) { var a = foo(), b = bar(); return (x - b) || (y - a); }\n        function f12(x,y) { var a = foo(), b = bar(); return (x - y) || (b - a); }\n        function f13(x,y) { var a = foo(), b = bar(); return (a - b) || (x - y); }\n        function f14(x,y) { var a = foo(), b = bar(); return (b - a) || (x - y); }\n    }\n    expect: {\n        function f0(x) { foo(); return bar() || x; }\n        function f1(x) { foo(); return bar() && x; }\n        function f2(x) { var a = foo(), b = bar(); return x && a && b; }\n        function f3(x) { var a = foo(); bar(); return a && x; }\n        function f4(x) { var a = foo(), b = bar(); return a && x && b; }\n        function f5(x) { var a = foo(), b = bar(); return x || a || b; }\n        function f6(x) { var a = foo(), b = bar(); return a || x || b; }\n        function f7(x) { var a = foo(), b = bar(); return a && b && x; }\n        function f8(x,y) { var a = foo(), b = bar(); return (x || a) && (y || b); }\n        function f9(x,y) { var a = foo(), b = bar(); return (x && a) || (y && b); }\n        function f10(x,y) { var a = foo(), b = bar(); return (x - a) || (y - b); }\n        function f11(x,y) { var a = foo(); return (x - bar()) || (y - a); }\n        function f12(x,y) { var a = foo(), b = bar(); return (x - y) || (b - a); }\n        function f13(x,y) { return (foo() - bar()) || (x - y); }\n        function f14(x,y) { var a = foo(); return (bar() - a) || (x - y); }\n    }\n}\n\ncollapse_vars_short_circuited_conditions: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: false,\n        conditionals: false,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: false,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        sequences: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function c1(x) { var a = foo(), b = bar(), c = baz(); return a ? b : c; }\n        function c2(x) { var a = foo(), b = bar(), c = baz(); return a ? c : b; }\n        function c3(x) { var a = foo(), b = bar(), c = baz(); return b ? a : c; }\n        function c4(x) { var a = foo(), b = bar(), c = baz(); return b ? c : a; }\n        function c5(x) { var a = foo(), b = bar(), c = baz(); return c ? a : b; }\n        function c6(x) { var a = foo(), b = bar(), c = baz(); return c ? b : a; }\n\n        function i1(x) { var a = foo(), b = bar(), c = baz(); if (a) return b; else return c; }\n        function i2(x) { var a = foo(), b = bar(), c = baz(); if (a) return c; else return b; }\n        function i3(x) { var a = foo(), b = bar(), c = baz(); if (b) return a; else return c; }\n        function i4(x) { var a = foo(), b = bar(), c = baz(); if (b) return c; else return a; }\n        function i5(x) { var a = foo(), b = bar(), c = baz(); if (c) return a; else return b; }\n        function i6(x) { var a = foo(), b = bar(), c = baz(); if (c) return b; else return a; }\n    }\n    expect: {\n        function c1(x) { var a = foo(), b = bar(), c = baz(); return a ? b : c; }\n        function c2(x) { var a = foo(), b = bar(), c = baz(); return a ? c : b; }\n        function c3(x) { var a = foo(), b = bar(), c = baz(); return b ? a : c; }\n        function c4(x) { var a = foo(), b = bar(), c = baz(); return b ? c : a; }\n        function c5(x) { var a = foo(), b = bar(); return baz() ? a : b; }\n        function c6(x) { var a = foo(), b = bar(); return baz() ? b : a; }\n\n        function i1(x) { var a = foo(), b = bar(), c = baz(); if (a) return b; else return c; }\n        function i2(x) { var a = foo(), b = bar(), c = baz(); if (a) return c; else return b; }\n        function i3(x) { var a = foo(), b = bar(), c = baz(); if (b) return a; else return c; }\n        function i4(x) { var a = foo(), b = bar(), c = baz(); if (b) return c; else return a; }\n        function i5(x) { var a = foo(), b = bar(); if (baz()) return a; else return b; }\n        function i6(x) { var a = foo(), b = bar(); if (baz()) return b; else return a; }\n    }\n}\n\ncollapse_vars_regexp: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var k = 9;\n            var rx = /[A-Z]+/;\n            return [rx, k];\n        }\n        function f2() {\n            var rx = /ab*/g;\n            return function(s) {\n                return rx.exec(s);\n            };\n        }\n        function f3() {\n            var rx = /ab*/g;\n            return function() {\n                return rx;\n            };\n        }\n        (function() {\n            var result;\n            var s = \"acdabcdeabbb\";\n            var rx = /ab*/g;\n            while (result = rx.exec(s))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result;\n            var s = \"acdabcdeabbb\";\n            var rx = f2();\n            while (result = rx(s))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result;\n            var s = \"acdabcdeabbb\";\n            var rx = f3();\n            while (result = rx().exec(s))\n                console.log(result[0]);\n        })();\n    }\n    expect: {\n        function f1() {\n            return [/[A-Z]+/, 9];\n        }\n        function f2() {\n            var rx = /ab*/g;\n            return function(s) {\n                return rx.exec(s);\n            };\n        }\n        function f3() {\n            var rx = /ab*/g;\n            return function() {\n                return rx;\n            };\n        }\n        (function() {\n            var result, rx = /ab*/g;\n            while (result = rx.exec(\"acdabcdeabbb\"))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result, rx = f2();\n            while (result = rx(\"acdabcdeabbb\"))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result, rx = f3();\n            while (result = rx().exec(\"acdabcdeabbb\"))\n                console.log(result[0]);\n        })();\n    }\n    expect_stdout: [\n        \"a\",\n        \"ab\",\n        \"abbb\",\n        \"a\",\n        \"ab\",\n        \"abbb\",\n        \"a\",\n        \"ab\",\n        \"abbb\",\n    ]\n}\n\ncollapse_arg_sequence: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            a(\"foo\");\n        })((console.log(\"bar\"), console.log));\n    }\n    expect: {\n        (function(a) {\n            (0, console.log)(\"foo\");\n        })(console.log(\"bar\"));\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n}\n\ncollapse_for_init: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a = (Math, console), b = a.log(\"PASS\"); b;);\n    }\n    expect: {\n        Math;\n        for (var a, b = console.log(\"PASS\"); b;);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1537: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var k = '';\n        for (k in {prop: 'val'}){}\n    }\n    expect: {\n        var k = '';\n        for (k in {prop: 'val'});\n    }\n}\n\nissue_1562: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var v = 1, B = 2;\n        for (v in objs) f(B);\n\n        var x = 3, C = 10;\n        while(x + 2) bar(C);\n\n        var y = 4, D = 20;\n        do bar(D); while(y + 2);\n\n        var z = 5, E = 30;\n        for (; f(z + 2) ;) bar(E);\n    }\n    expect: {\n        var v = 1;\n        for (v in objs) f(2);\n\n        while(5) bar(10);\n\n        do bar(20); while(6);\n\n        for (; f(7) ;) bar(30);\n    }\n}\n\nissue_1605_1: {\n    options = {\n        collapse_vars: true,\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        function foo(x) {\n            var y = x;\n            return y;\n        }\n        var o = new Object;\n        o.p = 1;\n    }\n    expect: {\n        function foo(x) {\n            return x;\n        }\n        var o = new Object;\n        o.p = 1;\n    }\n}\n\nissue_1605_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: \"vars\",\n        unused: true,\n    }\n    input: {\n        function foo(x) {\n            var y = x;\n            return y;\n        }\n        var o = new Object;\n        o.p = 1;\n    }\n    expect: {\n        function foo(x) {\n            return x;\n        }\n        (new Object).p = 1;\n    }\n}\n\nissue_1631_1: {\n    options = {\n        collapse_vars: true,\n        hoist_funs: true,\n        join_vars: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var pc = 0;\n        function f(x) {\n            pc = 200;\n            return 100;\n        }\n        function x() {\n            var t = f();\n            pc += t;\n            return pc;\n        }\n        console.log(x());\n    }\n    expect: {\n        function f(x) {\n            return pc = 200, 100;\n        }\n        function x() {\n            var t = f();\n            return pc += t;\n        }\n        var pc = 0;\n        console.log(x());\n    }\n    expect_stdout: \"300\"\n}\n\nissue_1631_2: {\n    options = {\n        collapse_vars: true,\n        hoist_funs: true,\n        join_vars: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        function f() {\n            a = 2;\n            return 4;\n        }\n        function g() {\n            var t = f();\n            b = a + t;\n            return b;\n        }\n        console.log(g());\n    }\n    expect: {\n        function f() {\n            return a = 2, 4;\n        }\n        function g() {\n            var t = f();\n            return b = a + t;\n        }\n        var a = 0, b = 1;\n        console.log(g());\n    }\n    expect_stdout: \"6\"\n}\n\nissue_1631_3: {\n    options = {\n        collapse_vars: true,\n        hoist_funs: true,\n        join_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function g() {\n            var a = 0, b = 1;\n            function f() {\n                a = 2;\n                return 4;\n            }\n            var t = f();\n            b = a + t;\n            return b;\n        }\n        console.log(g());\n    }\n    expect: {\n        function g() {\n            function f() {\n                return a = 2, 4;\n            }\n            var a = 0, t = f();\n            return a + t;\n        }\n        console.log(g());\n    }\n    expect_stdout: \"6\"\n}\n\nvar_side_effects_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var print = console.log.bind(console);\n        function foo(x) {\n            var twice = x * 2;\n            print('Foo:', twice);\n        }\n        foo(10);\n    }\n    expect: {\n        var print = console.log.bind(console);\n        function foo(x) {\n            print('Foo:', 2 * x);\n        }\n        foo(10);\n    }\n    expect_stdout: true\n}\n\nvar_side_effects_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var print = console.log.bind(console);\n        function foo(x) {\n            var twice = x.y * 2;\n            print('Foo:', twice);\n        }\n        foo({ y: 10 });\n    }\n    expect: {\n        var print = console.log.bind(console);\n        function foo(x) {\n            var twice = 2 * x.y;\n            print('Foo:', twice);\n        }\n        foo({ y: 10 });\n    }\n    expect_stdout: true\n}\n\nvar_side_effects_3: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var print = console.log.bind(console);\n        function foo(x) {\n            var twice = x.y * 2;\n            print('Foo:', twice);\n        }\n        foo({ y: 10 });\n    }\n    expect: {\n        var print = console.log.bind(console);\n        function foo(x) {\n            print('Foo:', 2 * x.y);\n        }\n        foo({ y: 10 });\n    }\n    expect_stdout: true\n}\n\nreduce_vars_assign: {\n    options = {\n        collapse_vars: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        !function() {\n            var a = 1;\n            a = [].length,\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            var a = 1;\n            a = [].length,\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"0\"\n}\n\niife_1: {\n    options = {\n        collapse_vars: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var log = function(x) {\n            console.log(x);\n        }, foo = bar();\n        log(foo);\n    }\n    expect: {\n        (function(x) {\n            console.log(x);\n        })(bar());\n    }\n}\n\niife_2: {\n    options = {\n        collapse_vars: true,\n        reduce_funcs: false,\n        reduce_vars: false,\n        toplevel: true,\n        unused: false,\n    }\n    input: {\n        var foo = bar();\n        !function(x) {\n            console.log(x);\n        }(foo);\n    }\n    expect: {\n        var foo;\n        !function(x) {\n            console.log(x);\n        }(bar());\n    }\n}\n\nvar_defs: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var f1 = function(x, y) {\n            var a, b, r = x + y, q = r * r, z = q - r, a = z, b = 7;\n            console.log(a + b);\n        };\n        f1(\"1\", 0);\n    }\n    expect: {\n        var f1 = function(x, y) {\n            var r = x + y;\n            console.log(r * r - r + 7);\n        };\n        f1(\"1\", 0);\n    }\n    expect_stdout: \"97\"\n}\n\nassignment: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a;\n            a = x;\n            return a;\n        }\n    }\n    expect: {\n        function f() {\n            return x;\n        }\n    }\n}\n\nfor_init: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var a = x;\n            var b = y;\n            for (a; b;);\n        }\n    }\n    expect: {\n        function f(x, y) {\n            var b = y;\n            for (x; b;);\n        }\n    }\n}\n\nswitch_case_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y, z) {\n            var a = x();\n            var b = y();\n            var c = z;\n            switch (a) {\n              default: d();\n              case b: e();\n              case c: f();\n            }\n        }\n    }\n    expect: {\n        function f(x, y, z) {\n            switch (x()) {\n              default: d();\n              case y(): e();\n              case z: f();\n            }\n        }\n    }\n}\n\nswitch_case_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1, b = 2;\n        switch (b++) {\n          case b:\n            var c = a;\n            var a;\n            break;\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = 1, b = 2;\n        switch (b++) {\n          case b:\n            var c = a;\n            var a;\n            break;\n        }\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nswitch_case_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1, b = 2;\n        switch (a) {\n          case a:\n            var b;\n            break;\n          case b:\n            break;\n        }\n        console.log(b);\n    }\n    expect: {\n        var a = 1, b = 2;\n        switch (a) {\n          case a:\n            var b;\n            break;\n          case b:\n            break;\n        }\n        console.log(b);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_27: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(jQuery) {\n            var $;\n            $ = jQuery;\n            $(\"body\").addClass(\"foo\");\n        })(jQuery);\n    }\n    expect: {\n        (function(jQuery) {\n            jQuery(\"body\").addClass(\"foo\");\n        })(jQuery);\n    }\n}\n\nmodified: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f1(b) {\n            var a = b;\n            return b + a;\n        }\n        function f2(b) {\n            var a = b;\n            return b++ + a;\n        }\n        function f3(b) {\n            var a = b++;\n            return b + a;\n        }\n        function f4(b) {\n            var a = b++;\n            return b++ + a;\n        }\n        function f5(b) {\n            var a = function() {\n                return b;\n            }();\n            return b++ + a;\n        }\n        console.log(f1(1), f2(1), f3(1), f4(1), f5(1));\n    }\n    expect: {\n        function f1(b) {\n            return b + b;\n        }\n        function f2(b) {\n            var a = b;\n            return b++ + a;\n        }\n        function f3(b) {\n            var a = b++;\n            return b + a;\n        }\n        function f4(b) {\n            var a = b++;\n            return b++ + a;\n        }\n        function f5(b) {\n            var a = function() {\n                return b;\n            }();\n            return b++ + a;\n        }\n        console.log(f1(1), f2(1), f3(1), f4(1), f5(1));\n    }\n    expect_stdout: \"2 2 3 3 2\"\n}\n\nissue_1858: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(x) {\n            var a = {}, b = a.b = x;\n            return a.b + b;\n        }(1));\n    }\n    expect: {\n        console.log(function(x) {\n            var a = {}, b = a.b = 1;\n            return a.b + b;\n        }());\n    }\n    expect_stdout: \"2\"\n}\n\nanonymous_function: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function f(a) {\n            f ^= 0;\n            return f * a;\n        }(1));\n    }\n    expect: {\n        console.log(function f(a) {\n            f ^= 0;\n            return f * a;\n        }(1));\n    }\n    expect_stdout: true\n}\n\nside_effects_property: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = [];\n        var b = 0;\n        a[b++] = function() { return 42;};\n        var c = a[b++]();\n        console.log(c);\n    }\n    expect: {\n        var a = [];\n        var b = 0;\n        a[b++] = function() { return 42;};\n        var c = a[b++]();\n        console.log(c);\n    }\n    expect_stdout: true\n}\n\nundeclared_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var a;\n            a = x;\n            b = y;\n            return b + a;\n        }\n    }\n    expect: {\n        function f(x, y) {\n            return (b = y) + x;\n        }\n    }\n}\n\nundeclared_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var a;\n            a = x;\n            b = y;\n            return a + b;\n        }\n    }\n    expect: {\n        function f(x, y) {\n            return x + (b = y);\n        }\n    }\n}\n\nundeclared_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var a;\n            a = x;\n            b = y;\n            return b + a();\n        }\n    }\n    expect: {\n        function f(x, y) {\n            return (b = y) + x();\n        }\n    }\n}\n\nundeclared_4: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var a;\n            a = x;\n            b = y;\n            return a() + b;\n        }\n    }\n    expect: {\n        function f(x, y) {\n            b = y;\n            return x() + b;\n        }\n    }\n}\n\nref_scope: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 1, b = 2, c = 3;\n            var a = c++, b = b /= a;\n            return function() {\n                return a;\n            }() + b;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a = 1, b = 2, c = 3;\n            b = b /= a = c++;\n            return function() {\n                return a;\n            }() + b;\n        }());\n    }\n    expect_stdout: true\n}\n\nchained_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 2;\n        var a = 3 / a;\n        console.log(a);\n    }\n    expect: {\n        var a = 3 / (a = 2);\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\nchained_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        var a = 2;\n        a = 3 / a;\n        console.log(a);\n    }\n    expect: {\n        var a;\n        a = 3 / (a = 2);\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\nchained_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            var c = a, c = b;\n            b++;\n            return c;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(a, b) {\n            var c = 1, c = b;\n            b++;\n            return c;\n        }(0, 2));\n    }\n    expect_stdout: \"2\"\n}\n\nchained_4: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"foo\", b = 42;\n        var b = void (b = a);\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"foo\", b = 42;\n        var b = void (b = a);\n        console.log(a, b);\n    }\n    expect_stdout: \"foo undefined\"\n}\n\nchained_5: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\";\n        var a = (console, console.log(a));\n        a && ++a;\n    }\n    expect: {\n        var a = \"PASS\";\n        console;\n        var a;\n        (a = console.log(a)) && ++a;\n    }\n    expect_stdout: \"PASS\"\n}\n\nboolean_binary_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1;\n        a++;\n        (function() {} || a || 3).toString();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        a++;\n        (function() {} || a || 3).toString();\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\nboolean_binary_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = 0;\n        c += 1;\n        (function() {\n            c = 1 + c;\n        } || 9).toString();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        c += 1;\n        (function() {\n            c = 1 + c;\n        } || 9).toString();\n        console.log(c);\n    }\n    expect_stdout: true\n}\n\ninner_lvalues: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a, b = 10;\n        var a = (--b || a || 3).toString(), c = --b + -a;\n        console.log(null, a, b);\n    }\n    expect: {\n        var b = 10;\n        var a = (--b || a || 3).toString(), c = --b + -a;\n        console.log(null, a, b);\n    }\n    expect_stdout: true\n}\n\ndouble_def_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = x, a = a && y;\n        a();\n    }\n    expect: {\n        var a = x;\n        (a = a && y)();\n    }\n}\n\ndouble_def_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = x, a = a && y;\n        a();\n    }\n    expect: {\n        (x && y)();\n    }\n}\n\ntoplevel_single_reference: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        for (var b in x) {\n            var a = b;\n            b(a);\n        }\n    }\n    expect: {\n        for (var b in x) {\n            var a = b;\n            b(b);\n        }\n    }\n}\n\nunused_orig: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        console.log(function(b) {\n            var a;\n            var c = b;\n            for (var d in c) {\n                var a = c[0];\n                return --b + a;\n            }\n            try {\n            } catch (e) {\n                --b + a;\n            }\n            a && a.NaN;\n        }([2]), a);\n    }\n    expect: {\n        var a = 1;\n        console.log(function(b) {\n            var c = b;\n            for (var d in c) {\n                var a;\n                return --b + c[0];\n            }\n            a && a.NaN;\n        }([2]), a);\n    }\n    expect_stdout: \"3 1\"\n}\n\nissue_315: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(s) {\n            var w, _i, _len, _ref, _results;\n            _ref = s.trim().split(\" \");\n            _results = [];\n            for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n                w = _ref[_i];\n                _results.push(w.toLowerCase());\n            }\n            return _results;\n        }(\"test\"));\n    }\n    expect: {\n        console.log(function() {\n            var w, _i, _len, _ref, _results;\n            for (_results = [], _i = 0, _len = (_ref = \"test\".trim().split(\" \")).length; _i < _len ; _i++)\n                w = _ref[_i], _results.push(w.toLowerCase());\n            return _results;\n        }());\n    }\n    expect_stdout: true\n}\n\nlvalues_def: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        var a = b++, b = +function() {}();\n        a && a[a++];\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 1;\n        a = b++, b = +void 0;\n        a && a[a++];\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\ncompound_assignment_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        a = 1;\n        a += a + 2;\n        console.log(a);\n    }\n    expect: {\n        var a;\n        a = 1;\n        a += a + 2;\n        console.log(a);\n    }\n    expect_stdout: \"4\"\n}\n\ncompound_assignment_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        a = 1;\n        for (a += a + 2; console.log(a););\n    }\n    expect: {\n        var a;\n        a = 1;\n        for (a += a + 2; console.log(a););\n    }\n    expect_stdout: \"4\"\n}\n\ncompound_assignment_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1;\n        a += (console.log(\"PASS\"), 2);\n        a.p;\n    }\n    expect: {\n        var a = 1;\n        (a += (console.log(\"PASS\"), 2)).p;\n    }\n    expect_stdout: \"PASS\"\n}\n\ncompound_assignment_4: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a = \"\";\n        a += (a = \"FAIL\", A);\n        a.p;\n        console.log(a);\n    }\n    expect: {\n        var a = \"\";\n        (a += (a = \"FAIL\", A = \"PASS\")).p;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncompound_assignment_5: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0, b;\n        a += 42;\n        b && (a *= null);\n        console.log(a);\n    }\n    expect: {\n        var a = 0, b;\n        a += 42;\n        b && (a *= null);\n        console.log(a);\n    }\n    expect_stdout: \"42\"\n}\n\ncompound_assignment_6: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        a ^= 6;\n        a *= a + 1;\n        console.log(a);\n    }\n    expect: {\n        var a;\n        a = (a ^= 6) * (a + 1);\n        console.log(a);\n    }\n    expect_stdout: \"42\"\n}\n\ncompound_assignment_7: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FA\";\n        a = a + \"I\";\n        a = a + \"L\";\n        if (console)\n            a = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"FA\";\n        a = a + \"I\" + \"L\";\n        if (console)\n            a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncompound_assignment_8: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 2;\n        a = 3 * a;\n        a = 7 * a;\n        console || (a = \"FAIL\");\n        console.log(a);\n    }\n    expect: {\n        var a = 2;\n        a = a * 3 * 7;\n        console || (a = \"FAIL\");\n        console.log(a);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2187_1: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        !function(foo) {\n            foo();\n            var a = 2;\n            console.log(a);\n        }(function() {\n            console.log(a);\n        });\n    }\n    expect: {\n        var a = 1;\n        !function(foo) {\n            foo();\n            console.log(2);\n        }(function() {\n            console.log(a);\n        });\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_2187_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        console.log(function(a) {\n            return a && ++b;\n        }(b--));\n    }\n    expect: {\n        var b = 1;\n        console.log(function(a) {\n            return b-- && ++b;\n        }());\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2187_3: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        console.log(function(a) {\n            return a && ++b;\n        }(b--));\n    }\n    expect: {\n        var b = 1;\n        console.log(b-- && ++b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2203_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        a = \"FAIL\";\n        console.log({\n            a: \"PASS\",\n            b: function() {\n                return function(c) {\n                    return c.a;\n                }((String, (Object, this)));\n            }\n        }.b());\n    }\n    expect: {\n        a = \"FAIL\";\n        console.log({\n            a: \"PASS\",\n            b: function() {\n                return function(c) {\n                    return c.a;\n                }((String, (Object, this)));\n            }\n        }.b());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2203_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        a = \"PASS\";\n        console.log({\n            a: \"FAIL\",\n            b: function() {\n                return function(c) {\n                    return c.a;\n                }((String, (Object, function() {\n                    return this;\n                }())));\n            }\n        }.b());\n    }\n    expect: {\n        a = \"PASS\";\n        console.log({\n            a: \"FAIL\",\n            b: function() {\n                return function(c) {\n                    return (Object, function() {\n                        return this;\n                    }()).a;\n                }(String);\n            }\n        }.b());\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_argname: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() { return \"PASS\"; }\n        console.log(function(a, a) {\n            f++;\n            return a;\n        }(\"FAIL\", f()));\n    }\n    expect: {\n        function f() { return \"PASS\"; }\n        console.log(function(a, a) {\n            f++;\n            return a;\n        }(\"FAIL\", f()));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2298: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function f() {\n                var a = undefined;\n                var undefined = a++;\n                try {\n                    !function g(b) {\n                        b[1] = \"foo\";\n                    }();\n                    console.log(\"FAIL\");\n                } catch (e) {\n                    console.log(\"PASS\");\n                }\n            }\n            f();\n        }();\n    }\n    expect: {\n        !function() {\n            (function() {\n                try {\n                    !function(b) {\n                        (void 0)[1] = \"foo\";\n                    }();\n                    console.log(\"FAIL\");\n                } catch (e) {\n                    console.log(\"PASS\");\n                }\n            })();\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2313_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        var foo = {\n            get c() {\n                a++;\n                return 42;\n            },\n            set c(c) {\n                b++;\n            },\n            d: function() {\n                this.c++;\n                if (this.c) console.log(a, b);\n            }\n        }\n        foo.d();\n    }\n    expect: {\n        var a = 0, b = 0;\n        var foo = {\n            get c() {\n                a++;\n                return 42;\n            },\n            set c(c) {\n                b++;\n            },\n            d: function() {\n                this.c++;\n                this.c && console.log(a, b);\n            }\n        }\n        foo.d();\n    }\n    expect_stdout: \"2 1\"\n}\n\nissue_2313_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = 0;\n        !function a() {\n            a && c++;\n            var a = 0;\n            a && c++;\n        }();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        !function a() {\n            a && c++;\n            var a;\n            (a = 0) && c++;\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_2319_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect: {\n        console.log(function(a) {\n            return !function() {\n                return this;\n            }();\n        }());\n    }\n    expect_stdout: \"false\"\n}\n\nissue_2319_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            \"use strict\";\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect: {\n        console.log(function(a) {\n            \"use strict\";\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect_stdout: \"false\"\n}\n\nissue_2319_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function(a) {\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect: {\n        \"use strict\";\n        console.log(function(a) {\n            return !function() {\n                return this;\n            }();\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_2365: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = a.f;\n            a.f++;\n            return b;\n        }({ f: 1 }));\n        console.log(function() {\n            var a = { f: 1 }, b = a.f;\n            a.f++;\n            return b;\n        }());\n        console.log({\n            f: 1,\n            g: function() {\n                var b = this.f;\n                this.f++;\n                return b;\n            }\n        }.g());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = a.f;\n            a.f++;\n            return b;\n        }({ f: 1 }));\n        console.log(function() {\n            var a = { f: 1 }, b = a.f;\n            a.f++;\n            return b;\n        }());\n        console.log({\n            f: 1,\n            g: function() {\n                var b = this.f;\n                this.f++;\n                return b;\n            }\n        }.g());\n    }\n    expect_stdout: [\n        \"1\",\n        \"1\",\n        \"1\",\n    ]\n}\n\nissue_2364_1: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function inc(obj) {\n            return obj.count++;\n        }\n        function foo() {\n            var first = arguments[0];\n            var result = inc(first);\n            return foo.amount = first.count, result;\n        }\n        var data = {\n            count: 0,\n        };\n        var answer = foo(data);\n        console.log(foo.amount, answer);\n    }\n    expect: {\n        function inc(obj) {\n            return obj.count++;\n        }\n        function foo() {\n            var first = arguments[0];\n            var result = inc(first);\n            return foo.amount = first.count, result;\n        }\n        var data = {\n            count: 0\n        };\n        var answer = foo(data);\n        console.log(foo.amount, answer);\n    }\n    expect_stdout: \"1 0\"\n}\n\nissue_2364_2: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function callValidate() {\n            var validate = compilation.validate;\n            var result = validate.apply(null, arguments);\n            return callValidate.errors = validate.errors, result;\n        }\n    }\n    expect: {\n        function callValidate() {\n            var validate = compilation.validate;\n            var result = validate.apply(null, arguments);\n            return callValidate.errors = validate.errors, result;\n        }\n    }\n}\n\nissue_2364_3: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function inc(obj) {\n            return obj.count++;\n        }\n        function foo(bar) {\n            var result = inc(bar);\n            return foo.amount = bar.count, result;\n        }\n        var data = {\n            count: 0,\n        };\n        var answer = foo(data);\n        console.log(foo.amount, answer);\n    }\n    expect: {\n        function inc(obj) {\n            return obj.count++;\n        }\n        function foo(bar) {\n            var result = inc(bar);\n            return foo.amount = bar.count, result;\n        }\n        var data = {\n            count: 0,\n        };\n        var answer = foo(data);\n        console.log(foo.amount, answer);\n    }\n    expect_stdout: \"1 0\"\n}\n\nissue_2364_4: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function inc(obj) {\n            return obj.count++;\n        }\n        function foo(bar, baz) {\n            var result = inc(bar);\n            return foo.amount = baz.count, result;\n        }\n        var data = {\n            count: 0,\n        };\n        var answer = foo(data, data);\n        console.log(foo.amount, answer);\n    }\n    expect: {\n        function inc(obj) {\n            return obj.count++;\n        }\n        function foo(bar, baz) {\n            var result = inc(bar);\n            return foo.amount = baz.count, result;\n        }\n        var data = {\n            count: 0,\n        };\n        var answer = foo(data, data);\n        console.log(foo.amount, answer);\n    }\n    expect_stdout: \"1 0\"\n}\n\nissue_2364_5: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        properties: true,\n        pure_getters: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f0(o, a, h) {\n            var b = 3 - a;\n            var obj = o;\n            var seven = 7;\n            var prop = 'run';\n            var t = obj[prop](b)[seven] = h;\n            return t;\n        }\n    }\n    expect: {\n        function f0(o, a, h) {\n            return o.run(3 - a)[7] = h;\n        }\n    }\n}\n\nissue_2364_6: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function f(a, b) {\n            var c = a.p;\n            b.p = \"FAIL\";\n            return c;\n        }\n        var o = {\n            p: \"PASS\"\n        }\n        console.log(f(o, o));\n    }\n    expect: {\n        function f(a, b) {\n            var c = a.p;\n            b.p = \"FAIL\";\n            return c;\n        }\n        var o = {\n            p: \"PASS\"\n        }\n        console.log(f(o, o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2364_7: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function f(a, b) {\n            var c = a.p;\n            b.f();\n            return c;\n        }\n        var o = {\n            p: \"PASS\",\n            f: function() {\n                this.p = \"FAIL\";\n            }\n        }\n        console.log(f(o, o));\n    }\n    expect: {\n        function f(a, b) {\n            var c = a.p;\n            b.f();\n            return c;\n        }\n        var o = {\n            p: \"PASS\",\n            f: function() {\n                this.p = \"FAIL\";\n            }\n        }\n        console.log(f(o, o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2364_8: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function f(a, b, c) {\n            var d = a[b.f = function() {\n                return \"PASS\";\n            }];\n            return c.f(d);\n        }\n        var o = {\n            f: function() {\n                return \"FAIL\";\n            }\n        };\n        console.log(f({}, o, o));\n    }\n    expect: {\n        function f(a, b, c) {\n            var d = a[b.f = function() {\n                return \"PASS\";\n            }];\n            return c.f(d);\n        }\n        var o = {\n            f: function() {\n                return \"FAIL\";\n            }\n        };\n        console.log(f({}, o, o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2364_9: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function f(a, b) {\n            var d = a();\n            return b.f(d);\n        }\n        var o = {\n            f: function() {\n                return \"FAIL\";\n            }\n        };\n        console.log(f(function() {\n            o.f = function() {\n                return \"PASS\";\n            };\n        }, o));\n    }\n    expect: {\n        function f(a, b) {\n            var d = a();\n            return b.f(d);\n        }\n        var o = {\n            f: function() {\n                return \"FAIL\";\n            }\n        };\n        console.log(f(function() {\n            o.f = function() {\n                return \"PASS\";\n            };\n        }, o));\n    }\n    expect_stdout: \"PASS\"\n}\n\npure_getters_chain: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        unused: true,\n    }\n    input: {\n        function o(t, r) {\n            var a = t[1], s = t[2], o = t[3], i = t[5];\n            return a <= 23 && s <= 59 && o <= 59 && (!r || i);\n        }\n        console.log(o([ , 23, 59, 59, , 42], 1));\n    }\n    expect: {\n        function o(t, r) {\n            return t[1] <= 23 && t[2] <= 59 && t[3] <= 59 && (!r || t[5]);\n        }\n        console.log(o([ , 23, 59, 59, , 42], 1));\n    }\n    expect_stdout: \"42\"\n}\n\nconditional_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            var c = \"\";\n            var d = b ? \">\" : \"<\";\n            if (a) c += \"=\";\n            return c += d;\n        }\n        console.log(f(0, 0), f(0, 1), f(1, 0), f(1, 1));\n    }\n    expect: {\n        function f(a, b) {\n            var c = \"\";\n            if (a) c += \"=\";\n            return c += b ? \">\" : \"<\";\n        }\n        console.log(f(0, 0), f(0, 1), f(1, 0), f(1, 1));\n    }\n    expect_stdout: \"< > =< =>\"\n}\n\nconditional_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            var c = a + 1, d = a + 2;\n            return b ? c : d;\n        }\n        console.log(f(3, 0), f(4, 1));\n    }\n    expect: {\n        function f(a, b) {\n            return b ? a + 1 : a + 2;\n        }\n        console.log(f(3, 0), f(4, 1));\n    }\n    expect_stdout: \"5 5\"\n}\n\nissue_2425_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 8;\n        (function(b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect: {\n        var a = 8;\n        (function(b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2425_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 8;\n        (function(b, c) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect: {\n        var a = 8;\n        (function(b, c) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2425_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 8;\n        (function(b, b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect: {\n        var a = 8;\n        (function(b, b) {\n            (a |= 10).toString();\n        })(--a);\n        console.log(a);\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2437_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        if_return: true,\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            return bar();\n        }\n        function bar() {\n            if (xhrDesc) {\n                var req = new XMLHttpRequest();\n                var result = !!req.onreadystatechange;\n                Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});\n                return result;\n            } else {\n                var req = new XMLHttpRequest();\n                var detectFunc = function(){};\n                req.onreadystatechange = detectFunc;\n                var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;\n                req.onreadystatechange = null;\n                return result;\n            }\n        }\n        console.log(foo());\n    }\n    expect: {\n        var req, detectFunc, result;\n        console.log((\n            xhrDesc ? (result = !!(req = new XMLHttpRequest).onreadystatechange,\n                Object.defineProperty(XMLHttpRequest.prototype, \"onreadystatechange\", xhrDesc||{})\n            ) : (\n                (req = new XMLHttpRequest).onreadystatechange = detectFunc = function(){},\n                result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,\n                req.onreadystatechange = null\n            ),\n            result\n        ));\n    }\n}\n\nissue_2437_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        inline: true,\n        join_vars: true,\n        negate_iife: true,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            bar();\n        }\n        function bar() {\n            if (xhrDesc) {\n                var req = new XMLHttpRequest();\n                var result = !!req.onreadystatechange;\n                Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});\n                return result;\n            } else {\n                var req = new XMLHttpRequest();\n                var detectFunc = function(){};\n                req.onreadystatechange = detectFunc;\n                var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;\n                req.onreadystatechange = null;\n                return result;\n            }\n        }\n        foo();\n    }\n    expect: {\n        var req;\n        xhrDesc ? (\n            (req = new XMLHttpRequest).onreadystatechange,\n            Object.defineProperty(XMLHttpRequest.prototype, \"onreadystatechange\", xhrDesc || {})\n        ) : (\n            (req = new XMLHttpRequest).onreadystatechange = function(){},\n            req[SYMBOL_FAKE_ONREADYSTATECHANGE_1],\n            req.onreadystatechange = null\n        );\n    }\n}\n\nissue_2436_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log({\n            x: o.a,\n            y: o.b,\n        });\n    }\n    expect_stdout: true\n}\n\nissue_2436_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            o.a = 3;\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            o.a = 3;\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect_stdout: true\n}\n\nissue_2436_3: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            o = {\n                a: 3,\n                b: 4,\n            };\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        console.log(function(c) {\n            ({\n                a: 3,\n                b: 4,\n            });\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }({\n            a: 1,\n            b: 2,\n        }));\n    }\n    expect_stdout: true\n}\n\nissue_2436_4: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            return {\n                x: c.a,\n                y: c.b,\n            };\n            var o;\n        }(o));\n    }\n    expect: {\n        console.log({\n            x: (c = {\n            a: 1,\n            b: 2,\n        }).a,\n            y: c.b,\n        });\n        var c;\n    }\n    expect_stdout: true\n}\n\nissue_2436_5: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(o) {\n            return {\n                x: o.a,\n                y: o.b,\n            };\n        }(o));\n    }\n    expect: {\n        console.log(function(o) {\n            return {\n                x: o.a,\n                y: o.b,\n            };\n        }({\n            a: 1,\n            b: 2,\n        }));\n    }\n    expect_stdout: true\n}\n\nissue_2436_6: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        console.log({\n            x: 1,\n            y: 2,\n        });\n    }\n    expect_stdout: true\n}\n\nissue_2436_7: {\n    options = {\n        collapse_vars: true,\n        hoist_props: true,\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(function(c) {\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        console.log({\n            x: 1,\n            y: 2,\n        });\n    }\n    expect_stdout: true\n}\n\nissue_2436_8: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(c) {\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        console.log({\n            x: (c = o).a,\n            y: c.b,\n        });\n        var c;\n    }\n    expect_stdout: true\n}\n\nissue_2436_9: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = console;\n        console.log(function(c) {\n            return {\n                x: c.a,\n                y: c.b,\n            };\n        }(o));\n    }\n    expect: {\n        var o = console;\n        console.log({\n            x: o.a,\n            y: o.b,\n        });\n    }\n    expect_stdout: true\n}\n\nissue_2436_10: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        pure_getters: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        function f(n) {\n            o = { b: 3 };\n            return n;\n        }\n        console.log(function(c) {\n            return [\n                c.a,\n                f(c.b),\n                c.b,\n            ];\n        }(o).join(\" \"));\n    }\n    expect: {\n        function f(n) {\n            ({ b: 3 });\n            return n;\n        }\n        console.log([\n            (c = {\n                a: 1,\n                b: 2,\n            }).a,\n            f(c.b),\n            c.b,\n        ].join(\" \"));\n        var c;\n    }\n    expect_stdout: \"1 2 2\"\n}\n\nissue_2436_11: {\n    options = {\n        collapse_vars: true,\n        join_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function matrix() {}\n        function isCollection() {}\n        function _randomDataForMatrix() {}\n        function _randomInt() {}\n        function f(arg1, arg2) {\n            if (isCollection(arg1)) {\n                var size = arg1;\n                var max = arg2;\n                var min = 0;\n                var res = _randomDataForMatrix(size.valueOf(), min, max, _randomInt);\n                return size && true === size.isMatrix ? matrix(res) : res;\n            } else {\n                var min = arg1;\n                var max = arg2;\n                return _randomInt(min, max);\n            }\n        }\n    }\n    expect: {\n        function matrix() {}\n        function isCollection() {}\n        function _randomDataForMatrix() {}\n        function _randomInt() {}\n        function f(arg1, arg2) {\n            if (isCollection(arg1)) {\n                var size = arg1, max = arg2, min = 0, res = _randomDataForMatrix(size.valueOf(), min, max, _randomInt);\n                return size && true === size.isMatrix ? matrix(res) : res;\n            } else\n                return _randomInt(min = arg1, max = arg2);\n        }\n    }\n}\n\nissue_2436_12: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function isUndefined() {}\n        function f() {\n            var viewValue = this.$$lastCommittedViewValue;\n            var modelValue = viewValue;\n            return isUndefined(modelValue) ? modelValue : null;\n        }\n    }\n    expect: {\n        function isUndefined() {}\n        function f() {\n            var modelValue = this.$$lastCommittedViewValue;\n            return isUndefined(modelValue) ? modelValue : null;\n        }\n    }\n}\n\nissue_2436_13: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            function f(b) {\n                (function g(b) {\n                    var b = b && (b.null = \"FAIL\");\n                })(a);\n            }\n            f();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            (function(b) {\n                (function(b) {\n                    a && (a.null = \"FAIL\");\n                })();\n            })();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2436_14: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        var b = {};\n        (function() {\n            var c = a;\n            c && function(c, d) {\n                console.log(c, d);\n            }(b, c);\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        var b = {};\n        (function() {\n            a && function(c, d) {\n                console.log(b, d);\n            }(0, a);\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_2497: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function sample() {\n            if (true) {\n                for (var i = 0; i < 1; ++i) {\n                    for (var k = 0; k < 1; ++k) {\n                        var value = 1;\n                        var x = value;\n                        value = x ? x + 1 : 0;\n                    }\n                }\n            } else {\n                for (var i = 0; i < 1; ++i) {\n                    for (var k = 0; k < 1; ++k) {\n                        var value = 1;\n                    }\n                }\n            }\n        }\n    }\n    expect: {\n        function sample() {\n            if (true)\n                for (var i = 0; i < 1; ++i)\n                    for (var k = 0; k < 1; ++k)\n                        value = (value = 1) ? value + 1 : 0;\n            else\n                for (i = 0; i < 1; ++i)\n                    for (k = 0; k < 1; ++k)\n                        var value = 1;\n        }\n    }\n}\n\nissue_2506: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        function f0(bar) {\n            function f1(Infinity_2) {\n                function f13(NaN) {\n                    if (false <= NaN & this >> 1 >= 0) {\n                        c++;\n                    }\n                }\n                var b_2 = f13(NaN, c++);\n            }\n            var bar = f1(-3, -1);\n        }\n        f0(false);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        function f0(bar) {\n            (function(Infinity_2) {\n                (function(NaN) {\n                    if (false <= 0/0 & this >> 1 >= 0)\n                        c++;\n                })(0, c++);\n            })();\n        }\n        f0(false);\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2571_1: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1;\n        try {\n            var a = function f0(c) {\n                throw c;\n            }(2);\n            var d = --b + a;\n        } catch (e) {\n        }\n        console.log(b);\n    }\n    expect: {\n        var b = 1;\n        try {\n            var a = function f0(c) {\n                throw c;\n            }(2);\n            var d = --b + a;\n        } catch (e) {\n        }\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2571_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            var a = A, b = 1;\n            throw a;\n        } catch (e) {\n            console.log(b);\n        }\n    }\n    expect: {\n        try {\n            var a = A, b = 1;\n            throw a;\n        } catch (e) {\n            console.log(b);\n        }\n    }\n    expect_stdout: \"undefined\"\n}\n\nmay_throw_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f() {\n            var a_2 = function() {\n                var a;\n            }();\n        }\n    }\n    expect: {\n        function f() {\n            var a_2 = function() {\n                var a;\n            }();\n        }\n    }\n}\n\nmay_throw_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(b) {\n            try {\n                var a = x();\n                ++b;\n                return b(a);\n            } catch (e) {}\n            console.log(b);\n        }\n        f(0);\n    }\n    expect: {\n        function f(b) {\n            try {\n                var a = x();\n                return (++b)(a);\n            } catch (e) {}\n            console.log(b);\n        }\n        f(0);\n    }\n    expect_stdout: \"0\"\n}\n\nside_effect_free_replacement: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var b;\n        (function(a) {\n            x(a);\n        })(b);\n    }\n    expect: {\n        var b;\n        x(b);\n    }\n}\n\nrecursive_function_replacement: {\n    rename = true\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        function f(a) {\n            return x(g(a));\n        }\n        function g(a) {\n            return y(f(a));\n        }\n        console.log(f(c));\n    }\n    expect: {\n        console.log(function n(o) {\n            return x(y(n(o)));\n        }(c));\n    }\n}\n\ncascade_conditional: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            (a = x(), a) ? a++ : (b = y(a), b(a));\n        }\n    }\n    expect: {\n        function f(a, b) {\n            (a = x()) ? a++ : (b = y(a))(a);\n        }\n    }\n}\n\ncascade_if_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        if (a = x(), a)\n            if (a == y()) z();\n    }\n    expect: {\n        var a;\n        if (a = x())\n            if (a == y()) z();\n    }\n}\n\ncascade_if_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            if (a(), b = x()) return b;\n        }\n    }\n    expect: {\n        function f(a, b) {\n            if (a(), b = x()) return b;\n        }\n    }\n}\n\ncascade_return: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f(a) {\n            return a = x();\n            return a;\n        }\n    }\n    expect: {\n        function f(a) {\n            return a = x();\n            return a;\n        }\n    }\n}\n\ncascade_switch: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            switch(a = x(), a) {\n              case a = x(), b(a):\n                break;\n            }\n        }\n    }\n    expect: {\n        function f(a, b) {\n            switch(a = x()) {\n              case b(a = x()):\n                break;\n            }\n        }\n    }\n}\n\ncascade_call: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return x((b = a, y(b)));\n        }\n    }\n    expect: {\n        function f(a) {\n            return x(y(a));\n        }\n    }\n}\n\nreplace_all_var: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            var b = b || c && c[a = \"FAIL\"], c = a;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            var b = b || c && c[a = \"FAIL\"], c = a;\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nreplace_all_var_scope: {\n    rename = true\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var a = 100, b = 10;\n        (function(r, a) {\n            switch (~a) {\n              case (b += a):\n              case a++:\n            }\n        })(--b, a);\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        (function(c, o) {\n            switch (~a) {\n              case (b += a):\n              case o++:\n            }\n        })(--b, a);\n        console.log(a, b);\n    }\n    expect_stdout: \"100 109\"\n}\n\ncascade_statement: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            var c;\n            if (a)\n                return c = b, c || a;\n            else\n                c = a, c(b);\n        }\n        function f2(a, b) {\n            var c;\n            while (a)\n                c = b, a = c + b;\n            do\n                throw c = a + b, c;\n            while (c);\n        }\n        function f3(a, b) {\n            for (; a < b; a++)\n                if (c = a, c && b)\n                    var c = (c = b(a), c);\n        }\n    }\n    expect: {\n        function f1(a, b) {\n            var c;\n            if (a)\n                return (c = b) || a;\n            else\n                (c = a)(b);\n        }\n        function f2(a, b) {\n            var c;\n            while (a)\n                a = (c = b) + b;\n            do\n                throw c = a + b;\n            while (c);\n        }\n        function f3(a, b) {\n            for (; a < b; a++)\n                if ((c = a) && b)\n                    var c = c = b(a);\n        }\n    }\n}\n\ncascade_forin: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            return [ b, b, b ];\n        }\n        for (var c in a = console, f(a))\n            console.log(c);\n    }\n    expect: {\n        var a;\n        function f(b) {\n            return [ b, b, b ];\n        }\n        for (var c in f(a = console))\n            console.log(c);\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n        \"2\",\n    ]\n}\n\nunsafe_builtin_1: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b = Math.abs(a);\n            return Math.pow(b, 2);\n        }\n        console.log(f(-1), f(2));\n    }\n    expect: {\n        function f(a) {\n            return Math.pow(Math.abs(a), 2);\n        }\n        console.log(f(-1), f(2));\n    }\n    expect_stdout: \"1 4\"\n}\n\nunsafe_builtin_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a = A;\n        console.log(a);\n    }\n    expect: {\n        console.log(A = \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nunsafe_builtin_3: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        A = \"PASS\";\n        (function() {\n            var a = A;\n            console.log(a);\n        })();\n    }\n    expect: {\n        A = \"PASS\";\n        (function() {\n            console.log(A);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nreturn_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var log = console.log;\n        function f(b, c) {\n            var a = c;\n            if (b) return b;\n            log(a);\n        }\n        f(false, 1);\n        f(true, 2);\n    }\n    expect: {\n        var log = console.log;\n        function f(b, c) {\n            if (b) return b;\n            log(c);\n        }\n        f(false, 1);\n        f(true, 2);\n    }\n    expect_stdout: \"1\"\n}\n\nreturn_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var log = console.log;\n        function f(b, c) {\n            var a = c();\n            if (b) return b;\n            log(a);\n        }\n        f(false, function() { return 1 });\n        f(true, function() { return 2 });\n    }\n    expect: {\n        var log = console.log;\n        function f(b, c) {\n            var a = c();\n            if (b) return b;\n            log(a);\n        }\n        f(false, function() { return 1 });\n        f(true, function() { return 2 });\n    }\n    expect_stdout: \"1\"\n}\n\nreturn_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var log = console.log;\n        function f(b, c) {\n            var a = b <<= c;\n            if (b) return b;\n            log(a);\n        }\n        f(false, 1);\n        f(true, 2);\n    }\n    expect: {\n        var log = console.log;\n        function f(b, c) {\n            var a = b <<= c;\n            if (b) return b;\n            log(a);\n        }\n        f(false, 1);\n        f(true, 2);\n    }\n    expect_stdout: \"0\"\n}\n\nreturn_4: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b) {\n            a = \"PASS\";\n            return;\n            b(a);\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function(b) {\n            a = \"PASS\";\n            return;\n            b(a);\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2858: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var b;\n        (function() {\n            function f() {\n                a++;\n            }\n            f();\n            var c = f();\n            var a = void 0;\n            c || (b = a);\n        })();\n        console.log(b);\n    }\n    expect: {\n        var b;\n        (function() {\n            function f() {\n                a++;\n            }\n            f();\n            var c = f();\n            var a = void 0;\n            c || (b = a);\n        })();\n        console.log(b);\n    }\n    expect_stdout: \"undefined\"\n}\n\ncond_branch_1: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        function f1(b, c) {\n            var log = console.log;\n            var a = ++c;\n            if (b) b++;\n            log(a, b);\n        }\n        function f2(b, c) {\n            var log = console.log;\n            var a = ++c;\n            b && b++;\n            log(a, b);\n        }\n        function f3(b, c) {\n            var log = console.log;\n            var a = ++c;\n            b ? b++ : b--;\n            log(a, b);\n        }\n        f1(1, 2);\n        f2(3, 4);\n        f3(5, 6);\n    }\n    expect: {\n        function f1(b, c) {\n            if (b) b++;\n            (0, console.log)(++c, b);\n        }\n        function f2(b, c) {\n            b && b++,\n            (0, console.log)(++c, b);\n        }\n        function f3(b, c) {\n            b ? b++ : b--,\n            (0, console.log)(++c, b);\n        }\n        f1(1, 2),\n        f2(3, 4),\n        f3(5, 6);\n    }\n    expect_stdout: [\n        \"3 2\",\n        \"5 4\",\n        \"7 6\",\n    ]\n}\n\ncond_branch_2: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        function f1(b, c) {\n            var log = console.log;\n            var a = ++c;\n            if (b) b += a;\n            log(a, b);\n        }\n        function f2(b, c) {\n            var log = console.log;\n            var a = ++c;\n            b && (b += a);\n            log(a, b);\n        }\n        function f3(b, c) {\n            var log = console.log;\n            var a = ++c;\n            b ? b += a : b--;\n            log(a, b);\n        }\n        f1(1, 2);\n        f2(3, 4);\n        f3(5, 6);\n    }\n    expect: {\n        function f1(b, c) {\n            var a = ++c;\n            if (b) b += a;\n            (0, console.log)(a, b);\n        }\n        function f2(b, c) {\n            var a = ++c;\n            b && (b += a),\n            (0, console.log)(a, b);\n        }\n        function f3(b, c) {\n            var a = ++c;\n            b ? b += a : b--,\n            (0, console.log)(a, b);\n        }\n        f1(1, 2),\n        f2(3, 4),\n        f3(5, 6);\n    }\n    expect_stdout: [\n        \"3 4\",\n        \"5 8\",\n        \"7 12\",\n    ]\n}\n\ncond_branch_switch: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = 0;\n        if (c = 1 + c, 0) switch (c = 1 + c) {\n        }\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        if (c = 1 + c, 0) switch (c = 1 + c) {\n        }\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2873_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var b = 1, c = 0;\n        do {\n            c++;\n            if (!--b) break;\n            c = 1 + c;\n        } while (0);\n        console.log(b, c);\n    }\n    expect: {\n        var b = 1, c = 0;\n        do {\n            c++;\n            if (!--b) break;\n            c = 1 + c;\n        } while (0);\n        console.log(b, c);\n    }\n    expect_stdout: \"0 1\"\n}\n\nissue_2873_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var b = 1, c = 0;\n        do {\n            c++;\n            if (!--b) continue;\n            c = 1 + c;\n        } while (0);\n        console.log(b, c);\n    }\n    expect: {\n        var b = 1, c = 0;\n        do {\n            c++;\n            if (!--b) continue;\n            c = 1 + c;\n        } while (0);\n        console.log(b, c);\n    }\n    expect_stdout: \"0 1\"\n}\n\nissue_2878: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n    }\n    input: {\n        var c = 0;\n        (function(a, b) {\n            function f2() {\n                if (a) c++;\n            }\n            b = f2();\n            a = 1;\n            b && b.b;\n            f2();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(a, b) {\n            function f2() {\n                if (a) c++;\n            }\n            b = f2(),\n            a = 1,\n            b && b.b,\n            f2();\n        })(),\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2891_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        try {\n            b = c.p = 0;\n            a = \"FAIL\";\n            b();\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\", b;\n        try {\n            b = c.p = 0;\n            a = \"FAIL\";\n            b();\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2891_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"PASS\", b;\n        try {\n            b = c = 0;\n            a = \"FAIL\";\n            b();\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"PASS\", b;\n        try {\n            b = c = 0;\n            a = \"FAIL\";\n            b();\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\nissue_2908: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        function f(c) {\n            if (1 == c) return;\n            a++;\n            if (2 == c) b = a;\n        }\n        f(0);\n        f(2);\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b = 0;\n        function f(c) {\n            if (1 == c) return;\n            a++;\n            if (2 == c) b = a;\n        }\n        f(0);\n        f(2);\n        console.log(b);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2914_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function read(input) {\n            var i = 0;\n            var e = 0;\n            var t = 0;\n            while (e < 32) {\n                var n = input[i++];\n                t |= (127 & n) << e;\n                if (0 === (128 & n))\n                    return t;\n                e += 7;\n            }\n        }\n        console.log(read([129]));\n    }\n    expect: {\n        function read(input) {\n            var i = 0;\n            var e = 0;\n            var t = 0;\n            while (e < 32) {\n                var n = input[i++];\n                t |= (127 & n) << e;\n                if (0 === (128 & n))\n                    return t;\n                e += 7;\n            }\n        }\n        console.log(read([129]));\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2914_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function read(input) {\n            var i = 0;\n            var e = 0;\n            var t = 0;\n            while (e < 32) {\n                var n = input[i++];\n                t = (127 & n) << e;\n                if (0 === (128 & n))\n                    return t;\n                e += 7;\n            }\n        }\n        console.log(read([129]));\n    }\n    expect: {\n        function read(input) {\n            var i = 0;\n            var e = 0;\n            var t = 0;\n            while (e < 32) {\n                var n = input[i++];\n                if (0 === (128 & n))\n                    return t = (127 & n) << e;\n                e += 7;\n            }\n        }\n        console.log(read([129]));\n    }\n    expect_stdout: \"0\"\n}\n\nissue_805: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            function Foo(){}\n            Foo.prototype = {};\n            Foo.prototype.bar = 42;\n            return Foo;\n        }\n    }\n    expect: {\n        function f() {\n            function Foo(){}\n            (Foo.prototype = {}).bar = 42;\n            return Foo;\n        }\n    }\n}\n\nissue_2931: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = function() {\n                return;\n            }();\n            return a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return function() {\n                return;\n            }();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_2954_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        try {\n            do {\n                b = function() {\n                    throw 0;\n                }();\n                a = \"FAIL\";\n                b && b.c;\n            } while (0);\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\", b;\n        try {\n            do {\n                b = function() {\n                    throw 0;\n                }();\n                a = \"FAIL\";\n                b && b.c;\n            } while (0);\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2954_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL_1\", b;\n        try {\n            throw 0;\n        } catch (e) {\n            do {\n                b = function() {\n                    throw new Error(\"PASS\");\n                }();\n                a = \"FAIL_2\";\n                b && b.c;\n            } while (0);\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL_1\", b;\n        try {\n            throw 0;\n        } catch (e) {\n            do {\n                a = \"FAIL_2\";\n                (b = function() {\n                    throw new Error(\"PASS\");\n                }()) && b.c;\n            } while (0);\n        }\n        console.log(a);\n    }\n    expect_stdout: Error(\"PASS\")\n}\n\nissue_2954_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL_1\", b;\n        try {\n        } finally {\n            do {\n                b = function() {\n                    throw new Error(\"PASS\");\n                }();\n                a = \"FAIL_2\";\n                b && b.c;\n            } while (0);\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL_1\", b;\n        try {\n        } finally {\n            do {\n                a = \"FAIL_2\";\n                (b = function() {\n                    throw new Error(\"PASS\");\n                }()) && b.c;\n            } while (0);\n        }\n        console.log(a);\n    }\n    expect_stdout: Error(\"PASS\")\n}\n\ncollapse_rhs_conditional_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\", b = \"FAIL\";\n        b = a;\n        \"function\" == typeof f && f(a);\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"PASS\", b = \"FAIL\";\n        b = a;\n        \"function\" == typeof f && f(a);\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\ncollapse_rhs_conditional_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\", b;\n        while ((a = \"PASS\", --b) && \"PASS\" == b);\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"FAIL\", b;\n        while ((a = \"PASS\", --b) && \"PASS\" == b);\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS NaN\"\n}\n\ncollapse_rhs_lhs_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = 0;\n        new function() {\n            this[c++] = 1;\n            c += 1;\n        }();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        new function() {\n            this[c++] = 1;\n            c += 1;\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\ncollapse_rhs_lhs_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var b = 1;\n        (function f(f) {\n            f = b;\n            f[b] = 0;\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        var b = 1;\n        (function f(f) {\n            b[b] = 0;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_rhs_loop: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var s;\n        s = \"<tpl>PASS</tpl>\";\n        for (var m, r = /<tpl>(.*)<\\/tpl>/; m = s.match(r);)\n            s = s.replace(m[0], m[1]);\n        console.log(s);\n    }\n    expect: {\n        var s;\n        s = \"<tpl>PASS</tpl>\";\n        for (var m, r = /<tpl>(.*)<\\/tpl>/; m = s.match(r);)\n            s = s.replace(m[0], m[1]);\n        console.log(s);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_rhs_side_effects: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1, c = 0;\n        new function f() {\n            this[a-- && f()] = 1;\n            c += 1;\n        }();\n        console.log(c);\n    }\n    expect: {\n        var a = 1, c = 0;\n        new function f() {\n            this[a-- && f()] = 1;\n            c += 1;\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\ncollapse_rhs_vardef: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b = 1;\n        a = --b + function c() {\n            var b;\n            c[--b] = 1;\n        }();\n        b |= a;\n        console.log(a, b);\n    }\n    expect: {\n        var a, b = 1;\n        a = --b + function c() {\n            var b;\n            c[--b] = 1;\n        }();\n        b |= a;\n        console.log(a, b);\n    }\n    expect_stdout: \"NaN 0\"\n}\n\ncollapse_rhs_array: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = [];\n            b = [];\n            return [];\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            a = [];\n            b = [];\n            return [];\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"false false false\"\n}\n\ncollapse_rhs_boolean_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = !0;\n            b = !0;\n            return !0;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            return b = a = !0;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"true true true\"\n}\n\ncollapse_rhs_boolean_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n    }\n    input: {\n        var a;\n        (function f1() {\n            a = function() {};\n            if (/foo/)\n                console.log(typeof a);\n        })();\n        console.log(function f2() {\n            a = [];\n            return !1;\n        }());\n    }\n    expect: {\n        var a;\n        (function f1() {\n            if (a = function() {})\n                console.log(typeof a);\n        })();\n        console.log(function f2() {\n            return !(a = []);\n        }());\n    }\n    expect_stdout: [\n        \"function\",\n        \"false\",\n    ]\n}\n\ncollapse_rhs_boolean_3: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        var a, f, g, h, i, n, s, t, x, y;\n        if (x()) {\n            n = a;\n        } else if (y()) {\n            n = f();\n        } else if (s) {\n            i = false;\n            n = g(true);\n        } else if (t) {\n            i = false;\n            n = h(true);\n        } else {\n            n = [];\n        }\n    }\n    expect: {\n        var a, f, g, h, i, n, s, t, x, y;\n        n = x() ? a : y() ? f() : s ? g(!(i = !1)) : t ? h(!(i = !1)) : [];\n    }\n}\n\ncollapse_rhs_function: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = function() {};\n            b = function() {};\n            return function() {};\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            a = function() {};\n            b = function() {};\n            return function() {};\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"false false false\"\n}\n\ncollapse_rhs_number: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = 42;\n            b = 42;\n            return 42;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            return b = a = 42;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"true true true\"\n}\n\ncollapse_rhs_object: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = {};\n            b = {};\n            return {};\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            a = {};\n            b = {};\n            return {};\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"false false false\"\n}\n\ncollapse_rhs_regexp: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = /bar/;\n            b = /bar/;\n            return /bar/;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            a = /bar/;\n            b = /bar/;\n            return /bar/;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"false false false\"\n}\n\ncollapse_rhs_string: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = \"foo\";\n            b = \"foo\";\n            return \"foo\";\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            return b = a = \"foo\";\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"true true true\"\n}\n\ncollapse_rhs_var: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = f;\n            b = f;\n            return f;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            return b = a = f;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"true true true\"\n}\n\ncollapse_rhs_this: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = this;\n            b = this;\n            return this;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            return b = a = this;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"true true true\"\n}\n\ncollapse_rhs_undefined: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            a = void 0;\n            b = void 0;\n            return void 0;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect: {\n        var a, b;\n        function f() {\n            b = a = void 0;\n            return;\n        }\n        var c = f();\n        console.log(a === b, b === c, c === a);\n    }\n    expect_stdout: \"true true true\"\n}\n\nissue_2974: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        evaluate: true,\n        loops: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function f(b) {\n            var a = 2;\n            do {\n                b && b[b];\n                b && (b.null = -4);\n                c++;\n            } while (b.null && --a > 0);\n        })(true);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(b) {\n            var a = 2;\n            for (;c++, (!0).null && --a > 0;);\n        })(),\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3032: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        console.log({\n            f: function() {\n                this.a = 42;\n                return [ this.a, !1 ];\n            }\n        }.f()[0]);\n    }\n    expect: {\n        console.log({\n            f: function() {\n                this.a = 42;\n                return [ this.a, !1 ];\n            }\n        }.f()[0]);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3096: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var ar = [\"a\", \"b\"];\n            var first = ar.pop();\n            return ar + \"\" + first;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var ar = [\"a\", \"b\"];\n            var first = ar.pop();\n            return ar + \"\" + first;\n        }());\n    }\n    expect_stdout: \"ab\"\n}\n\nissue_3215_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        ie: false,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function a() {\n            var a = 42;\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(\"number\");\n    }\n    expect_stdout: \"number\"\n}\n\nissue_3215_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        ie: true,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function a() {\n            var a = 42;\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(function a() {\n            var a = 42;\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"number\"\n}\n\nissue_3215_3: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        ie: false,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 42;\n            (function a() {});\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(\"number\");\n    }\n    expect_stdout: \"number\"\n}\n\nissue_3215_4: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        ie: true,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 42;\n            (function a() {});\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a = 42;\n            (function a() {});\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"number\"\n}\n\nissue_3238_1: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = Object.create(null);\n                c = Object.create(null);\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = Object.create(null);\n                c = Object.create(null);\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"true false\"\n}\n\nissue_3238_2: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = Error();\n                c = Error();\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = Error();\n                c = Error();\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"true false\"\n}\n\nissue_3238_3: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = new Date();\n                c = new Date();\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = new Date();\n                c = new Date();\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"true false\"\n}\n\nissue_3238_4: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = a && {};\n                c = a && {};\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = a && {};\n                c = a && {};\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"true false\"\n}\n\nissue_3238_5: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = a ? [] : 42;\n                c = a ? [] : 42;\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = a ? [] : 42;\n                c = a ? [] : 42;\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"true false\"\n}\n\nissue_3238_6: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = a && 0 || [];\n                c = a && 0 || [];\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            var b, c;\n            if (a) {\n                b = a && 0 || [];\n                c = a && 0 || [];\n            }\n            return b === c;\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"true false\"\n}\n\nissue_3247: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f(o) {\n            console.log(o.p);\n        }\n        var a;\n        a = Object({ p: \"PASS\" });\n        a.q = true;\n        f(a, true);\n    }\n    expect: {\n        function f(o) {\n            console.log(o.p);\n        }\n        var a;\n        (a = Object({ p: \"PASS\" })).q = true;\n        f(a, true);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3305: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function calc(a) {\n            var x, w;\n            if (a) {\n                x = a;\n                w = 1;\n            } else {\n                x = 1;\n                w = 0;\n            }\n            return add(x, w);\n        }\n        function add(x, w) {\n            return x + w;\n        }\n        console.log(calc(41));\n    }\n    expect: {\n        function calc(a) {\n            var x, w;\n            return w = a ? (x = a, 1) : (x = 1, 0), add(x, w);\n        }\n        function add(x, w) {\n            return x + w;\n        }\n        console.log(calc(41));\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3314: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function test(a, b) {\n            console.log(a, b);\n        }\n        var a = \"FAIL\", b;\n        b = a = \"PASS\";\n        test(a, b);\n    }\n    expect: {\n        function test(a, b) {\n            console.log(a, b);\n        }\n        var a = \"FAIL\", b;\n        b = a = \"PASS\";\n        test(a, b);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_3327: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        var a, b, l = [\"PASS\", 42];\n        if (l.length === 1) {\n            a = l[0].a;\n            b = l[0].b;\n        } else {\n            a = l[0];\n            b = l[1];\n        }\n        function echo(a, b) {\n            console.log(a, b);\n        }\n        echo(a, b);\n    }\n    expect: {\n        var a, b, l = [\"PASS\", 42];\n        function echo(a, b) {\n            console.log(a, b);\n        }\n        b = 1 === l.length ? (a = l[0].a, l[0].b) : (a = l[0], l[1]),\n        echo(a,b);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nassign_left: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            (b = a, b.p).q = \"PASS\";\n            return a.p.q;\n        }({p: {}}));\n    }\n    expect: {\n        console.log(function(a, b) {\n            a.p.q = \"PASS\";\n            return a.p.q;\n        }({p: {}}));\n    }\n    expect_stdout: \"PASS\"\n}\n\nsub_property: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            return a[b = a, b.length - 1];\n        }([ \"FAIL\", \"PASS\" ]));\n    }\n    expect: {\n        console.log(function(a, b) {\n            return a[a.length - 1];\n        }([ \"FAIL\", \"PASS\" ]));\n    }\n    expect_stdout: \"PASS\"\n}\n\nassign_undeclared: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var A = (console.log(42), function() {});\n        B = new A();\n        console.log(typeof B);\n    }\n    expect: {\n        console.log(42);\n        B = new function() {}();\n        console.log(typeof B);\n    }\n    expect_stdout: [\n        \"42\",\n        \"object\",\n    ]\n}\n\nInfinity_assignment: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        unsafe: true,\n    }\n    input: {\n        var Infinity;\n        Infinity = 42;\n        console.log(Infinity);\n    }\n    expect: {\n        var Infinity;\n        Infinity = 42;\n        console.log(Infinity);\n    }\n    expect_stdout: true\n}\n\nissue_3439_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function(a) {\n            function a() {}\n            return a;\n        }(42));\n    }\n    expect: {\n        console.log(typeof function(a) {\n            function a() {}\n            return a;\n        }(42));\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3439_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            var a = 42;\n            function a() {}\n            return a;\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            return 42;\n        }());\n    }\n    expect_stdout: \"number\"\n}\n\ncond_sequence_return_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(n) {\n            var c = 0;\n            for (var k in [0, 1])\n                if (c++, k == n) return c;\n        }(1));\n    }\n    expect: {\n        console.log(function(n) {\n            var c = 0;\n            for (var k in [0, 1])\n                if (c++, k == n) return c;\n        }(1));\n    }\n    expect_stdout: \"2\"\n}\n\ncond_sequence_return_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(n) {\n            var c = 0;\n            for (var k in [0, 1])\n                if (c += 1, k == n) return c;\n        }(1));\n    }\n    expect: {\n        console.log(function(n) {\n            var c = 0;\n            for (var k in [0, 1])\n                if (c += 1, k == n) return c;\n        }(1));\n    }\n    expect_stdout: \"2\"\n}\n\nissue_3520: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        var b = function(c) {\n            for (var i = 2; --i >= 0;) {\n                (function f() {\n                    c = 0;\n                    var i = void 0;\n                    var f = f && f[i];\n                })();\n                a += b;\n                c && b++;\n            }\n        }(b = 1);\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        var b = function(c) {\n            for (var i = 2; --i >= 0;) {\n                (function() {\n                    c = 0;\n                    var f = f && f[void 0];\n                })();\n                a += b;\n                c && b++;\n            }\n        }(b = 1);\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_3526_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var b = function() {\n            this.a = \"FAIL\";\n        }();\n        var a = \"PASS\";\n        var b;\n        var c = b;\n        console.log(a);\n    }\n    expect: {\n        var b = function() {\n            this.a = \"FAIL\";\n        }();\n        var a = \"PASS\";\n        var b;\n        var c = b;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3526_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f() {\n            this.a = \"FAIL\";\n        }\n        var b = f();\n        var a = \"PASS\";\n        var b;\n        var c = b;\n        console.log(a);\n    }\n    expect: {\n        function f() {\n            this.a = \"FAIL\";\n        }\n        var b = f();\n        var a = \"PASS\";\n        var b;\n        var c = b;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3562: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(a) {\n            console.log(\"PASS\", a);\n        }\n        function g(b) {\n            console.log(\"FAIL\", b);\n        }\n        var h;\n        var c;\n        if (console) {\n            h = f;\n            c = \"PASS\";\n        } else {\n            h = g;\n            c = \"FAIL\";\n        }\n        h(c);\n    }\n    expect: {\n        function f(a) {\n            console.log(\"PASS\", a);\n        }\n        function g(b) {\n            console.log(\"FAIL\", b);\n        }\n        var h;\n        var c;\n        c = console ? (h = f, \"PASS\") : (h = g, \"FAIL\"),\n        h(c);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\ndot_throw_assign_sequence: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            var b;\n            b[0] = (a = \"PASS\", 0);\n            a = 1 + a;\n        } catch (c) {\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            var b;\n            b[0] = (a = \"PASS\", 0);\n            a = 1 + a;\n        } catch (c) {\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncall_assign_order: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b = 1, c = 0, log = console.log;\n        (function() {\n            a = b = \"PASS\";\n        })((b = \"FAIL\", c++));\n        log(a, b);\n    }\n    expect: {\n        var a, b = 1, c = 0, log = console.log;\n        (function() {\n            a = b = \"PASS\";\n        })((b = \"FAIL\", c++));\n        log(a, b);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_3573: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = 0;\n        (function(b) {\n            while (--b) {\n                b = NaN;\n                switch (0 / this < 0) {\n                  case c++, false:\n                  case c++, NaN:\n                }\n            }\n        })(3);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(b) {\n            while (--b) {\n                b = NaN;\n                switch (0 / this < 0) {\n                  case c++, false:\n                  case c++, NaN:\n                }\n            }\n        })(3);\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3581_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\", b = \"FAIL\";\n        try {\n            b = \"PASS\";\n            if (a) throw 0;\n            b = 1 + b;\n            a = \"FAIL\";\n        } catch (e) {}\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"PASS\", b = \"FAIL\";\n        try {\n            b = \"PASS\";\n            if (a) throw 0;\n            b = 1 + b;\n            a = \"FAIL\";\n        } catch (e) {}\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_3581_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        (function() {\n            var a = \"PASS\", b = \"FAIL\";\n            try {\n                b = \"PASS\";\n                if (a) return;\n                b = 1 + b;\n                a = \"FAIL\";\n            } finally {\n                console.log(a, b);\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            var a = \"PASS\", b = \"FAIL\";\n            try {\n                b = \"PASS\";\n                if (a) return;\n                b = 1 + b;\n                a = \"FAIL\";\n            } finally {\n                console.log(a, b);\n            }\n        })();\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_3596: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        console.log(function f() {\n            return f[[ ][f.undefined = 42, 0]] += !1;\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            return f[[ ][f.undefined = 42, 0]] += !1;\n        }());\n    }\n    expect_stdout: \"42\"\n}\n\nlocal_value_replacement: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            (a = b) && g(a);\n        }\n        function g(c) {\n            console.log(c);\n        }\n        f(\"FAIL\", \"PASS\");\n    }\n    expect: {\n        function f(a, b) {\n            b && g(b);\n        }\n        function g(c) {\n            console.log(c);\n        }\n        f(\"FAIL\", \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\narray_in_object_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 2;\n        console.log({\n            p: [ a, a-- ],\n            q: a,\n        }.q, a);\n    }\n    expect: {\n        var a = 2;\n        console.log({\n            p: [ a, a-- ],\n            q: a,\n        }.q, a);\n    }\n    expect_stdout: \"1 1\"\n}\n\narray_in_object_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 2;\n        console.log({\n            p: [ a, (a--, 42) ],\n            q: a,\n        }.q, a);\n    }\n    expect: {\n        var a = 2;\n        console.log({\n            p: [ a, 42 ],\n            q: --a,\n        }.q, a);\n    }\n    expect_stdout: \"1 1\"\n}\n\narray_in_conditional: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1, b = 2, c;\n        console.log(c && [ b = a ], a, b);\n    }\n    expect: {\n        var a = 1, b = 2, c;\n        console.log(c && [ b = a ], a, b);\n    }\n    expect_stdout: \"undefined 1 2\"\n}\n\nobject_in_conditional: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 1, b = 2, c;\n        console.log(c && {\n            p: b = a\n        }, a, b);\n    }\n    expect: {\n        var a = 1, b = 2, c;\n        console.log(c && {\n            p: b = a\n        }, a, b);\n    }\n    expect_stdout: \"undefined 1 2\"\n}\n\nsequence_in_iife_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"foo\", b = 42;\n        (function() {\n            var c = (b = a, b);\n        })();\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"foo\", b = 42;\n        (function() {\n            var c = b = a;\n        })();\n        console.log(a, b);\n    }\n    expect_stdout: \"foo foo\"\n}\n\nsequence_in_iife_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\", b = 42;\n        (function() {\n            var c = (b = a, b);\n        })();\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"foo\", b = 42;\n        console.log(b = a, b);\n    }\n    expect_stdout: \"foo foo\"\n}\n\nsequence_in_iife_3: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\", b = 42;\n        (function() {\n            var c = (b = a, b);\n        })();\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(a, a);\n    }\n    expect_stdout: \"foo foo\"\n}\n\nretain_assign: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 42, b, c = \"FAIL\";\n        b = a;\n        b++ && (c = \"PASS\");\n        console.log(c);\n    }\n    expect: {\n        var a = 42, b, c = \"FAIL\";\n        b = a;\n        b++ && (c = \"PASS\");\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\ngetter_side_effect: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(a) {\n            var b;\n            (b = a) && {\n                get foo() {\n                    a = 0;\n                }\n            }.foo;\n            b && (c = \"PASS\");\n        })(42);\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(a) {\n            var b;\n            (b = a) && {\n                get foo() {\n                    a = 0;\n                }\n            }.foo;\n            b && (c = \"PASS\");\n        })(42);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nsetter_side_effect: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(a) {\n            var b;\n            (b = a) && ({\n                set foo(v) {\n                    a = v;\n                }\n            }.foo = 0);\n            b && (c = \"PASS\");\n        })(42);\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(a) {\n            var b;\n            (b = a) && ({\n                set foo(v) {\n                    a = v;\n                }\n            }.foo = 0);\n            b && (c = \"PASS\");\n        })(42);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nsubstitution_assign: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f1(a, b) {\n            f1 = b = a;\n            console.log(a, b);\n        }\n        function f2(a, b) {\n            a = 1 + (b = a);\n            console.log(a, b);\n        }\n        function f3(a, b) {\n            b = 1 + (b = a);\n            console.log(a, b);\n        }\n        function f4(a, b) {\n            b = 1 + (a = b);\n            console.log(a, b);\n        }\n        f1(42, \"foo\");\n        f2(42, \"foo\");\n        f3(42, \"foo\");\n        f4(\"bar\", 41);\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(f1 = a, a);\n        }\n        function f2(a, b) {\n            console.log(a = 1 + (b = a), b);\n        }\n        function f3(a, b) {\n            console.log(a, b = 1 + (b = a));\n        }\n        function f4(a, b) {\n            b = 1 + (a = b);\n            console.log(a, b);\n        }\n        f1(42, \"foo\");\n        f2(42, \"foo\");\n        f3(42, \"foo\");\n        f4(\"bar\", 41);\n    }\n    expect_stdout: [\n        \"42 42\",\n        \"43 42\",\n        \"42 43\",\n        \"41 42\",\n    ]\n}\n\nsubstitution_arithmetic: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            console.log((b = a) + a, b);\n        }\n        function f2(a, b) {\n            console.log(a - (b = a), b);\n        }\n        function f3(a, b) {\n            console.log(a / (b = a) + b, b);\n        }\n        f1(42, \"foo\");\n        f2(42, \"foo\");\n        f3(42, \"foo\");\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(a + a, a);\n        }\n        function f2(a, b) {\n            console.log(a - a, a);\n        }\n        function f3(a, b) {\n            console.log(a / a + a, a);\n        }\n        f1(42, \"foo\");\n        f2(42, \"foo\");\n        f3(42, \"foo\");\n    }\n    expect_stdout: [\n        \"84 42\",\n        \"0 42\",\n        \"43 42\",\n    ]\n}\n\nsubstitution_logical_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            console.log((b = a) && a, b);\n        }\n        function f2(a, b) {\n            console.log(a && (b = a), b);\n        }\n        f1(42, \"foo\");\n        f1(null, true);\n        f2(42, \"foo\");\n        f2(null, true);\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(a && a, a);\n        }\n        function f2(a, b) {\n            console.log(a && (b = a), b);\n        }\n        f1(42, \"foo\");\n        f1(null, true);\n        f2(42, \"foo\");\n        f2(null, true);\n    }\n    expect_stdout: [\n        \"42 42\",\n        \"null null\",\n        \"42 42\",\n        \"null true\"\n    ]\n}\n\nsubstitution_logical_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            console.log((b = a) && a && b);\n        }\n        function f2(a, b) {\n            console.log((b = a) && a || b);\n        }\n        function f3(a, b) {\n            console.log((b = a) || a && b);\n        }\n        function f4(a, b) {\n            console.log((b = a) || a || b);\n        }\n        f1(42, \"foo\");\n        f1(null, true);\n        f2(42, \"foo\");\n        f2(null, true);\n        f3(42, \"foo\");\n        f3(null, true);\n        f4(42, \"foo\");\n        f4(null, true);\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(a && a && a);\n        }\n        function f2(a, b) {\n            console.log(a && a || a);\n        }\n        function f3(a, b) {\n            console.log(a || a && a);\n        }\n        function f4(a, b) {\n            console.log(a || a || a);\n        }\n        f1(42, \"foo\");\n        f1(null, true);\n        f2(42, \"foo\");\n        f2(null, true);\n        f3(42, \"foo\");\n        f3(null, true);\n        f4(42, \"foo\");\n        f4(null, true);\n    }\n    expect_stdout: [\n        \"42\",\n        \"null\",\n        \"42\",\n        \"null\",\n        \"42\",\n        \"null\",\n        \"42\",\n        \"null\",\n    ]\n}\n\nsubstitution_logical_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            console.log(a && (b = a) && b);\n        }\n        function f2(a, b) {\n            console.log(a && (b = a) || b);\n        }\n        function f3(a, b) {\n            console.log(a || (b = a) && b);\n        }\n        function f4(a, b) {\n            console.log(a || (b = a) || b);\n        }\n        f1(42, \"foo\");\n        f1(null, true);\n        f2(42, \"foo\");\n        f2(null, true);\n        f3(42, \"foo\");\n        f3(null, true);\n        f4(42, \"foo\");\n        f4(null, true);\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(a && a && a);\n        }\n        function f2(a, b) {\n            console.log(a && (b = a) || b);\n        }\n        function f3(a, b) {\n            console.log(a || a && a);\n        }\n        function f4(a, b) {\n            console.log(a || a || a);\n        }\n        f1(42, \"foo\");\n        f1(null, true);\n        f2(42, \"foo\");\n        f2(null, true);\n        f3(42, \"foo\");\n        f3(null, true);\n        f4(42, \"foo\");\n        f4(null, true);\n    }\n    expect_stdout: [\n        \"42\",\n        \"null\",\n        \"42\",\n        \"true\",\n        \"42\",\n        \"null\",\n        \"42\",\n        \"null\",\n    ]\n}\n\nsubstitution_conditional: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            console.log((b = a) ? a : b, a, b);\n        }\n        function f2(a, b) {\n            console.log(a ? b = a : b, a, b);\n        }\n        function f3(a, b) {\n            console.log(a ? a : b = a, a, b);\n        }\n        f1(\"foo\", \"bar\");\n        f1(null, true);\n        f2(\"foo\", \"bar\");\n        f2(null, true);\n        f3(\"foo\", \"bar\");\n        f3(null, true);\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(a ? a : a, a, a);\n        }\n        function f2(a, b) {\n            console.log(a ? b = a : b, a, b);\n        }\n        function f3(a, b) {\n            console.log(a ? a : b = a, a, b);\n        }\n        f1(\"foo\", \"bar\");\n        f1(null, true);\n        f2(\"foo\", \"bar\");\n        f2(null, true);\n        f3(\"foo\", \"bar\");\n        f3(null, true);\n    }\n    expect_stdout: [\n        \"foo foo foo\",\n        \"null null null\",\n        \"foo foo foo\",\n        \"true null true\",\n        \"foo foo bar\",\n        \"null null null\",\n    ]\n}\n\nsubstitution_unary: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function f1(a, b) {\n            console.log(typeof (b = a), a, b);\n        }\n        function f2(a, b) {\n            console.log(void (b = a), a, b);\n        }\n        function f3(a, b) {\n            console.log(delete (b = a), a, b);\n        }\n        f1(42, \"foo\");\n        f2(42, \"foo\");\n        f3(42, \"foo\");\n    }\n    expect: {\n        function f1(a, b) {\n            console.log(typeof a, a, a);\n        }\n        function f2(a, b) {\n            console.log(void a, a, a);\n        }\n        function f3(a, b) {\n            console.log(delete (b = a), a, b);\n        }\n        f1(42, \"foo\");\n        f2(42, \"foo\");\n        f3(42, \"foo\");\n    }\n    expect_stdout: [\n        \"number 42 42\",\n        \"undefined 42 42\",\n        \"true 42 42\",\n    ]\n}\n\nissue_3626_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"foo\", b = 42;\n        a.p && (b = a) && a;\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"foo\", b = 42;\n        a.p && (b = a) && a;\n        console.log(a, b);\n    }\n    expect_stdout: \"foo 42\"\n}\n\nissue_3626_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n    }\n    input: {\n        var a = \"foo\", b = 42, c = null;\n        if (a && a.p)\n            if (b = a)\n                c++ + a;\n        console.log(a, b, c);\n    }\n    expect: {\n        var a = \"foo\", b = 42, c = null;\n        a && a.p && (b = a) && c++ + a;\n        console.log(a, b, c);\n    }\n    expect_stdout: \"foo 42 null\"\n}\n\nissue_3628_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"bar\", b;\n        ({\n            get p() {\n                a = \"foo\";\n            },\n            q: b = a\n        }).p;\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"bar\", b;\n        ({\n            get p() {\n                a = \"foo\";\n            },\n            q: b = a\n        }).p;\n        console.log(a, b);\n    }\n    expect_stdout: \"foo bar\"\n}\n\nissue_3628_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"bar\", b;\n        ({\n            get p() {\n                a = \"foo\";\n            },\n            q: (b = a, 42)\n        }).p;\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"bar\", b;\n        ({\n            get p() {\n                a = \"foo\";\n            },\n            q: (b = a, 42)\n        }).p;\n        console.log(a, b);\n    }\n    expect_stdout: \"foo bar\"\n}\n\nissue_3641: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        try {\n            a = \"foo\";\n            b = (a += (A.p = 0, \"bar\")) % 0;\n        } catch (e) {}\n        console.log(a, b);\n    }\n    expect: {\n        var a, b;\n        try {\n            a = \"foo\";\n            b = (a += (A.p = 0, \"bar\")) % 0;\n        } catch (e) {}\n        console.log(a, b);\n    }\n    expect_stdout: \"foo undefined\"\n}\n\nissue_3651: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = \"PASS\";\n        try {\n            a = function() {\n                try {\n                    var c = 1;\n                    while (0 < --c);\n                } catch (e) {} finally {\n                    throw 42;\n                }\n            }();\n            b = \"FAIL\";\n            a.p;\n        } catch (e) {\n            console.log(b);\n        }\n    }\n    expect: {\n        var a, b = \"PASS\";\n        try {\n            a = function() {\n                try {\n                    var c = 1;\n                    while (0 < --c);\n                } catch (e) {} finally {\n                    throw 42;\n                }\n            }();\n            b = \"FAIL\";\n            a.p;\n        } catch (e) {\n            console.log(b);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3671: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        try {\n            a++;\n            A += 0;\n            a = 1 + a;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = 0;\n        try {\n            a++;\n            A += 0;\n            a = 1 + a;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"1\"\n}\n\ncall_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        (function(a) {\n            a = console;\n            (function() {})();\n            a.log(\"PASS\");\n        })();\n    }\n    expect: {\n        (function(a) {\n            (function() {})();\n            (a = console).log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\ncall_1_symbol: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            function f() {}\n            a = console;\n            f();\n            a.log(typeof f);\n        })();\n    }\n    expect: {\n        (function(a) {\n            function f() {}\n            f();\n            (a = console).log(typeof f);\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\ncall_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        (function(a) {\n            a = console;\n            (function() {\n                return 42;\n                console.log(\"FAIL\");\n            })();\n            a.log(\"PASS\");\n        })();\n    }\n    expect: {\n        (function(a) {\n            (function() {\n                return 42;\n                console.log(\"FAIL\");\n            })();\n            (a = console).log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\ncall_2_symbol: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            function f() {\n                return 42;\n                console.log(\"FAIL\");\n            }\n            a = console;\n            f();\n            a.log(typeof f);\n        })();\n    }\n    expect: {\n        (function(a) {\n            function f() {\n                return 42;\n                console.log(\"FAIL\");\n            }\n            f();\n            (a = console).log(typeof f);\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\ncall_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        (function(a) {\n            a = console;\n            (function() {\n                a = {\n                    log: function() {\n                        console.log(\"PASS\");\n                    }\n                }\n            })();\n            a.log(\"FAIL\");\n        })();\n    }\n    expect: {\n        (function(a) {\n            a = console;\n            (function() {\n                a = {\n                    log: function() {\n                        console.log(\"PASS\");\n                    }\n                }\n            })();\n            a.log(\"FAIL\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\ncall_3_symbol: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            function f() {\n                a = {\n                    log: function() {\n                        console.log(typeof f);\n                    }\n                }\n            }\n            a = console;\n            f();\n            a.log(\"FAIL\");\n        })();\n    }\n    expect: {\n        (function(a) {\n            function f() {\n                a = {\n                    log: function() {\n                        console.log(typeof f);\n                    }\n                }\n            }\n            a = console;\n            f();\n            a.log(\"FAIL\");\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3698_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log;\n        var a, b = 0, c = 0;\n        (function() {\n            a = b;\n        })(b++, (b++, c++));\n        log(a, b, c);\n    }\n    expect: {\n        var log = console.log;\n        var a, b = 0, c = 0;\n        (function() {\n            a = b;\n        })(b++, (b++, c++));\n        log(a, b, c);\n    }\n    expect_stdout: \"2 2 1\"\n}\n\nissue_3698_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        var log = console.log;\n        var a, b = 0, c = 0, d = 1;\n        (function f() {\n            a = b;\n            d-- && f();\n        })(b++, (b++, c++));\n        log(a, b, c, d);\n    }\n    expect: {\n        var log = console.log;\n        var a, b = 0, c = 0, d = 1;\n        (function f() {\n            a = b;\n            d-- && f();\n        })(b++, (b++, c++));\n        log(a, b, c, d);\n    }\n    expect_stdout: \"2 2 1 -1\"\n}\n\nissue_3698_3: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        (function f(c) {\n            {\n                b++;\n                var bar_1 = (b = 1 + b, c = 0);\n                a-- && f();\n            }\n        })();\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b = 0;\n        (function f(c) {\n            var bar_1 = (b = 1 + ++b, c = 0);\n            a-- && f();\n        })();\n        console.log(b);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_3700: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            (function() {\n                throw 0;\n            })();\n            a = 1 + a;\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            (function() {\n                throw 0;\n            })();\n            a = 1 + a;\n        } catch (e) {\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3744: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            ({\n                get p() {\n                    switch (1) {\n                      case 0:\n                        f((a = 2, 3));\n                      case 1:\n                        console.log(function g(b) {\n                            return b || \"PASS\";\n                        }());\n                    }\n                }\n            }).p;\n        })();\n    }\n    expect: {\n        (function f(a) {\n            ({\n                get p() {\n                    switch (1) {\n                      case 0:\n                        f();\n                      case 1:\n                        console.log(b || \"PASS\");\n                    }\n                    var b;\n                }\n            }).p;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nassign_value_def: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            while (1) {\n                var b = a[0], c = a[1];\n                d = b;\n                e = c;\n                if (c[0] - e[0] > c[1] - d[1]) break;\n                return \"PASS\";\n            }\n            var d, e;\n            return \"FAIL\";\n        }\n        console.log(f([\n            [ 1, 2 ],\n            [ 3, 4 ],\n        ]));\n    }\n    expect: {\n        function f(a) {\n            while (1) {\n                var b = a[0], c = a[1];\n                if (c[0] - c[0] > c[1] - b[1]) break;\n                return \"PASS\";\n            }\n            return \"FAIL\";\n        }\n        console.log(f([\n            [ 1, 2 ],\n            [ 3, 4 ],\n        ]));\n    }\n    expect_stdout: \"PASS\"\n}\n\njoin_vars_value_def: {\n    options = {\n        collapse_vars: true,\n        join_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            while (1) {\n                var b = a[0], c = a[1];\n                d = b;\n                e = c;\n                if (c[0] - e[0] > c[1] - d[1]) break;\n                return \"PASS\";\n            }\n            var d, e;\n            return \"FAIL\";\n        }\n        console.log(f([\n            [ 1, 2 ],\n            [ 3, 4 ],\n        ]));\n    }\n    expect: {\n        function f(a) {\n            while (1) {\n                var b = a[0], c = a[1];\n                if (c[0] - c[0] > c[1] - b[1]) break;\n                return \"PASS\";\n            }\n            return \"FAIL\";\n        }\n        console.log(f([\n            [ 1, 2 ],\n            [ 3, 4 ],\n        ]));\n    }\n    expect_stdout: \"PASS\"\n}\n\nvar_value_def: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            while (1) {\n                var b = a[0], c = a[1], d = b, e = c;\n                if (c[0] - e[0] > c[1] - d[1]) break;\n                return \"PASS\";\n            }\n            var d, e;\n            return \"FAIL\";\n        }\n        console.log(f([\n            [ 1, 2 ],\n            [ 3, 4 ],\n        ]));\n    }\n    expect: {\n        function f(a) {\n            while (1) {\n                var b = a[0], c = a[1];\n                if (c[0] - c[0] > c[1] - b[1]) break;\n                return \"PASS\";\n            }\n            return \"FAIL\";\n        }\n        console.log(f([\n            [ 1, 2 ],\n            [ 3, 4 ],\n        ]));\n    }\n    expect_stdout: \"PASS\"\n}\n\nmangleable_var: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b = a(), c = a(), d = b;\n            return c.p(c, d);\n        }\n        console.log(f(function() {\n            return {\n                p: function() {\n                    return \"PASS\"\n                },\n            };\n        }));\n    }\n    expect: {\n        function f(a) {\n            var b = a(), c = a();\n            return c.p(c, b);\n        }\n        console.log(f(function() {\n            return {\n                p: function() {\n                    return \"PASS\";\n                }\n            };\n        }));\n    }\n    expect_stdout: \"PASS\"\n}\n\nmangleable_assignment_1: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            p: function() {\n                return 6;\n            },\n        };\n        (function() {\n            var a, b = a = o.p();\n            console.log(a * (b / a + b));\n        })();\n    }\n    expect: {\n        var o = {\n            p: function() {\n                return 6;\n            },\n        };\n        (function() {\n            var a;\n            a = o.p();\n            console.log(a * (a / a + a));\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nmangleable_assignment_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            p: function() {\n                return 6;\n            },\n        };\n        (function(a, b) {\n            b = a = o.p();\n            console.log(a * (b / a + b));\n        })();\n    }\n    expect: {\n        var o = {\n            p: function() {\n                return 6;\n            },\n        };\n        (function(a, b) {\n            a = o.p();\n            console.log(a * (a / a + a));\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3884_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 100, b = 1;\n        {\n            a++ + a || a;\n            b <<= a;\n        }\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100;\n        ++a;\n        console.log(a, 32);\n    }\n    expect_stdout: \"101 32\"\n}\n\nissue_3884_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        passes: 3,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 100, b = 1;\n        {\n            a++ + a || a;\n            b <<= a;\n        }\n        console.log(a, b);\n    }\n    expect: {\n        console.log(101, 32);\n    }\n    expect_stdout: \"101 32\"\n}\n\nissue_3891: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function log(a) {\n            console.log(typeof a);\n        }\n        log(function f() {\n            try {\n                do {\n                    var b = function() {}();\n                } while (f = 0, b.p);\n            } catch (e) {\n                var f;\n                b;\n            }\n        });\n    }\n    expect: {\n        function log(a) {\n            console.log(typeof a);\n        }\n        log(function() {\n            try {\n                do {} while ((void 0).p);\n            } catch (e) {}\n        });\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3894: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function log(msg) {\n            console.log(msg ? \"FAIL\" : \"PASS\");\n        }\n        var a, c;\n        (function(b) {\n            a = c = 0,\n            log(b);\n        })(-0);\n        log(a);\n        log(c);\n    }\n    expect: {\n        function log(msg) {\n            console.log(msg ? \"FAIL\" : \"PASS\");\n        }\n        var a, c;\n        void log(-(a = c = 0));\n        log(a);\n        log(c);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_3897: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            function f(b) {\n                b = a = 1 + a;\n                a = 1 + a;\n                console.log(b);\n            }\n            f();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function() {\n            function f(b) {\n                b = a = 1 + a;\n                a = 1 + a;\n                console.log(b);\n            }\n            f();\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_3908: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        if (console) {\n            var o = {\n                p: !1\n            }, a = o;\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        console && 0;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3927: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        console.log(function(b) {\n            try {\n                try {\n                    if (a + (b = \"PASS\", true)) return;\n                    b.p;\n                } finally {\n                    return b;\n                }\n            } catch (e) {\n            }\n        }());\n    }\n    expect: {\n        var a = 0;\n        console.log(function(b) {\n            try {\n                try {\n                    if (a + (b = \"PASS\", true)) return;\n                    b.p;\n                } finally {\n                    return b;\n                }\n            } catch (e) {}\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\noperator_in: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        function log(msg) {\n            console.log(msg);\n        }\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            0 in null;\n            log(\"FAIL\", a);\n        } catch (e) {}\n        log(a);\n    }\n    expect: {\n        function log(msg) {\n            console.log(msg);\n        }\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            0 in null;\n            log(\"FAIL\", a);\n        } catch (e) {}\n        log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3971: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0 == typeof f, b = 0;\n        {\n            var a = void (a++ + (b |= a));\n        }\n        console.log(b);\n    }\n    expect: {\n        var a = 0 == typeof f, b = 0;\n        var a = void (b |= ++a);\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3976: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(\"FAIL\");\n        }\n        (function(a) {\n            function g() {\n                if ((a = 0) || f(0)) {\n                    f();\n                } else {\n                    f();\n                }\n                if (h(a = 0));\n            }\n            function h() {\n                g();\n            }\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        function f() {\n            console.log(\"FAIL\");\n        }\n        void 0;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4012: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        evaluate: true,\n    }\n    input: {\n        (function(a) {\n            try {\n                throw 2;\n            } catch (b) {\n                a = \"PASS\";\n                if (--b)\n                    return;\n                if (3);\n            } finally {\n                console.log(a);\n            }\n        })();\n    }\n    expect: {\n        (function(a) {\n            try {\n                throw 2;\n            } catch (b) {\n                a = \"PASS\";\n                if (--b)\n                    return;\n                if (3);\n            } finally {\n                console.log(a);\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nglobal_assign: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        this.A = \"FAIL\";\n        A = \"PASS\";\n        B = \"FAIL\";\n        console.log(A);\n    }\n    expect: {\n        this.A = \"FAIL\";\n        A = \"PASS\";\n        B = \"FAIL\";\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n}\n\nglobal_read: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        a = this.A;\n        A = 1;\n        a ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect: {\n        var a = 0;\n        a = this.A;\n        A = 1;\n        a ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4038: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        a = this;\n        a = a.A;\n        A = 1;\n        a ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect: {\n        var a = 0;\n        a = (a = this).A;\n        A = 1;\n        a ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4040: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = console.log(\"PASS\") && a.p;\n        delete NaN;\n    }\n    expect: {\n        var a = console.log(\"PASS\") && a.p;\n        delete NaN;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4047_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        console.log(+function(a) {\n            b = a;\n            (a >>= 0) && console.log(\"PASS\");\n        }(--b + (0 !== typeof A)));\n    }\n    expect: {\n        var b = 1;\n        var a;\n        console.log((a = --b + (0 !== typeof A), +void ((a >>= 0) && console.log(\"PASS\"))));\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"NaN\",\n    ]\n}\n\nissue_4047_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        console.log(+function(a) {\n            b = a;\n            (a >>= 0) && console.log(\"PASS\");\n        }(--b + (0 !== typeof A)));\n    }\n    expect: {\n        var a;\n        console.log((a = +(0 !== typeof A), +void ((a >>= 0) && console.log(\"PASS\"))));\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"NaN\",\n    ]\n}\n\nissue_4051: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        try {\n            var a = (b = b.p, \"FAIL\"), b = b;\n        } catch (e) {}\n        console.log(a);\n    }\n    expect: {\n        try {\n            var a = (b = b.p, \"FAIL\"), b = b;\n        } catch (e) {}\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4070: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function f() {\n            function g() {}\n            g.p++;\n            return f.p = g.p;\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            function g() {}\n            return f.p = ++g.p;\n        }());\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4242: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            if (console)\n                var a = function(){}, b = (!1 === console || a)();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            console && (!1 === console || function(){})();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4248: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        try {\n            a = 1;\n            b[1];\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = 0;\n        try {\n            a = 1;\n            b[1];\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4430_1: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        function f(a) {\n            switch (a = 1, arguments[0]) {\n              case 1:\n                return \"PASS\";\n              case 2:\n                return \"FAIL\";\n            }\n        }\n        console.log(f(2));\n    }\n    expect: {\n        function f(a) {\n            switch (a = 1, arguments[0]) {\n              case 1:\n                return \"PASS\";\n              case 2:\n                return \"FAIL\";\n            }\n        }\n        console.log(f(2));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4430_2: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        function f(a) {\n            switch (a = 0, arguments[0]) {\n              case 0:\n                return \"PASS\";\n              case 1:\n                return \"FAIL\";\n            }\n        }\n        console.log(f(1));\n    }\n    expect: {\n        function f(a) {\n            switch (arguments[a = 0]) {\n              case 0:\n                return \"PASS\";\n              case 1:\n                return \"FAIL\";\n            }\n        }\n        console.log(f(1));\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_and_assign: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log;\n        var a = {\n            p: \"PASS\",\n        };\n        console && (a = a.p);\n        log(a);\n    }\n    expect: {\n        var log = console.log;\n        var a = {\n            p: \"PASS\",\n        };\n        log(a = console ? a.p : a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_and_assign_property: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {\n            f && (f.p = \"PASS\");\n            return f.p;\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            return f.p = f ? \"PASS\" : f.p;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_or_assign: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log;\n        var a = {\n            p: \"PASS\",\n        };\n        a.q || (a = a.p);\n        log(a);\n    }\n    expect: {\n        var log = console.log;\n        var a = {\n            p: \"PASS\",\n        };\n        log(a = a.q ? a: a.p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4586_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 42;\n        (function f(b) {\n            var b = a;\n            if (b === arguments[0])\n                console.log(\"PASS\");\n        })(console);\n    }\n    expect: {\n        var a = 42;\n        (function f(b) {\n            var b = a;\n            if (b === arguments[0])\n                console.log(\"PASS\");\n        })(console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4586_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 42;\n        (function f(b) {\n            b = a;\n            if (b === arguments[0])\n                console.log(\"PASS\");\n        })(console);\n    }\n    expect: {\n        var a = 42;\n        (function f(b) {\n            if ((b = a) === arguments[0])\n                console.log(\"PASS\");\n        })(console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4732_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function(b) {\n            var b = a++;\n            var c = b ? b && console.log(\"PASS\") : 0;\n        })(a++);\n    }\n    expect: {\n        var a = 0;\n        (function(b) {\n            (b = a++) && console.log(\"PASS\");\n        })(a++);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4732_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function(b) {\n            var b = a++;\n            var c = b ? b && console.log(\"PASS\") : 0;\n        })(a++);\n    }\n    expect: {\n        var a = 0;\n        (function(b) {\n            (b = a++) && b && console.log(\"PASS\");\n        })(a++);\n    }\n    expect_stdout: \"PASS\"\n}\n\ndot_in_try: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var o, a = 6, b = 7, c;\n        try {\n            c = a * b;\n            o.p(c);\n        } catch (e) {\n            console.log(c);\n        }\n    }\n    expect: {\n        var o, a = 6, b = 7, c;\n        try {\n            c = a * b;\n            o.p(c);\n        } catch (e) {\n            console.log(c);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\ndot_non_local: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var o, a = 6, b = 7, c;\n        function f() {\n            c = a * b;\n            o.p(c);\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(c);\n        }\n    }\n    expect: {\n        var o, a = 6, b = 7, c;\n        function f() {\n            c = a * b;\n            o.p(c);\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(c);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\nissue_4806: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, o = {\n            f: function() {\n                console.log(this === o ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (a = 42, o.f)(42);\n    }\n    expect: {\n        var a, o = {\n            f: function() {\n                console.log(this === o ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (0, o.f)(a = 42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4852: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(b) {\n            switch (b = a) {\n              case 42:\n                try {\n                    console;\n                } catch (b) {\n                    b.p;\n                }\n              case console.log(b):\n            }\n        })(\"FAIL\");\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b) {\n            switch (a) {\n              case 42:\n                try {\n                    console;\n                } catch (b) {\n                    b.p;\n                }\n              case console.log(a):\n            }\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4865: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var NaN;\n        var a = NaN = \"PASS\";\n        console.log(a, NaN);\n    }\n    expect: {\n        var NaN;\n        var a = NaN = \"PASS\";\n        console.log(a, NaN);\n    }\n    expect_stdout: true\n}\n\nissue_4868: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b) {\n            console.log(b[0]);\n        })(a = [ \"PASS\" ], a = [ \"FAIL\" ]);\n    }\n    expect: {\n        var a;\n        (function(b) {\n            console.log(b[0]);\n        })(a = [ \"PASS\" ], a = [ \"FAIL\" ]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4874: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        a = null;\n        (function(b) {\n            for (var c in b = b && b[console.log(\"PASS\")])\n                console;\n        })(a = 42);\n    }\n    expect: {\n        null;\n        (function(b) {\n            for (var c in 42, 42[console.log(\"PASS\")])\n                console;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4891: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b;\n        a++;\n        console.log(b = a, b);\n        b--;\n        a.a += 0;\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b;\n        a++;\n        console.log(a, b = a);\n        b--;\n        a.a += 0;\n        console.log(b);\n    }\n    expect_stdout: [\n        \"1 1\",\n        \"0\",\n    ]\n}\n\nissue_4895: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b;\n        (function f() {\n            a = 42;\n        })();\n        console.log((b = a) || b, b += 0);\n    }\n    expect: {\n        var a, b;\n        (function f() {\n            a = 42;\n        })();\n        console.log((b = a) || b, b += 0);\n    }\n    expect_stdout: \"42 42\"\n}\n\nissue_4908: {\n    options = {\n        collapse_vars: true,\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        var b;\n        console || a++;\n        var c = d = a, d = [ c && c, d += 42 ];\n        console.log(d[1]);\n    }\n    expect: {\n        var a = 0, b, c = (console || a++, a), d = [ (d = a) && d, d += 42 ];\n        console.log(d[1]);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_4910: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"foo\", b;\n        var c = b = a;\n        1 && c[a = \"bar\"];\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"foo\", b;\n        var c = b = a;\n        1 && b[a = \"bar\"];\n        console.log(a, b);\n    }\n    expect_stdout: \"bar foo\"\n}\n\nissue_4914: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        console.log(typeof function f() {\n            f.__proto__ = 42;\n            return f.__proto__;\n        }());\n    }\n    expect: {\n        console.log(typeof function f() {\n            f.__proto__ = 42;\n            return f.__proto__;\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4918: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        ({\n            get 42() {\n                console.log(a);\n            }\n        }[a = \"PASS\", 42] += \"PASS\");\n    }\n    expect: {\n        var a = \"FAIL\";\n        ({\n            get 42() {\n                console.log(a);\n            }\n        }[a = \"PASS\", 42] += \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4920_1: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        ({\n            get PASS() {\n                a = \"FAIL\";\n            },\n        })[b = a];\n        console.log(b);\n    }\n    expect: {\n        var a = \"PASS\", b;\n        ({\n            get PASS() {\n                a = \"FAIL\";\n            },\n        })[b = a];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4920_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            get PASS() {\n                a = \"FAIL\";\n            },\n        };\n        var a = \"PASS\", b;\n        o[b = a];\n        console.log(b);\n    }\n    expect: {\n        var o;\n        var a = \"PASS\", b;\n        ({\n            get PASS() {\n                a = \"FAIL\";\n            },\n        })[b = a];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4920_3: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var o = {\n            get PASS() {\n                a = \"FAIL\";\n            },\n        };\n        var a = \"PASS\", b;\n        o[b = a];\n        log(b);\n    }\n    expect: {\n        var log = console.log;\n        var o;\n        var a = \"PASS\", b;\n        ({\n            get PASS() {\n                a = \"FAIL\";\n            },\n        })[b = a];\n        log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4920_4: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var o = {\n            get [(a = \"FAIL 1\", \"PASS\")]() {\n                a = \"FAIL 2\";\n            },\n        };\n        var a = \"PASS\", b;\n        o[b = a];\n        log(b);\n    }\n    expect: {\n        var log = console.log;\n        var o = {\n            get [(a = \"FAIL 1\", \"PASS\")]() {\n                a = \"FAIL 2\";\n            },\n        };\n        var a = \"PASS\", b;\n        o[b = a];\n        log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4935: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        var b;\n        var c = b = a;\n        console || c(a++);\n        --b;\n        console.log(a, b);\n    }\n    expect: {\n        var a = 1;\n        var b;\n        var c = b = a;\n        console || a(a++);\n        --b;\n        console.log(a, b);\n    }\n    expect_stdout: \"1 0\"\n}\n\ninline_throw: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        try {\n            (function() {\n                return function(a) {\n                    return function(b) {\n                        throw b;\n                    }(a);\n                };\n            })()(\"PASS\");\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        try {\n            (function(a) {\n                throw a;\n                return;\n            })(\"PASS\");\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4977_1: {\n    options = {\n        collapse_vars: true,\n        unsafe: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var o = {\n            get p() {\n                return a;\n            }\n        };\n        a = \"PASS\";\n        console.log(o.p, a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        var o = {\n            get p() {\n                return a;\n            }\n        };\n        a = \"PASS\";\n        console.log(o.p, a);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_4977_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        var a, o = {\n            get p() {\n                return a = \"PASS\";\n            },\n        };\n        if (console) {\n            var a = \"FAIL\";\n            console.log(o.p, a);\n        }\n    }\n    expect: {\n        var a, o = {\n            get p() {\n                return a = \"PASS\";\n            },\n        };\n        if (console) {\n            var a = \"FAIL\";\n            console.log(o.p, a);\n        }\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_5112_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                try {\n                    if (console + (a = \"PASS\", \"\"))\n                        return \"FAIL 1\";\n                    a.p;\n                } catch (e) {}\n            } finally {\n                return a;\n            }\n        }(\"FAIL 2\"));\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                try {\n                    if (console + (a = \"PASS\", \"\"))\n                        return \"FAIL 1\";\n                    a.p;\n                } catch (e) {}\n            } finally {\n                return a;\n            }\n        }(\"FAIL 2\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5112_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                return function() {\n                    try {\n                        if (console + (a = \"PASS\", \"\"))\n                            return \"FAIL 1\";\n                        a.p;\n                    } catch (e) {}\n                }();\n            } finally {\n                return a;\n            }\n        }(\"FAIL 2\"));\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                return function() {\n                    try {\n                        if (console + (a = \"PASS\", \"\"))\n                            return \"FAIL 1\";\n                        a.p;\n                    } catch (e) {}\n                }();\n            } finally {\n                return a;\n            }\n        }(\"FAIL 2\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5182: {\n    options = {\n        arrows: true,\n        collapse_vars: true,\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        merge_vars: true,\n        passes: 4,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var con = console;\n        global.log = con.log;\n        var jump = function(x) {\n            console.log(\"JUMP:\", x * 10);\n            return x + x;\n        };\n        var jump2 = jump;\n        var run = function(x) {\n            console.log(\"RUN:\", x * -10);\n            return x * x;\n        };\n        var run2 = run;\n        var bar = (x, y) => {\n            console.log(\"BAR:\", x + y);\n            return x - y;\n        };\n        var bar2 = bar;\n        var obj = {\n            foo: bar2,\n            go: run2,\n            not_used: jump2,\n        };\n        console.log(obj.foo(1, 2), global.log(\"PASS\"));\n    }\n    expect: {\n        var con = console;\n        global.log = con.log,\n        console.log((console.log(\"BAR:\", 3), -1), global.log(\"PASS\"));\n    }\n    expect_stdout: [\n        \"BAR: 3\",\n        \"PASS\",\n        \"-1 undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5273: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"10\", b = 1;\n        function f(c, d) {\n            return d;\n        }\n        f((b += a, b *= a), f);\n        console.log(b);\n    }\n    expect: {\n        var a = \"10\", b = 1;\n        function f(c, d) {\n            return d;\n        }\n        b = 1100,\n        f,\n        console.log(b);\n    }\n    expect_stdout: \"1100\"\n}\n\nissue_5276: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = A = \"PASS\";\n        a.p += null;\n        a.p -= 42;\n        console.log(a);\n    }\n    expect: {\n        var a = A = \"PASS\";\n        a.p += null;\n        a.p -= 42;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5277: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = function() {\n                a += null;\n                a -= 42;\n            };\n        }());\n    }\n    expect: {\n        console.log(function() {}());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5309_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        toplevel: true,\n    }\n    input: {\n        if (console)\n            var a = (console.log(\"PASS\"), b), b = a;\n        else\n            console.log(\"FAIL\");\n    }\n    expect: {\n        var a, b;\n        console ? (console.log(\"PASS\"), b = b) : console.log(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5309_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b;\n        console ? (a = (console.log(\"PASS\"), b), b = a) : console.log(\"FAIL\");\n    }\n    expect: {\n        var a, b;\n        console ? (console.log(\"PASS\"), b = b) : console.log(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5394: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n    }\n    input: {\n        try {\n            throw A.p = (console.log(\"FAIL\"), []), !1;\n        } catch (e) {\n            console.log(typeof e);\n        }\n    }\n    expect: {\n        try {\n            throw !(A.p = (console.log(\"FAIL\"), []));\n        } catch (e) {\n            console.log(typeof e);\n        }\n    }\n    expect_stdout: \"object\"\n}\n\nissue_5396: {\n    options = {\n        collapse_vars: true,\n        merge_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a, b;\n        function f() {}\n        b = 0;\n        new function g(c) {\n            var d = a && g(e), e = ++d, i = [ 42 ];\n            for (var j in i)\n                console.log(\"PASS\"),\n                i;\n        }();\n    }\n    expect: {\n        var a, b;\n        function f() {}\n        b = 0;\n        (function g(c) {\n            a && g();\n            for (var j in [ 42 ])\n                console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5568: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        var a = (A = \"PASS\", !1);\n        for (var b in a);\n        console.log(A);\n    }\n    expect: {\n        A = \"FAIL\";\n        for (var b in !(A = \"PASS\"));\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5638_1: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a;\n        console;\n        a = [ 42 ];\n        console || FAIL(a);\n        console.log(a++);\n    }\n    expect: {\n        var a;\n        console;\n        a = [ 42 ];\n        console || FAIL(a);\n        console.log(a++);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5638_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a;\n        console;\n        a = [ 6 ];\n        console || FAIL(a);\n        console.log(a *= 7);\n    }\n    expect: {\n        var a;\n        console;\n        a = [ 6 ];\n        console || FAIL(a);\n        console.log(a *= 7);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5638_3: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var a = { foo: 42 }, b;\n        for (var k in a) {\n            b = a[k];\n            log(k || b, b++);\n        }\n    }\n    expect: {\n        var log = console.log;\n        var a = { foo: 42 }, b;\n        for (var k in a) {\n            b = a[k];\n            log(k || b, b++);\n        }\n    }\n    expect_stdout: \"foo 42\"\n}\n\nissue_5638_4: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var a = { foo: 6 }, b;\n        for (var k in a) {\n            b = a[k];\n            log(k || b, b *= 7);\n        }\n    }\n    expect: {\n        var log = console.log;\n        var a = { foo: 6 }, b;\n        for (var k in a) {\n            b = a[k];\n            log(k || b, b *= 7);\n        }\n    }\n    expect_stdout: \"foo 42\"\n}\n\nissue_5643: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 3, b;\n        a *= 7;\n        b = !!this;\n        console || console.log(b);\n        console.log(a * ++b);\n    }\n    expect: {\n        var a = 3, b;\n        a *= 7;\n        b = !!this;\n        console || console.log(b);\n        console.log(a * ++b);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5719: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 42, b;\n        switch (b = a) {\n          case a:\n          case b:\n          case a++:\n        }\n        console.log(a === b++ ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = 42, b;\n        switch (b = a) {\n          case a:\n          case b:\n          case a++:\n        }\n        console.log(a === b++ ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5779: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = A = \"foo\";\n        a.p = 42;\n        if (a && !a.p)\n            console.log(\"PASS\");\n    }\n    expect: {\n        var a = A = \"foo\";\n        a.p = 42;\n        if (a, !a.p)\n            console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1666: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect: {\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect_stdout: true\n}\n\nissue_1666_strict: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect: {\n        \"use strict\";\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect_stdout: true\n}\n\nissue_1666_undefined: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect: {\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect_stdout: true\n}\n\nissue_1666_undefined_strict: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect: {\n        \"use strict\";\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect_stdout: true\n}\n\nissue_5869: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b, log = console.log;\n        log();\n        a.p = 0;\n        b = a;\n        log(b);\n    }\n    expect: {\n        var a, log = console.log;\n        log();\n        log(void (a.p = 0));\n    }\n    expect_stdout: TypeError(\"Cannot set properties of undefined\")\n}\n\nissue_5915_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        f = void 0;\n        {\n            console.log(typeof f);\n            function f() {}\n        }\n    }\n    expect: {\n        f = void 0;\n        {\n            console.log(typeof f);\n            function f() {}\n        }\n    }\n    expect_stdout: true\n}\n\nissue_5915_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        f = void 0;\n        {\n            function f() {}\n            console.log(typeof f);\n        }\n    }\n    expect: {\n        f = void 0;\n        {\n            function f() {}\n            console.log(typeof f);\n        }\n    }\n    expect_stdout: true\n}\n\nissue_5915_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        f = void 0;\n        function f() {}\n        {\n            console.log(typeof f);\n        }\n    }\n    expect: {\n        function f() {}\n        console.log(typeof (f = void 0));\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5915_4: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        {\n            f = void 0;\n            function f() {}\n            console.log(typeof f);\n        }\n    }\n    expect: {\n        function f() {}\n        console.log(typeof (f = void 0));\n    }\n    expect_stdout: \"undefined\"\n}\n"
  },
  {
    "path": "test/compress/comparisons.js",
    "content": "comparisons: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        var obj1, obj2;\n        var result1 = obj1 <= obj2;\n        var result2 = obj1 <  obj2;\n        var result3 = obj1 >= obj2;\n        var result4 = obj1 >  obj2;\n    }\n    expect: {\n        var obj1, obj2;\n        var result1 = obj1 <= obj2;\n        var result2 = obj1 <  obj2;\n        var result3 = obj2 <= obj1;\n        var result4 = obj2 <  obj1;\n    }\n}\n\nunsafe_comps: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        unsafe_comps: true,\n    }\n    input: {\n        var obj1, obj2;\n        obj1 <= obj2 ? f1() : g1();\n        obj1 <  obj2 ? f2() : g2();\n        obj1 >= obj2 ? f3() : g3();\n        obj1 >  obj2 ? f4() : g4();\n    }\n    expect: {\n        var obj1, obj2;\n        (obj2 <  obj1 ? g1 : f1)();\n        (obj1 <  obj2 ? f2 : g2)();\n        (obj1 <  obj2 ? g3 : f3)();\n        (obj2 <  obj1 ? f4 : g4)();\n    }\n}\n\nunsafe_in_instanceof: {\n    options = {\n        side_effects: true,\n        unsafe_comps: true,\n    }\n    input: {\n        var a;\n        42 in a;\n        f() instanceof \"foo\";\n    }\n    expect: {\n        var a;\n        f();\n    }\n}\n\ndont_change_in_or_instanceof_expressions: {\n    input: {\n        1 in 1;\n        null in null;\n        1 instanceof 1;\n        null instanceof null;\n    }\n    expect: {\n        1 in 1;\n        null in null;\n        1 instanceof 1;\n        null instanceof null;\n    }\n}\n\nself_comparison_1: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        a === a;\n        a !== b;\n        b.c === a.c;\n        b.c !== b.c;\n    }\n    expect: {\n        a == a;\n        a !== b;\n        b.c === a.c;\n        b.c != b.c;\n    }\n}\n\nself_comparison_2: {\n    options = {\n        comparisons: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {}\n        var o = {};\n        console.log(f != f, o === o);\n    }\n    expect: {\n        function f() {}\n        var o = {};\n        console.log(false, true);\n    }\n    expect_stdout: \"false true\"\n}\n\nself_comparison_3: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var b = a;\n            a = null;\n            return b;\n        }\n        for (var i = 0; i < 2; i++)\n            console.log(f() === f());\n    }\n    expect: {\n        var a;\n        function f() {\n            var b = a;\n            a = null;\n            return b;\n        }\n        for (var i = 0; i < 2; i++)\n            console.log(f() === f());\n    }\n    expect_stdout: [\n        \"false\",\n        \"true\",\n    ]\n}\n\nself_comparison_4: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {};\n        console.log(o == o, o != o);\n        console.log(o === o, o !== o);\n    }\n    expect: {\n        console.log(!0, !1);\n        console.log(!0, !1);\n    }\n    expect_stdout: [\n        \"true false\",\n        \"true false\",\n    ]\n}\n\nissue_2857_1: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        a === undefined || a === null;\n        a === undefined || a !== null;\n        a !== undefined || a === null;\n        a !== undefined || a !== null;\n        a === undefined && a === null;\n        a === undefined && a !== null;\n        a !== undefined && a === null;\n        a !== undefined && a !== null;\n    }\n    expect: {\n        null == a;\n        void 0 === a || null !== a;\n        void 0 !== a || null === a;\n        void 0 !== a || null !== a;\n        void 0 === a && null === a;\n        void 0 === a && null !== a;\n        void 0 !== a && null === a;\n        null != a;\n    }\n}\n\nissue_2857_2: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        a === null || a === undefined;\n        a === null || a !== undefined;\n        a !== null || a === undefined;\n        a !== null || a !== undefined;\n        a === null && a === undefined;\n        a === null && a !== undefined;\n        a !== null && a === undefined;\n        a !== null && a !== undefined;\n    }\n    expect: {\n        null == a;\n        null === a || void 0 !== a;\n        null !== a || void 0 === a;\n        null !== a || void 0 !== a;\n        null === a && void 0 === a;\n        null === a && void 0 !== a;\n        null !== a && void 0 === a;\n        null != a;\n    }\n}\n\nissue_2857_3: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        a === undefined || a === null || p;\n        a === undefined || a !== null || p;\n        a !== undefined || a === null || p;\n        a !== undefined || a !== null || p;\n        a === undefined && a === null || p;\n        a === undefined && a !== null || p;\n        a !== undefined && a === null || p;\n        a !== undefined && a !== null || p;\n    }\n    expect: {\n        null == a || p;\n        void 0 === a || null !== a || p;\n        void 0 !== a || null === a || p;\n        void 0 !== a || null !== a || p;\n        void 0 === a && null === a || p;\n        void 0 === a && null !== a || p;\n        void 0 !== a && null === a || p;\n        null != a || p;\n    }\n}\n\nissue_2857_4: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        a === undefined || a === null && p;\n        a === undefined || a !== null && p;\n        a !== undefined || a === null && p;\n        a !== undefined || a !== null && p;\n        a === undefined && a === null && p;\n        a === undefined && a !== null && p;\n        a !== undefined && a === null && p;\n        a !== undefined && a !== null && p;\n    }\n    expect: {\n        void 0 === a || null === a && p;\n        void 0 === a || null !== a && p;\n        void 0 !== a || null === a && p;\n        void 0 !== a || null !== a && p;\n        void 0 === a && null === a && p;\n        void 0 === a && null !== a && p;\n        void 0 !== a && null === a && p;\n        null != a && p;\n    }\n}\n\nissue_2857_5: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n    }\n    input: {\n        p || a === undefined || a === null;\n        p || a === undefined || a !== null;\n        p || a !== undefined || a === null;\n        p || a !== undefined || a !== null;\n        p || a === undefined && a === null;\n        p || a === undefined && a !== null;\n        p || a !== undefined && a === null;\n        p || a !== undefined && a !== null;\n    }\n    expect: {\n        p || null == a;\n        p || void 0 === a || null !== a;\n        p || void 0 !== a || null === a;\n        p || void 0 !== a || null !== a;\n        p || void 0 === a && null === a;\n        p || void 0 === a && null !== a;\n        p || void 0 !== a && null === a;\n        p || null != a;\n    }\n}\n\nissue_2857_6: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n    }\n    input: {\n        p && a === undefined || a === null;\n        p && a === undefined || a !== null;\n        p && a !== undefined || a === null;\n        p && a !== undefined || a !== null;\n        p && a === undefined && a === null;\n        p && a === undefined && a !== null;\n        p && a !== undefined && a === null;\n        p && a !== undefined && a !== null;\n    }\n    expect: {\n        p && void 0 === a || null === a;\n        p && void 0 === a || null !== a;\n        p && void 0 !== a || null === a;\n        p && void 0 !== a || null !== a;\n        p && void 0 === a && null === a;\n        p && void 0 === a && null !== a;\n        p && void 0 !== a && null === a;\n        p && null != a;\n    }\n}\n\nissue_2857_7: {\n    options = {\n        comparisons: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            if ({}.b === undefined || {}.b === null)\n                return a.b !== undefined && a.b !== null;\n        }\n        console.log(f({ b: [] }));\n    }\n    expect: {\n        function f(a) {\n            if (null == {}.b)\n                return null != a.b;\n        }\n        console.log(f({ b: [] }));\n    }\n    expect_stdout: \"true\"\n}\n\nis_boolean_unsafe: {\n    options = {\n        comparisons: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(/foo/.test(\"bar\") === [].isPrototypeOf({}));\n    }\n    expect: {\n        console.log(/foo/.test(\"bar\") == [].isPrototypeOf({}));\n    }\n    expect_stdout: \"true\"\n}\n\nis_number_unsafe: {\n    options = {\n        comparisons: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(Math.acos(42) !== \"foo\".charCodeAt(4));\n    }\n    expect: {\n        console.log(Math.acos(42) != \"foo\".charCodeAt(4));\n    }\n    expect_stdout: \"true\"\n}\n\nis_boolean_var: {\n    options = {\n        comparisons: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            for (var i = 0, c = !b; i < a.length; i++)\n                if (!a[i] === c)\n                    return i;\n        }([ false, true ], 42));\n    }\n    expect: {\n        console.log(function(a, b) {\n            for (var i = 0, c = !b; i < a.length; i++)\n                if (!a[i] == c)\n                    return i;\n        }([ false, true ], 42));\n    }\n    expect_stdout: \"1\"\n}\n\nis_defined: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        console.log(function a() {\n            return void 0 === a;\n        }());\n    }\n    expect: {\n        console.log(function a() {\n            return a, false;\n        }());\n    }\n    expect_stdout: \"false\"\n    expect_warnings: [\n        \"WARN: Expression always defined [test/compress/comparisons.js:2,19]\",\n    ]\n}\n\nunsafe_indexOf: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        unsafe: true,\n    }\n    input: {\n        var a = Object.keys({ foo: 42 });\n        if (a.indexOf(\"bar\") < 0) console.log(\"PASS\");\n        if (0 > a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (a.indexOf(\"foo\") >= 0) console.log(\"PASS\");\n        if (0 <= a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (a.indexOf(\"foo\") > -1) console.log(\"PASS\");\n        if (-1 < a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (a.indexOf(\"bar\") == -1) console.log(\"PASS\");\n        if (-1 == a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (a.indexOf(\"bar\") === -1) console.log(\"PASS\");\n        if (-1 === a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (a.indexOf(\"foo\") != -1) console.log(\"PASS\");\n        if (-1 != a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (a.indexOf(\"foo\") !== -1) console.log(\"PASS\");\n        if (-1 !== a.indexOf(\"foo\")) console.log(\"PASS\");\n    }\n    expect: {\n        var a = Object.keys({ foo: 42 });\n        if (!~a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (!~a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (!~a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (!~a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (!~a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (!~a.indexOf(\"bar\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n        if (~a.indexOf(\"foo\")) console.log(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nunsafe_indexOf_assignment: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        unsafe: true,\n    }\n    input: {\n        var a;\n        if ((a = Object.keys({ foo: 42 }).indexOf(\"bar\")) < 0) console.log(\"PASS\");\n        if (0 > (a = Object.keys({ foo: 42 }).indexOf(\"bar\"))) console.log(\"PASS\");\n    }\n    expect: {\n        var a;\n        if (!~(a = Object.keys({ foo: 42 }).indexOf(\"bar\"))) console.log(\"PASS\");\n        if (!~(a = Object.keys({ foo: 42 }).indexOf(\"bar\"))) console.log(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_3413: {\n    options = {\n        comparisons: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        var b;\n        void 0 !== (\"\" < b || void 0) || console.log(\"PASS\");\n    }\n    expect: {\n        var b;\n        void 0 === (\"\" < b || void 0) && console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nnullish_assign: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        var a;\n        void 0 !== (a = \"PASS\".split(\"\")) && null !== a && console.log(a.join(\"-\"));\n    }\n    expect: {\n        var a;\n        null != (a = \"PASS\".split(\"\")) && console.log(a.join(\"-\"));\n    }\n    expect_stdout: \"P-A-S-S\"\n}\n\nnullish_chain: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n    }\n    input: {\n        var a;\n        A || B || void 0 === a || null === a || C;\n    }\n    expect: {\n        var a;\n        A || B || null == a || C;\n    }\n}\n\nnullish_inline: {\n    options = {\n        comparisons: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function isNull(a) {\n            return null === a;\n        }\n        function isUndefined(b) {\n            return void 0 === b;\n        }\n        null === c || void 0 === c;\n        isNull(c) || void 0 === c;\n        null === c || isUndefined(c);\n        isNull(c) || isUndefined(c);\n    }\n    expect: {\n        null == c;\n        null == c;\n        null == c;\n        null == c;\n    }\n}\n\nnullish_inline_renamed: {\n    rename = true\n    mangle = {\n        toplevel: true,\n    }\n    options = {\n        comparisons: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function isNull(a) {\n            return null === a;\n        }\n        function isUndefined(b) {\n            return void 0 === b;\n        }\n        null === c || void 0 === c;\n        isNull(c) || void 0 === c;\n        null === c || isUndefined(c);\n        isNull(c) || isUndefined(c);\n    }\n    expect: {\n        null == c;\n        null == c;\n        null == c;\n        null == c;\n    }\n}\n"
  },
  {
    "path": "test/compress/concat-strings.js",
    "content": "concat_1: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        var a = \"foo\" + \"bar\" + x() + \"moo\" + \"foo\" + y() + \"x\" + \"y\" + \"z\" + q();\n        var b = \"foo\" + 1 + x() + 2 + \"boo\";\n        var c = 1 + x() + 2 + \"boo\";\n\n        // this CAN'T safely be shortened to 1 + x() + \"5boo\"\n        var d = 1 + x() + 2 + 3 + \"boo\";\n\n        var e = 1 + x() + 2 + \"X\" + 3 + \"boo\";\n\n        // be careful with concatenation with \"\\0\" with octal-looking strings.\n        var f = \"\\0\" + 360 + \"\\0\" + 8 + \"\\0\";\n    }\n    expect: {\n        var a = \"foobar\" + x() + \"moofoo\" + y() + \"xyz\" + q();\n        var b = \"foo1\" + x() + \"2boo\";\n        var c = 1 + x() + 2 + \"boo\";\n        var d = 1 + x() + 2 + 3 + \"boo\";\n        var e = 1 + x() + 2 + \"X3boo\";\n        var f = \"\\x00360\\x008\\0\";\n    }\n}\n\nconcat_2: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            1 + (2 + 3),\n            1 + (2 + \"3\"),\n            1 + (\"2\" + 3),\n            1 + (\"2\" + \"3\"),\n            \"1\" + (2 + 3),\n            \"1\" + (2 + \"3\"),\n            \"1\" + (\"2\" + 3),\n            \"1\" + (\"2\" + \"3\")\n        );\n    }\n    expect: {\n        console.log(\n            1 + (2 + 3),\n            1 + (2 + \"3\"),\n            1 + \"2\" + 3,\n            1 + \"2\" + \"3\",\n            \"1\" + (2 + 3),\n            \"1\" + 2 + \"3\",\n            \"1\" + \"2\" + 3,\n            \"1\" + \"2\" + \"3\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_3: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            1 + 2 + (3 + 4 + 5),\n            1 + 2 + (3 + 4 + \"5\"),\n            1 + 2 + (3 + \"4\" + 5),\n            1 + 2 + (3 + \"4\" + \"5\"),\n            1 + 2 + (\"3\" + 4 + 5),\n            1 + 2 + (\"3\" + 4 + \"5\"),\n            1 + 2 + (\"3\" + \"4\" + 5),\n            1 + 2 + (\"3\" + \"4\" + \"5\")\n        );\n    }\n    expect: {\n        console.log(\n            1 + 2 + (3 + 4 + 5),\n            1 + 2 + (3 + 4 + \"5\"),\n            1 + 2 + (3 + \"4\") + 5,\n            1 + 2 + (3 + \"4\") + \"5\",\n            1 + 2 + \"3\" + 4 + 5,\n            1 + 2 + \"3\" + 4 + \"5\",\n            1 + 2 + \"3\" + \"4\" + 5,\n            1 + 2 + \"3\" + \"4\" + \"5\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_4: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            1 + \"2\" + (3 + 4 + 5),\n            1 + \"2\" + (3 + 4 + \"5\"),\n            1 + \"2\" + (3 + \"4\" + 5),\n            1 + \"2\" + (3 + \"4\" + \"5\"),\n            1 + \"2\" + (\"3\" + 4 + 5),\n            1 + \"2\" + (\"3\" + 4 + \"5\"),\n            1 + \"2\" + (\"3\" + \"4\" + 5),\n            1 + \"2\" + (\"3\" + \"4\" + \"5\")\n        );\n    }\n    expect: {\n        console.log(\n            1 + \"2\" + (3 + 4 + 5),\n            1 + \"2\" + (3 + 4) + \"5\",\n            1 + \"2\" + 3 + \"4\" + 5,\n            1 + \"2\" + 3 + \"4\" + \"5\",\n            1 + \"2\" + \"3\" + 4 + 5,\n            1 + \"2\" + \"3\" + 4 + \"5\",\n            1 + \"2\" + \"3\" + \"4\" + 5,\n            1 + \"2\" + \"3\" + \"4\" + \"5\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_5: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            \"1\" + 2 + (3 + 4 + 5),\n            \"1\" + 2 + (3 + 4 + \"5\"),\n            \"1\" + 2 + (3 + \"4\" + 5),\n            \"1\" + 2 + (3 + \"4\" + \"5\"),\n            \"1\" + 2 + (\"3\" + 4 + 5),\n            \"1\" + 2 + (\"3\" + 4 + \"5\"),\n            \"1\" + 2 + (\"3\" + \"4\" + 5),\n            \"1\" + 2 + (\"3\" + \"4\" + \"5\")\n        );\n    }\n    expect: {\n        console.log(\n            \"1\" + 2 + (3 + 4 + 5),\n            \"1\" + 2 + (3 + 4) + \"5\",\n            \"1\" + 2 + 3 + \"4\" + 5,\n            \"1\" + 2 + 3 + \"4\" + \"5\",\n            \"1\" + 2 + \"3\" + 4 + 5,\n            \"1\" + 2 + \"3\" + 4 + \"5\",\n            \"1\" + 2 + \"3\" + \"4\" + 5,\n            \"1\" + 2 + \"3\" + \"4\" + \"5\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_6: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            \"1\" + \"2\" + (3 + 4 + 5),\n            \"1\" + \"2\" + (3 + 4 + \"5\"),\n            \"1\" + \"2\" + (3 + \"4\" + 5),\n            \"1\" + \"2\" + (3 + \"4\" + \"5\"),\n            \"1\" + \"2\" + (\"3\" + 4 + 5),\n            \"1\" + \"2\" + (\"3\" + 4 + \"5\"),\n            \"1\" + \"2\" + (\"3\" + \"4\" + 5),\n            \"1\" + \"2\" + (\"3\" + \"4\" + \"5\")\n        );\n    }\n    expect: {\n        console.log(\n            \"1\" + \"2\" + (3 + 4 + 5),\n            \"1\" + \"2\" + (3 + 4) + \"5\",\n            \"1\" + \"2\" + 3 + \"4\" + 5,\n            \"1\" + \"2\" + 3 + \"4\" + \"5\",\n            \"1\" + \"2\" + \"3\" + 4 + 5,\n            \"1\" + \"2\" + \"3\" + 4 + \"5\",\n            \"1\" + \"2\" + \"3\" + \"4\" + 5,\n            \"1\" + \"2\" + \"3\" + \"4\" + \"5\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_7: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            \"\" + 1,\n            \"\" + \"1\",\n            \"\" + 1 + 2,\n            \"\" + 1 + \"2\",\n            \"\" + \"1\" + 2,\n            \"\" + \"1\" + \"2\",\n            \"\" + (x += \"foo\")\n        );\n    }\n    expect: {\n        console.log(\n            \"\" + 1,\n            \"1\",\n            \"\" + 1 + 2,\n            1 + \"2\",\n            \"1\" + 2,\n            \"1\" + \"2\",\n            x += \"foo\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_8: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(\n            1 + \"\",\n            \"1\" + \"\",\n            1 + 2 + \"\",\n            1 + \"2\" + \"\",\n            \"1\" + 2 + \"\",\n            \"1\" + \"2\" + \"\",\n            (x += \"foo\") + \"\"\n        );\n    }\n    expect: {\n        console.log(\n            1 + \"\",\n            \"1\",\n            1 + 2 + \"\",\n            1 + \"2\",\n            \"1\" + 2,\n            \"1\" + \"2\",\n            x += \"foo\"\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_9: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_vars: true,\n        strings: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"foo\";\n        console.log(\n            12 + (34 + a),\n            null + (34 + a),\n            12 + (null + a),\n            false + (34 + a),\n            12 + (false + a),\n            \"bar\" + (34 + a),\n            12 + (\"bar\" + a)\n        );\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(\n            \"1234\" + a,\n            \"null34\" + a,\n            \"12null\" + a,\n            !1 + (34 + a),\n            12 + (!1 + a),\n            \"bar34\" + a,\n            \"12bar\" + a\n        );\n    }\n    expect_stdout: true\n}\n\nconcat_sequence: {\n    options = {\n        collapse_vars: true,\n        strings: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(12 + (a = null, \"34\" + a));\n    }\n    expect: {\n        console.log(12 + \"34\" + null);\n    }\n    expect_stdout: \"1234null\"\n}\n\nissue_3689: {\n    options = {\n        strings: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a + (\"\" + (a[0] = 0));\n        }([]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a + (\"\" + (a[0] = 0));\n        }([]));\n    }\n    expect_stdout: \"00\"\n}\n\nissue_5145: {\n    options = {\n        strings: true,\n    }\n    input: {\n        var a = [];\n        console.log(\"\" + a + ((a[0] = 4) + \"2\"));\n    }\n    expect: {\n        var a = [];\n        console.log(\"\" + a + (a[0] = 4) + \"2\");\n    }\n    expect_stdout: \"42\"\n}\n"
  },
  {
    "path": "test/compress/conditionals.js",
    "content": "ifs_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (foo) bar();\n        if (!foo); else bar();\n        if (foo); else bar();\n        if (foo); else;\n    }\n    expect: {\n        foo&&bar();\n        foo&&bar();\n        foo||bar();\n        foo;\n    }\n}\n\nifs_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (foo) {\n            x();\n        } else if (bar) {\n            y();\n        } else if (baz) {\n            z();\n        }\n\n        if (foo) {\n            x();\n        } else if (bar) {\n            y();\n        } else if (baz) {\n            z();\n        } else {\n            t();\n        }\n    }\n    expect: {\n        foo ? x() : bar ? y() : baz && z();\n        (foo ? x : bar ? y : baz ? z : t)();\n    }\n}\n\nifs_3_should_warn: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        var x, y;\n        // 1\n        if (x && !(x + \"1\") && y) {\n            var qq;\n            foo();\n        } else {\n            bar();\n        }\n        // 2\n        if (x || !!(x + \"1\") || y) {\n            foo();\n        } else {\n            var jj;\n            bar();\n        }\n    }\n    expect: {\n        var x, y;\n        // 1\n        var qq; bar();\n        // 2\n        foo(); var jj;\n    }\n    expect_warnings: [\n        \"WARN: + in boolean context always true [test/compress/conditionals.js:3,18]\",\n        \"WARN: Boolean && always false [test/compress/conditionals.js:3,12]\",\n        \"WARN: Condition left of && always false [test/compress/conditionals.js:3,12]\",\n        \"WARN: Condition always false [test/compress/conditionals.js:3,12]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:3,12]\",\n        \"WARN: Dropping unreachable code [test/compress/conditionals.js:3,34]\",\n        \"WARN: + in boolean context always true [test/compress/conditionals.js:10,19]\",\n        \"WARN: Boolean || always true [test/compress/conditionals.js:10,12]\",\n        \"WARN: Condition left of || always true [test/compress/conditionals.js:10,12]\",\n        \"WARN: Condition always true [test/compress/conditionals.js:10,12]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/conditionals.js:10,12]\",\n        \"WARN: Dropping unreachable code [test/compress/conditionals.js:12,15]\",\n    ]\n}\n\nifs_4: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (foo && bar) {\n            x(foo)[10].bar.baz = something();\n        } else\n            x(foo)[10].bar.baz = something_else();\n    }\n    expect: {\n        foo && bar\n            ? x(foo)[10].bar.baz = something()\n            : x(foo)[10].bar.baz = something_else();\n    }\n}\n\nifs_5: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f() {\n            if (foo) return;\n            bar();\n            baz();\n        }\n        function g() {\n            if (foo) return;\n            if (bar) return;\n            if (baz) return;\n            if (baa) return;\n            a();\n            b();\n        }\n    }\n    expect: {\n        function f() {\n            if (!foo) {\n                bar();\n                baz();\n            }\n        }\n        function g() {\n            if (!(foo || bar || baz || baa)) {\n                a();\n                b();\n            }\n        }\n    }\n}\n\nifs_6: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n    }\n    input: {\n        var x, y;\n        if (!foo && !bar && !baz && !boo) {\n            x = 10;\n        } else {\n            x = 20;\n        }\n        if (y) {\n            x[foo] = 10;\n        } else {\n            x[foo] = 20;\n        }\n        if (foo) {\n            x[bar] = 10;\n        } else {\n            x[bar] = 20;\n        }\n    }\n    expect: {\n        var x, y;\n        x = foo || bar || baz || boo ? 20 : 10;\n        x[foo] = y ? 10 : 20;\n        foo ? x[bar] = 10 : x[bar] = 20;\n    }\n}\n\nifs_7: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (A); else;\n        if (A) while (B); else;\n        if (A); else while (C);\n        if (A) while (B); else while (C);\n    }\n    expect: {\n        A;\n        if (A) while (B);\n        if (!A) while (C);\n        if (A) while (B); else while (C);\n    }\n}\n\nmerge_tail_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                while (console.log(\"baz\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b = \"foo\";\n            if (a)\n                while (console.log(\"bar\"));\n            else\n                while (console.log(\"baz\"));\n            console.log(b);\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nmerge_tail_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                c = \"baz\";\n                while (console.log(c));\n                while (console.log(\"bar\"));\n                console.log(b);\n                var c;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b = \"foo\";\n            if (!a) {\n                c = \"baz\";\n                while (console.log(c));\n                var c;\n            }\n            while (console.log(\"bar\"));\n            console.log(b);\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"baz\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nmerge_tail_3: {\n    options = {\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            if (b = a.shift())\n                console.log(b);\n            else {\n                if (b = a.shift())\n                    while (console.log(\"foo\"));\n                console.log(b);\n            }\n        })([ false, \"bar\" ]);\n    }\n    expect: {\n        (function(a, b) {\n            if (!(b = a.shift()) && (b = a.shift()))\n                while (console.log(\"foo\"));\n            console.log(b);\n        })([ false, \"bar\" ]);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nmerge_tail_sequence_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                c = \"baz\";\n                while (console.log(c));\n                console.log(\"bar\"),\n                console.log(b);\n                var c;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b = \"foo\";\n            if (a)\n                while (console.log(\"bar\"));\n            else {\n                c = \"baz\";\n                while (console.log(c));\n                console.log(\"bar\");\n                var c;\n            }\n            console.log(b);\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"baz\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nmerge_tail_sequence_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                console.log(\"bar\");\n                console.log(b);\n            } else {\n                c = \"baz\";\n                while (console.log(c));\n                console.log(\"bar\"),\n                console.log(b);\n                var c;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b = \"foo\";\n            if (!a) {\n                c = \"baz\";\n                while (console.log(c));\n                var c;\n            }\n            console.log(\"bar\");\n            console.log(b);\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"baz\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nmerge_tail_sequence_3: {\n    options = {\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            if (b = a.shift())\n                console.log(\"foo\"),\n                console.log(b);\n            else {\n                if (b = a.shift())\n                    while (console.log(\"bar\"));\n                console.log(b);\n            }\n        })([ false, \"baz\" ]);\n    }\n    expect: {\n        (function(a, b) {\n            if (b = a.shift())\n                console.log(\"foo\");\n            else if (b = a.shift())\n                while (console.log(\"bar\"));\n            console.log(b);\n        })([ false, \"baz\" ]);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"baz\",\n    ]\n}\n\ncond_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function foo(do_something, some_condition) {\n            if (some_condition) {\n                do_something(x);\n            } else {\n                do_something(y);\n            }\n            if (some_condition) {\n                side_effects(x);\n            } else {\n                side_effects(y);\n            }\n        }\n    }\n    expect: {\n        function foo(do_something, some_condition) {\n            do_something(some_condition ? x : y);\n            some_condition ? side_effects(x) : side_effects(y);\n        }\n    }\n}\n\ncond_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function foo(x, FooBar, some_condition) {\n            if (some_condition) {\n                x = new FooBar(1);\n            } else {\n                x = new FooBar(2);\n            }\n        }\n    }\n    expect: {\n        function foo(x, FooBar, some_condition) {\n            x = new FooBar(some_condition ? 1 : 2);\n        }\n    }\n}\n\ncond_3: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var FooBar;\n        if (some_condition()) {\n            new FooBar(1);\n        } else {\n            FooBar(2);\n        }\n    }\n    expect: {\n        var FooBar;\n        some_condition() ? new FooBar(1) : FooBar(2);\n    }\n}\n\ncond_4: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var do_something;\n        if (some_condition()) {\n            do_something();\n        } else {\n            do_something();\n        }\n        if (some_condition()) {\n            side_effects();\n        } else {\n            side_effects();\n        }\n    }\n    expect: {\n        var do_something;\n        some_condition(), do_something();\n        some_condition(), side_effects();\n    }\n}\n\ncond_5: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (some_condition()) {\n            if (some_other_condition()) {\n                do_something();\n            } else {\n                alternate();\n            }\n        } else {\n            alternate();\n        }\n\n        if (some_condition()) {\n            if (some_other_condition()) {\n                do_something();\n            }\n        }\n    }\n    expect: {\n        (some_condition() && some_other_condition() ? do_something : alternate)();\n        some_condition() && some_other_condition() && do_something();\n    }\n}\n\ncond_6: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        x ? a : b;\n        x ? a : a;\n\n        x ? y ? a : b : c;\n        x ? y ? a : a : b;\n        x ? y ? a : b : b;\n        x ? y ? a : b : a;\n        x ? y ? a : a : a;\n\n        x ? a : y ? b : c;\n        x ? a : y ? a : b;\n        x ? a : y ? b : b;\n        x ? a : y ? b : a;\n        x ? a : y ? a : a;\n    }\n    expect: {\n        x ? a : b;\n        x, a;\n\n        x ? y ? a : b : c;\n        x ? (y, a) : b;\n        x && y ? a : b;\n        !x || y ? a : b;\n        x && y, a;\n\n        x ? a : y ? b : c;\n        x || y ? a : b;\n        x ? a : (y, b);\n        !x && y ? b : a;\n        !x && y, a;\n    }\n}\n\ncond_7: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        var x, y, z, a, b;\n        // compress these\n        if (y) {\n            x = 1+1;\n        } else {\n            x = 2;\n        }\n\n        if (y) {\n            x = 1+1;\n        } else if (z) {\n            x = 2;\n        } else {\n            x = 3-1;\n        }\n\n        x = y ? 'foo' : 'fo'+'o';\n\n        x = y ? 'foo' : y ? 'foo' : 'fo'+'o';\n\n        // Compress conditions that have side effects\n        if (condition()) {\n            x = 10+10;\n        } else {\n            x = 20;\n        }\n\n        if (z) {\n            x = 'fuji';\n        } else if (condition()) {\n            x = 'fu'+'ji';\n        } else {\n            x = 'fuji';\n        }\n\n        x = condition() ? 'foobar' : 'foo'+'bar';\n\n        // don't compress these\n        x = y ? a : b;\n\n        x = y ? 'foo' : 'fo';\n    }\n    expect: {\n        var x, y, z, a, b;\n        x = 2;\n        x = 2;\n        x = 'foo';\n        x = 'foo';\n        x = (condition(), 20);\n        x = (z || condition(), 'fuji');\n        x = (condition(), 'foobar');\n        x = y ? a : b;\n        x = y ? 'foo' : 'fo';\n    }\n}\n\ncond_7_1: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        var x;\n        // access to global should be assumed to have side effects\n        if (y) {\n            x = 1+1;\n        } else {\n            x = 2;\n        }\n    }\n    expect: {\n        var x;\n        x = (y, 2);\n    }\n}\n\ncond_8: {\n    options = {\n        booleans: false,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        var a;\n        // compress these\n        a = condition ? true : false;\n        a = !condition ? true : false;\n        a = condition() ? true : false;\n\n        a = condition ? !0 : !1;\n        a = !condition ? !null : !2;\n        a = condition() ? !0 : !-3.5;\n\n        if (condition) {\n            a = true;\n        } else {\n            a = false;\n        }\n\n        if (condition) {\n            a = !0;\n        } else {\n            a = !1;\n        }\n\n        a = condition ? false : true;\n        a = !condition ? false : true;\n        a = condition() ? false : true;\n\n        a = condition ? !3 : !0;\n        a = !condition ? !2 : !0;\n        a = condition() ? !1 : !0;\n\n        if (condition) {\n            a = false;\n        } else {\n            a = true;\n        }\n\n        if (condition) {\n            a = !1;\n        } else {\n            a = !0;\n        }\n\n        // don't compress these\n        a = condition ? 1 : false;\n        a = !condition ? true : 0;\n        a = condition ? 1 : 0;\n    }\n    expect: {\n        var a;\n        a = !!condition;\n        a = !condition;\n        a = !!condition();\n\n        a = !!condition;\n        a = !condition;\n        a = !!condition();\n\n        a = !!condition;\n        a = !!condition;\n\n        a = !condition;\n        a = !!condition;\n        a = !condition();\n\n        a = !condition;\n        a = !!condition;\n        a = !condition();\n\n        a = !condition;\n        a = !condition;\n\n        a = !!condition && 1;\n        a = !condition || 0;\n        a = condition ? 1 : 0;\n    }\n}\n\ncond_8b: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        var a;\n        // compress these\n        a = condition ? true : false;\n        a = !condition ? true : false;\n        a = condition() ? true : false;\n\n        a = condition ? !0 : !1;\n        a = !condition ? !null : !2;\n        a = condition() ? !0 : !-3.5;\n\n        if (condition) {\n            a = true;\n        } else {\n            a = false;\n        }\n\n        if (condition) {\n            a = !0;\n        } else {\n            a = !1;\n        }\n\n        a = condition ? false : true;\n        a = !condition ? false : true;\n        a = condition() ? false : true;\n\n        a = condition ? !3 : !0;\n        a = !condition ? !2 : !0;\n        a = condition() ? !1 : !0;\n\n        if (condition) {\n            a = false;\n        } else {\n            a = true;\n        }\n\n        if (condition) {\n            a = !1;\n        } else {\n            a = !0;\n        }\n\n        a = condition ? 1 : false;\n        a = !condition ? true : 0;\n        a = condition ? 1 : 0;\n    }\n    expect: {\n        var a;\n        a = !!condition;\n        a = !condition;\n        a = !!condition();\n\n        a = !!condition;\n        a = !condition;\n        a = !!condition();\n\n        a = !!condition;\n        a = !!condition;\n\n        a = !condition;\n        a = !!condition;\n        a = !condition();\n\n        a = !condition;\n        a = !!condition;\n        a = !condition();\n\n        a = !condition;\n        a = !condition;\n\n        a = !!condition && 1;\n        a = !condition || 0;\n        a = condition ? 1 : 0;\n    }\n}\n\ncond_8c: {\n    options = {\n        booleans: false,\n        conditionals: true,\n        evaluate: false,\n    }\n    input: {\n        var a;\n        // compress these\n        a = condition ? true : false;\n        a = !condition ? true : false;\n        a = condition() ? true : false;\n\n        a = condition ? !0 : !1;\n        a = !condition ? !null : !2;\n        a = condition() ? !0 : !-3.5;\n\n        if (condition) {\n            a = true;\n        } else {\n            a = false;\n        }\n\n        if (condition) {\n            a = !0;\n        } else {\n            a = !1;\n        }\n\n        a = condition ? false : true;\n        a = !condition ? false : true;\n        a = condition() ? false : true;\n\n        a = condition ? !3 : !0;\n        a = !condition ? !2 : !0;\n        a = condition() ? !1 : !0;\n\n        if (condition) {\n            a = false;\n        } else {\n            a = true;\n        }\n\n        if (condition) {\n            a = !1;\n        } else {\n            a = !0;\n        }\n\n        a = condition ? 1 : false;\n        a = !condition ? true : 0;\n        a = condition ? 1 : 0;\n    }\n    expect: {\n        var a;\n        a = !!condition;\n        a = !condition;\n        a = !!condition();\n\n        a = !!condition;\n        a = !condition;\n        a = !!condition() || !-3.5;\n\n        a = !!condition;\n        a = !!condition;\n\n        a = !condition;\n        a = !!condition;\n        a = !condition();\n\n        a = !condition;\n        a = !!condition;\n        a = !condition();\n\n        a = !condition;\n        a = !condition;\n\n        a = !!condition && 1;\n        a = !condition || 0;\n        a = condition ? 1 : 0;\n    }\n}\n\ncond_9: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y) {\n            g() ? x(1) : x(2);\n            x ? (y || x)() : (y || x)();\n            x ? y(a, b) : y(d, b, c);\n            x ? y(a, b, c) : y(a, b, c);\n            x ? y(a, b, c) : y(a, b, f);\n            x ? y(a, b, c) : y(a, e, c);\n            x ? y(a, b, c) : y(a, e, f);\n            x ? y(a, b, c) : y(d, b, c);\n            x ? y(a, b, c) : y(d, b, f);\n            x ? y(a, b, c) : y(d, e, c);\n            x ? y(a, b, c) : y(d, e, f);\n        }\n    }\n    expect: {\n        function f(x, y) {\n            g() ? x(1) : x(2);\n            x, (y || x)();\n            x ? y(a, b) : y(d, b, c);\n            x, y(a, b, c);\n            y(a, b, x ? c : f);\n            y(a, x ? b : e, c);\n            x ? y(a, b, c) : y(a, e, f);\n            y(x ? a : d, b, c);\n            x ? y(a, b, c) : y(d, b, f);\n            x ? y(a, b, c) : y(d, e, c);\n            x ? y(a, b, c) : y(d, e, f);\n        }\n    }\n}\n\ncond_10: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (1 == a) return \"foo\";\n            if (2 == a) return \"foo\";\n            if (3 == a) return \"foo\";\n            if (4 == a) return 42;\n            if (5 == a) return \"foo\";\n            if (6 == a) return \"foo\";\n            return \"bar\";\n        }\n        console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));\n    }\n    expect: {\n        function f(a) {\n            return 1 == a || 2 == a || 3 == a ? \"foo\" : 4 == a ? 42 : 5 == a || 6 == a ? \"foo\" : \"bar\";\n        }\n        console.log(f(1), f(2), f(3), f(4), f(5), f(6), f(7));\n    }\n    expect_stdout: \"foo foo foo 42 foo foo bar\"\n}\n\ncond_11: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var o = {\n            p: \"foo\",\n            q: function() {\n                return this.p;\n            }\n        };\n        function f() {\n            return \"bar\";\n        }\n        function g(a) {\n            return a ? f() : o.q();\n        }\n        console.log(g(0), g(1));\n    }\n    expect: {\n        var o = {\n            p: \"foo\",\n            q: function() {\n                return this.p;\n            }\n        };\n        function f() {\n            return \"bar\";\n        }\n        function g(a) {\n            return a ? f() : o.q();\n        }\n        console.log(g(0), g(1));\n    }\n    expect_stdout: \"foo bar\"\n}\n\ncond_12: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        x ? y && a : a;\n        x ? y || a : a;\n        x ? a : y && a;\n        x ? a : y || a;\n    }\n    expect: {\n        (!x || y) && a;\n        x && y || a;\n        (x || y) && a;\n        !x && y || a;\n    }\n}\n\ncond_13: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        x ? y(a) : z(a);\n        x ? y.f(a) : z.f(a);\n        x ? y.f(a) : z.g(a);\n        x ? y.f()(a) : z.g()(a);\n        x ? y.f.u(a) : z.g.u(a);\n        x ? y.f().u(a) : z.g().u(a);\n    }\n    expect: {\n        (x ? y : z)(a);\n        (x ? y : z).f(a);\n        x ? y.f(a) : z.g(a);\n        (x ? y.f() : z.g())(a);\n        (x ? y.f : z.g).u(a);\n        (x ? y.f() : z.g()).u(a);\n    }\n}\n\ncond_14: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                if (a)\n                    console.log(\"PASS\");\n                else\n                    console.log(\"FAIL\");\n        }\n        f(null);\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            a && console.log(\"PASS\");\n        }\n        f(null);\n        f(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nternary_boolean_consequent: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() { return a == b ? true : x; }\n        function f2() { return a == b ? false : x; }\n        function f3() { return a < b ? !0 : x; }\n        function f4() { return a < b ? !1 : x; }\n        function f5() { return c ? !0 : x; }\n        function f6() { return c ? false : x; }\n        function f7() { return !c ? true : x; }\n        function f8() { return !c ? !1 : x; }\n    }\n    expect: {\n        function f1() { return a == b || x; }\n        function f2() { return a != b && x; }\n        function f3() { return a < b || x; }\n        function f4() { return !(a < b) && x; }\n        function f5() { return !!c || x; }\n        function f6() { return !c && x; }\n        function f7() { return !c || x; }\n        function f8() { return !!c && x; }\n    }\n}\n\nternary_boolean_alternative: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() { return a == b ? x : true; }\n        function f2() { return a == b ? x : false; }\n        function f3() { return a < b ? x : !0; }\n        function f4() { return a < b ? x : !1; }\n        function f5() { return c ? x : true; }\n        function f6() { return c ? x : !1; }\n        function f7() { return !c ? x : !0; }\n        function f8() { return !c ? x : false; }\n    }\n    expect: {\n        function f1() { return a != b || x; }\n        function f2() { return a == b && x; }\n        function f3() { return !(a < b) || x; }\n        function f4() { return a < b && x; }\n        function f5() { return !c || x; }\n        function f6() { return !!c && x; }\n        function f7() { return !!c || x; }\n        function f8() { return !c && x; }\n    }\n}\n\ntrivial_boolean_ternary_expressions : {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        f('foo' in m ? true  : false);\n        f('foo' in m ? false : true);\n\n        f(g       ? true : false);\n        f(foo()   ? true : false);\n        f(\"bar\"   ? true : false);\n        f(5       ? true : false);\n        f(5.7     ? true : false);\n        f(x - y   ? true : false);\n\n        f(x == y  ? true : false);\n        f(x === y ?   !0 :    !1);\n        f(x < y   ?   !0 : false);\n        f(x <= y  ? true : false);\n        f(x > y   ? true :    !1);\n        f(x >= y  ?   !0 :    !1);\n\n        f(g       ? false : true);\n        f(foo()   ? false : true);\n        f(\"bar\"   ? false : true);\n        f(5       ? false : true);\n        f(5.7     ? false : true);\n        f(x - y   ? false : true);\n\n        f(x == y  ?    !1 :   !0);\n        f(x === y ? false : true);\n\n        f(x < y   ? false : true);\n        f(x <= y  ? false :   !0);\n        f(x > y   ?    !1 : true);\n        f(x >= y  ?    !1 :   !0);\n    }\n    expect: {\n        f('foo' in m);\n        f(!('foo' in m));\n\n        f(!!g);\n        f(!!foo());\n        f(!0);\n        f(!0);\n        f(!0);\n        f(!!(x - y));\n\n        f(x == y);\n        f(x === y);\n        f(x < y);\n        f(x <= y);\n        f(x > y);\n        f(x >= y);\n\n        f(!g);\n        f(!foo());\n        f(!1);\n        f(!1);\n        f(!1);\n        f(!(x - y));\n\n        f(x != y);\n        f(x !== y);\n\n        f(!(x < y));\n        f(!(x <= y));\n        f(!(x > y));\n        f(!(x >= y));\n    }\n}\n\nextendscript_1: {\n    beautify = {\n        extendscript: true,\n    }\n    input: {\n        var alert = console.log;\n        function f(a, b) {\n            return a ? b ? \"foo\" : \"bar\" : \"baz\";\n        }\n        alert(f());\n        alert(f(42));\n        alert(f(null, true));\n        alert(f([], {}));\n    }\n    expect_exact: 'var alert=console.log;function f(a,b){return a?(b?\"foo\":\"bar\"):\"baz\"}alert(f());alert(f(42));alert(f(null,true));alert(f([],{}));'\n    expect_stdout: [\n        \"baz\",\n        \"bar\",\n        \"baz\",\n        \"foo\",\n    ]\n}\n\nextendscript_2: {\n    beautify = {\n        extendscript: true,\n    }\n    input: {\n        var alert = console.log;\n        function f(a, b) {\n            return a ? \"foo\" : b ? \"bar\" : \"baz\";\n        }\n        alert(f());\n        alert(f(42));\n        alert(f(null, true));\n        alert(f([], {}));\n    }\n    expect_exact: 'var alert=console.log;function f(a,b){return a?\"foo\":(b?\"bar\":\"baz\")}alert(f());alert(f(42));alert(f(null,true));alert(f([],{}));'\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nissue_1154: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f1(x) { return x ? -1 : -1; }\n        function f2(x) { return x ? +2 : +2; }\n        function f3(x) { return x ? ~3 : ~3; }\n        function f4(x) { return x ? !4 : !4; }\n        function f5(x) { return x ? void 5 : void 5; }\n        function f6(x) { return x ? typeof 6 : typeof 6; }\n\n        function g1() { return g() ? -1 : -1; }\n        function g2() { return g() ? +2 : +2; }\n        function g3() { return g() ? ~3 : ~3; }\n        function g4() { return g() ? !4 : !4; }\n        function g5() { return g() ? void 5 : void 5; }\n        function g6() { return g() ? typeof 6 : typeof 6; }\n    }\n    expect: {\n        function f1(x) { return -1; }\n        function f2(x) { return 2; }\n        function f3(x) { return -4; }\n        function f4(x) { return !1; }\n        function f5(x) { return; }\n        function f6(x) { return \"number\"; }\n\n        function g1() { return g(), -1; }\n        function g2() { return g(), 2; }\n        function g3() { return g(), -4; }\n        function g4() { return g(), !1; }\n        function g5() { return void g(); }\n        function g6() { return g(), \"number\"; }\n    }\n}\n\nno_evaluate: {\n    options = {\n        conditionals: true,\n        evaluate: false,\n        side_effects: true,\n    }\n    input: {\n        function f(b) {\n            a = b ? !0 : !0;\n            a = b ? ~1 : ~1;\n            a = b ? -2 : -2;\n            a = b ? +3 : +3;\n        }\n    }\n    expect: {\n        function f(b) {\n            a = !0;\n            a = ~1;\n            a = -2;\n            a = +3;\n        }\n    }\n}\n\nequality_conditionals_false: {\n    options = {\n        conditionals: false,\n        sequences: true,\n    }\n    input: {\n        function f(a, b, c) {\n            console.log(\n                a == (b ? a : a),\n                a == (b ? a : c),\n                a != (b ? a : a),\n                a != (b ? a : c),\n                a === (b ? a : a),\n                a === (b ? a : c),\n                a !== (b ? a : a),\n                a !== (b ? a : c)\n            );\n        }\n        f(0, 0, 0);\n        f(0, true, 0);\n        f(1, 2, 3);\n        f(1, null, 3);\n        f(NaN);\n        f(NaN, \"foo\");\n    }\n    expect: {\n        function f(a, b, c) {\n            console.log(\n                a == (b ? a : a),\n                a == (b ? a : c),\n                a != (b ? a : a),\n                a != (b ? a : c),\n                a === (b ? a : a),\n                a === (b ? a : c),\n                a !== (b ? a : a),\n                a !== (b ? a : c)\n            );\n        }\n        f(0, 0, 0),\n        f(0, true, 0),\n        f(1, 2, 3),\n        f(1, null, 3),\n        f(NaN),\n        f(NaN, \"foo\");\n    }\n    expect_stdout: true\n}\n\nequality_conditionals_true: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(a, b, c) {\n            console.log(\n                a == (b ? a : a),\n                a == (b ? a : c),\n                a != (b ? a : a),\n                a != (b ? a : c),\n                a === (b ? a : a),\n                a === (b ? a : c),\n                a !== (b ? a : a),\n                a !== (b ? a : c)\n            );\n        }\n        f(0, 0, 0);\n        f(0, true, 0);\n        f(1, 2, 3);\n        f(1, null, 3);\n        f(NaN);\n        f(NaN, \"foo\");\n    }\n    expect: {\n        function f(a, b, c) {\n            console.log(\n                (b, a == a),\n                a == (b ? a : c),\n                (b, a != a),\n                a != (b ? a : c),\n                (b, a === a),\n                a === (b ? a : c),\n                (b, a !== a),\n                a !== (b ? a : c)\n            );\n        }\n        f(0, 0, 0),\n        f(0, true, 0),\n        f(1, 2, 3),\n        f(1, null, 3),\n        f(NaN),\n        f(NaN, \"foo\");\n    }\n    expect_stdout: true\n}\n\nissue_1645_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        (b = a) ? a++ + (b += a) ? b += a : b += a : b ^= a;\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        (b = a) ? (a++ + (b += a), b += a) : b ^= a;\n        console.log(a,b);\n    }\n    expect_stdout: true\n}\n\nissue_1645_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a = 0;\n        function f() {\n            return a++;\n        }\n        f() ? a += 2 : a += 4;\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        function f(){\n            return a++;\n        }\n        f() ? a += 2 : a += 4;\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\ncondition_matches_consequent: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function foo(x, y) {\n            return x ? x : y;\n        }\n        function bar() {\n            return g ? g : h;\n        }\n        var g = 4;\n        var h = 5;\n        console.log(foo(3, null), foo(0, 7), foo(true, false), bar());\n    }\n    expect: {\n        function foo(x, y) {\n            return x || y;\n        }\n        function bar() {\n            return g || h;\n        }\n        var g = 4;\n        var h = 5;\n        console.log(foo(3, null), foo(0, 7), foo(true, false), bar());\n    }\n    expect_stdout: \"3 7 true 4\"\n}\n\ncondition_matches_alternative: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function foo(x, y) {\n            return x.p ? y[0] : x.p;\n        }\n        function bar() {\n            return g ? h : g;\n        }\n        var g = 4;\n        var h = 5;\n        console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());\n    }\n    expect: {\n        function foo(x, y) {\n            return x.p && y[0];\n        }\n        function bar() {\n            return g && h;\n        }\n        var g = 4;\n        var h = 5;\n        console.log(foo({ p: 3 }, [ null ]), foo({ p: 0 }, [ 7 ]), foo({ p: true } , [ false ]), bar());\n    }\n    expect_stdout: \"null 0 false 5\"\n}\n\ncondition_sequence_1: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(x, y) {\n            return (console.log(x), x) ? x : y;\n        }\n        console.log(f(\"foo\", \"bar\"));\n        console.log(f(null, \"baz\"));\n        console.log(f(42));\n        console.log(f());\n    }\n    expect: {\n        function f(x, y) {\n            return console.log(x), x || y;\n        }\n        console.log(f(\"foo\", \"bar\")),\n        console.log(f(null, \"baz\")),\n        console.log(f(42)),\n        console.log(f());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"null\",\n        \"baz\",\n        \"42\",\n        \"42\",\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\ncondition_sequence_2: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(x, y) {\n            return (console.log(y), y) ? x : y;\n        }\n        console.log(f(\"foo\", \"bar\"));\n        console.log(f(null, \"baz\"));\n        console.log(f(42));\n        console.log(f());\n    }\n    expect: {\n        function f(x, y) {\n            return console.log(y), y && x;\n        }\n        console.log(f(\"foo\", \"bar\")),\n        console.log(f(null, \"baz\")),\n        console.log(f(42)),\n        console.log(f());\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"baz\",\n        \"null\",\n        \"undefined\",\n        \"undefined\",\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\ncombine_tail_sequence: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var n = {\n            f: function() {\n                console.log(\"foo\");\n                return this.p;\n            },\n            p: \"FAIL 1\",\n        };\n        var o = {\n            f: function() {\n                console.log(\"foz\");\n                return this.p;\n            },\n            p: \"FAIL 2\",\n        };\n        var p = \"PASS\";\n        function g(a) {\n            return a\n                ? (console.log(\"baa\"), (console.log(\"bar\"), (console.log(\"baz\"), n).f)())\n                : (console.log(\"moo\"), (console.log(\"mor\"), (console.log(\"moz\"), o).f)());\n        }\n        console.log(g());\n        console.log(g(42));\n    }\n    expect: {\n        var n = {\n            f: function() {\n                console.log(\"foo\");\n                return this.p;\n            },\n            p: \"FAIL 1\",\n        };\n        var o = {\n            f: function() {\n                console.log(\"foz\");\n                return this.p;\n            },\n            p: \"FAIL 2\",\n        };\n        var p = \"PASS\";\n        function g(a) {\n            return (0, (a\n                ? (console.log(\"baa\"), console.log(\"bar\"), console.log(\"baz\"), n)\n                : (console.log(\"moo\"), console.log(\"mor\"), console.log(\"moz\"), o)).f)();\n        }\n        console.log(g());\n        console.log(g(42));\n    }\n    expect_stdout: [\n        \"moo\",\n        \"mor\",\n        \"moz\",\n        \"foz\",\n        \"PASS\",\n        \"baa\",\n        \"bar\",\n        \"baz\",\n        \"foo\",\n        \"PASS\",\n    ]\n}\n\nconsequent_sequence_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a) {\n            return x ? (console.log(\"seq\"), y && a) : a;\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect: {\n        function f(x, y, a) {\n            return (!x || (console.log(\"seq\"), y)) && a;\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"seq\",\n        \"false\",\n        \"seq\",\n        \"4\",\n    ]\n}\n\nconsequent_sequence_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a) {\n            return x ? (console.log(\"seq\"), y || a) : a;\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect: {\n        function f(x, y, a) {\n            return x && (console.log(\"seq\"), y) || a;\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"seq\",\n        \"3\",\n        \"seq\",\n        \"true\",\n    ]\n}\n\nconsequent_sequence_3: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a, b) {\n            return x ? (console.log(\"seq\"), y ? a : b) : b;\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect: {\n        function f(x, y, a, b) {\n            return x && (console.log(\"seq\"), y) ? a : b;\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect_stdout: [\n        \"-1\",\n        \"-2\",\n        \"seq\",\n        \"-3\",\n        \"seq\",\n        \"4\",\n    ]\n}\n\nconsequent_sequence_4: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a, b) {\n            return x ? (console.log(\"seq\"), y ? a : b) : a;\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect: {\n        function f(x, y, a, b) {\n            return !x || (console.log(\"seq\"), y) ? a : b;\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"seq\",\n        \"-3\",\n        \"seq\",\n        \"4\",\n    ]\n}\n\nalternative_sequence_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a) {\n            return x ? a : (console.log(\"seq\"), y && a);\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect: {\n        function f(x, y, a) {\n            return (x || (console.log(\"seq\"), y)) && a;\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect_stdout: [\n        \"seq\",\n        \"false\",\n        \"seq\",\n        \"2\",\n        \"3\",\n        \"4\",\n    ]\n}\n\nalternative_sequence_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a) {\n            return x ? a : (console.log(\"seq\"), y || a);\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect: {\n        function f(x, y, a) {\n            return !x && (console.log(\"seq\"), y) || a;\n        }\n        console.log(f(false, false, 1));\n        console.log(f(false, true, 2));\n        console.log(f(true, false, 3));\n        console.log(f(true, true, 4));\n    }\n    expect_stdout: [\n        \"seq\",\n        \"1\",\n        \"seq\",\n        \"true\",\n        \"3\",\n        \"4\",\n    ]\n}\n\nalternative_sequence_3: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a, b) {\n            return x ? a : (console.log(\"seq\"), y ? a : b);\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect: {\n        function f(x, y, a, b) {\n            return x || (console.log(\"seq\"), y) ? a : b;\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect_stdout: [\n        \"seq\",\n        \"-1\",\n        \"seq\",\n        \"2\",\n        \"3\",\n        \"4\",\n    ]\n}\n\nalternative_sequence_4: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(x, y, a, b) {\n            return x ? b : (console.log(\"seq\"), y ? a : b);\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect: {\n        function f(x, y, a, b) {\n            return !x && (console.log(\"seq\"), y) ? a : b;\n        }\n        console.log(f(false, false, 1, -1));\n        console.log(f(false, true, 2, -2));\n        console.log(f(true, false, 3, -3));\n        console.log(f(true, true, 4, -4));\n    }\n    expect_stdout: [\n        \"seq\",\n        \"-1\",\n        \"seq\",\n        \"2\",\n        \"-3\",\n        \"-4\",\n    ]\n}\n\ndelete_conditional_1: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (1 ? undefined : x));\n        console.log(delete (1 ? void 0 : x));\n        console.log(delete (1 ? Infinity : x));\n        console.log(delete (1 ? 1 / 0 : x));\n        console.log(delete (1 ? NaN : x));\n        console.log(delete (1 ? 0 / 0 : x));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\ndelete_conditional_2: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        keep_infinity: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (0 ? x : undefined));\n        console.log(delete (0 ? x : void 0));\n        console.log(delete (0 ? x : Infinity));\n        console.log(delete (0 ? x : 1 / 0));\n        console.log(delete (0 ? x : NaN));\n        console.log(delete (0 ? x : 0 / 0));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\nissue_2535_1: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        if (true || x()) y();\n        if (true && x()) y();\n        if (x() || true) y();\n        if (x() && true) y();\n        if (false || x()) y();\n        if (false && x()) y();\n        if (x() || false) y();\n        if (x() && false) y();\n    }\n    expect: {\n        y();\n        x() && y();\n        x(), y();\n        x() && y();\n        x() && y();\n        x() && y();\n        x();\n    }\n}\n\nissue_2535_2: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function x() {}\n        function y() {\n            return \"foo\";\n        }\n        console.log((x() || true) || y());\n        console.log((y() || true) || x());\n        console.log((x() || true) && y());\n        console.log((y() || true) && x());\n        console.log((x() && true) || y());\n        console.log((y() && true) || x());\n        console.log((x() && true) && y());\n        console.log((y() && true) && x());\n        console.log((x() || false) || y());\n        console.log((y() || false) || x());\n        console.log((x() || false) && y());\n        console.log((y() || false) && x());\n        console.log((x() && false) || y());\n        console.log((y() && false) || x());\n        console.log((x() && false) && y());\n        console.log((y() && false) && x());\n    }\n    expect: {\n        function x() {}\n        function y() {\n            return \"foo\";\n        }\n        console.log(x() || !0);\n        console.log(y() || !0);\n        console.log((x(), y()));\n        console.log((y(), x()));\n        console.log(!!x() || y());\n        console.log(!!y() || x());\n        console.log(x() && y());\n        console.log(y() && x());\n        console.log(x() || y());\n        console.log(y() || x());\n        console.log(!!x() && y());\n        console.log(!!y() && x());\n        console.log((x(), y()));\n        console.log((y(), x()));\n        console.log(x() && !1);\n        console.log(y() && !1);\n    }\n    expect_stdout: [\n        \"true\",\n        \"foo\",\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"true\",\n        \"undefined\",\n        \"undefined\",\n        \"foo\",\n        \"foo\",\n        \"false\",\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"undefined\",\n        \"false\",\n    ]\n}\n\nissue_2560: {\n    options = {\n        conditionals: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function log(x) {\n            console.log(x);\n        }\n        function foo() {\n            return log;\n        }\n        function bar() {\n            if (x !== (x = foo())) {\n                x(1);\n            } else {\n                x(2);\n            }\n        }\n        var x = function() {\n            console.log(\"init\");\n        };\n        bar();\n        bar();\n    }\n    expect: {\n        function log(x) {\n            console.log(x);\n        }\n        function bar() {\n            x !== (x = log) ? x(1) : x(2);\n        }\n        var x = function() {\n            console.log(\"init\");\n        };\n        bar();\n        bar();\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\nhoist_decl: {\n    options = {\n        conditionals: true,\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        if (x()) {\n            var a;\n            y();\n        } else {\n            z();\n            var b;\n        }\n    }\n    expect: {\n        var a, b;\n        (x() ? y : z)();\n    }\n}\n\nto_and_or: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var values = [\n            0,\n            null,\n            true,\n            \"foo\",\n            false,\n            -1 / 0,\n            void 0,\n        ];\n        values.forEach(function(x) {\n            values.forEach(function(y) {\n                values.forEach(function(z) {\n                    console.log(x ? y || z : z);\n                });\n            });\n        });\n    }\n    expect: {\n        var values = [\n            0,\n            null,\n            true,\n            \"foo\",\n            false,\n            -1 / 0,\n            void 0,\n        ];\n        values.forEach(function(x) {\n            values.forEach(function(y) {\n                values.forEach(function(z) {\n                    console.log(x && y || z);\n                });\n            });\n        });\n    }\n    expect_stdout: true\n}\n\ncond_seq_assign_1: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(a) {\n            var t;\n            if (a) {\n                t = \"foo\";\n                t = \"bar\";\n            } else {\n                console.log(t);\n                t = 42;\n            }\n            console.log(t);\n        }\n        f(f);\n        f();\n    }\n    expect: {\n        function f(a) {\n            var t;\n            t = a ? (t = \"foo\", \"bar\") : (console.log(t), 42),\n            console.log(t);\n        }\n        f(f),\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"undefined\",\n        \"42\",\n    ]\n}\n\ncond_seq_assign_2: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(a) {\n            var t;\n            if (a) {\n                t = \"foo\";\n                a = \"bar\";\n            } else {\n                console.log(t);\n                t = 42;\n            }\n            console.log(t);\n        }\n        f(f);\n        f();\n    }\n    expect: {\n        function f(a) {\n            var t;\n            a ? (t = \"foo\", a = \"bar\") : (console.log(t), t = 42),\n            console.log(t);\n        }\n        f(f),\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n        \"42\",\n    ]\n}\n\ncond_seq_assign_3: {\n    options = {\n        assignments: true,\n        conditionals: true,\n    }\n    input: {\n        var c = 0;\n        if (this)\n            c = 1 + c, c = c + 1;\n        else\n            c = 1 + c, c = c + 1;\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        this, c = 1 + c, c += 1;\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_3271: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var i = 0, b = [];\n            if (a) {\n                b[i++] = 4,\n                b[i++] = 1;\n            } else {\n                b[i++] = 3,\n                b[i++] = 2,\n                b[i++] = 1;\n            }\n            return b;\n        }\n        console.log(f(0).pop(), f(1).pop());\n    }\n    expect: {\n        function f(a) {\n            var i = 0, b = [];\n            a ? b[i++] = 4 : (b[i++] = 3, b[i++] = 2),\n            b[i++] = 1;\n            return b;\n        }\n        console.log(f(0).pop(), f(1).pop());\n    }\n    expect_stdout: \"1 1\"\n}\n\niife_condition: {\n    options = {\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        if (function() {\n            return console;\n        }())\n            console.log(\"PASS\");\n    }\n    expect: {\n        !function() {\n            return console;\n        }() || console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nangularjs_chain: {\n    options = {\n        conditionals: true,\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        function nonComputedMember(left, right, context, create) {\n            var lhs = left();\n            if (create && create !== 1) {\n                if (lhs && lhs[right] == null) {\n                    lhs[right] = {};\n                }\n            }\n            var value = lhs != null ? lhs[right] : undefined;\n            if (context) {\n                return { context: lhs, name: right, value: value };\n            } else {\n                return value;\n            }\n        }\n    }\n    expect: {\n        function nonComputedMember(left, right, context, create) {\n            var lhs = left();\n            create && 1 !== create && lhs && null == lhs[right] && (lhs[right] = {});\n            var value = null != lhs ? lhs[right] : void 0;\n            return context ? {\n                context: lhs,\n                name: right,\n                value: value\n            } : value;\n        }\n    }\n}\n\nissue_3576: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(a) {\n            (a = -1) ? (a && (a.a = 0)) : (a && (a.a = 0));\n            a && a[c = \"PASS\"]++;\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(a) {\n            a = -1, a, a.a = 0;\n            a, a[c = \"PASS\"]++;\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3668_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                var undefined = typeof f;\n                if (!f) return undefined;\n                return;\n            } catch (e) {\n                return \"FAIL\";\n            }\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            try {\n                var undefined = typeof f;\n                if (!f) return undefined;\n            } catch (e) {\n                return \"FAIL\";\n            }\n        }\n        console.log(f());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3668_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                var undefined = typeof f;\n                if (!f) return undefined;\n                return;\n            } catch (e) {\n                return \"FAIL\";\n            }\n            FAIL;\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            try {\n                var undefined = typeof f;\n                return f ? void 0 : undefined;\n            } catch (e) {\n                return \"FAIL\";\n            }\n            FAIL;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"undefined\"\n}\n\nconditional_assignments_1: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f(a, b, c, d) {\n            a = b;\n            if (c) a = d;\n            return a;\n        }\n        function g(a, b, c, d) {\n            a = b;\n            if (c); else a = d;\n            return a;\n        }\n        console.log(f(0, \"FAIL\", 1, \"PASS\"), g(0, \"PASS\", 1, \"FAIL\"));\n    }\n    expect: {\n        function f(a, b, c, d) {\n            return a = c ? d : b, a;\n        }\n        function g(a, b, c, d) {\n            return a = c ? b : d, a;\n        }\n        console.log(f(0, \"FAIL\", 1, \"PASS\"), g(0, \"PASS\", 1, \"FAIL\"));\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nconditional_assignments_2: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        function f1(b, c, d) {\n            a = b;\n            if (c) a = d;\n            return a;\n        }\n        function f2(a, c, d) {\n            a = b;\n            if (c) a = d;\n            return a;\n        }\n        function f3(a, b, d) {\n            a = b;\n            if (c) a = d;\n            return a;\n        }\n        function f4(a, b, c) {\n            a = b;\n            if (c) a = d;\n            return a;\n        }\n    }\n    expect: {\n        function f1(b, c, d) {\n            return a = c ? d : b, a;\n        }\n        function f2(a, c, d) {\n            return a = b, c && (a = d), a;\n        }\n        function f3(a, b, d) {\n            return a = b, c && (a = d), a;\n        }\n        function f4(a, b, c) {\n            return a = b, c && (a = d), a;\n        }\n    }\n}\n\nconditional_assignments_3: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            a = \"PASS\";\n            if (b) a = a;\n            return a;\n        }(0, 1));\n    }\n    expect: {\n        console.log(function(a, b) {\n            return a = \"PASS\", b && (a = a), a;\n        }(0, 1));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3808_1: {\n    options = {\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        a = \"PASS\", [] + \"\" && (a = \"FAIL\");\n        console.log(a);\n    }\n    expect: {\n        var a;\n        a = [] + \"\" ? \"FAIL\" : \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3808_2: {\n    options = {\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        console.log((a = \"PASS\", [] + \"\" && (a = \"FAIL\")), a);\n    }\n    expect: {\n        var a;\n        console.log((a = \"PASS\", [] + \"\" && (a = \"FAIL\")), a);\n    }\n    expect_stdout: \" PASS\"\n}\n\nobject_super: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        Object.setPrototypeOf({\n            f(a) {\n                a ? this.g(\"FAIL\") : super.g(\"FAIL\");\n            },\n            g(b) {\n                console.log(b);\n            },\n        }, {\n            g() {\n                console.log(\"PASS\");\n            },\n        }).f();\n    }\n    expect: {\n        Object.setPrototypeOf({\n            f(a) {\n                a ? this.g(\"FAIL\") : super.g(\"FAIL\");\n            },\n            g(b) {\n                console.log(b);\n            },\n        }, {\n            g() {\n                console.log(\"PASS\");\n            },\n        }).f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5232_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        (function() {\n            if (Math) {\n                function f() {}\n                for (var a in [ 42 ])\n                    console.log(typeof f);\n            } else {\n                var b = null;\n                return true;\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            var b;\n            if (!Math)\n                return b = null, true;\n            function f() {}\n            for (var a in [ 42 ]) console.log(typeof f);\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_5232_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        console.log(function() {\n            if (!Math);\n            else {\n                var b = null;\n                return \"PASS\";\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var b;\n            if (Math)\n                return b = null, \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5232_3: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        console.log(function() {\n            return function() {\n                if (console)\n                    console.log(\"PASS\");\n                else {\n                    var a = null;\n                    return \"FAIL\";\n                }\n            };\n        }()());\n    }\n    expect: {\n        console.log(function() {\n            return function() {\n                var a;\n                if (!console)\n                    return a = null, \"FAIL\";\n                console.log(\"PASS\");\n            };\n        }()());\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\nissue_5334_1: {\n    options = {\n        conditionals: true,\n        hoist_props: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            if (console.log(\"PASS\"))\n                var o = true, o = {\n                    p: o += console.log(\"FAIL\"),\n                };\n        }\n        f();\n    }\n    expect: {\n        (function() {\n            var o;\n            console.log(\"PASS\") && (o = true, o = {\n                p: o += console.log(\"FAIL\"),\n            });\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5334_2: {\n    options = {\n        conditionals: true,\n        hoist_props: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            if (console.log(\"PASS\"))\n                var o = true, o = {\n                    p: o += console.log(\"FAIL\"),\n                };\n        }\n        f();\n    }\n    expect: {\n        console.log(\"PASS\") && console.log(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5544_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a;\n        if (a)\n            switch (42) {\n              case console.log(\"FAIL\"):\n              case console:\n            }\n        else\n            switch (false) {\n              case console.log(\"PASS\"):\n              case console:\n            }\n    }\n    expect: {\n        var a;\n        if (a)\n            switch (42) {\n              case console.log(\"FAIL\"):\n              case console:\n            }\n        else\n            switch (false) {\n              case console.log(\"PASS\"):\n              case console:\n            }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5544_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a;\n        if (a)\n            switch (42) {\n              case console.log(\"FAIL\"):\n              case console:\n            }\n        else\n            switch (42) {\n              case console.log(\"PASS\"):\n              case console:\n            }\n    }\n    expect: {\n        var a;\n        if (a)\n            switch (42) {\n              case console.log(\"FAIL\"):\n              case console:\n            }\n        else\n            switch (42) {\n              case console.log(\"PASS\"):\n              case console:\n            }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5546_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a;\n        if (a)\n            try {\n                console;\n            } finally {\n                console.log(\"FAIL\");\n            }\n        else\n            try {\n                console;\n            } finally {\n                console.log(\"PASS\");\n            }\n    }\n    expect: {\n        var a;\n        if (a)\n            try {\n                console;\n            } finally {\n                console.log(\"FAIL\");\n            }\n        else\n            try {\n                console;\n            } finally {\n                console.log(\"PASS\");\n            }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5546_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a;\n        if (a)\n            try {\n                console;\n            } catch (e) {}\n        else\n            try {\n                console;\n            } finally {\n                console.log(\"PASS\");\n            }\n    }\n    expect: {\n        var a;\n        if (a)\n            try {\n                console;\n            } catch (e) {}\n        else\n            try {\n                console;\n            } finally {\n                console.log(\"PASS\");\n            }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5546_3: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a;\n        if (a)\n            try {\n                FAIL;\n            } catch (e) {\n                console.log(\"FAIL\");\n            }\n        else\n            try {\n                FAIL;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n    }\n    expect: {\n        var a;\n        if (a)\n            try {\n                FAIL;\n            } catch (e) {\n                console.log(\"FAIL\");\n            }\n        else\n            try {\n                FAIL;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5666_1: {\n    options = {\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function() {\n            var b = a;\n            a ? a = b : (b++, a = b);\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (function() {\n            var b = a;\n            a = (a ? 0 : b++, b);\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5666_2: {\n    options = {\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        (function() {\n            var b = a;\n            a ? (b++, a = b) : a = b;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        (function() {\n            var b = a;\n            a = (a ? b++ : 0, b);\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5673_1: {\n    options = {\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\", b = null;\n        console.log(function(c) {\n            return c || (b ? c : (c = a) && c);\n        }());\n    }\n    expect: {\n        var a = \"PASS\", b = null;\n        console.log(function(c) {\n            return c || (b || (c = a)) && c;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5673_2: {\n    options = {\n        conditionals: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        console.log(function(b) {\n            return (b = a) ? b : (b = a) && b;\n        }());\n    }\n    expect: {\n        var a = \"PASS\";\n        console.log(function(b) {\n            return a || (b = a) && b;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5694: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        FORCE_EXEC = \"async()=>{}\";\n        var a = \"foo\";\n        // Node.js v0.12~6 (vm): foo\n        console.log((NaN = a) ? NaN : 42);\n    }\n    expect: {\n        FORCE_EXEC = \"async()=>{}\";\n        var a = \"foo\";\n        console.log((NaN = a) ? NaN : 42);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5712: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        var a = 0;\n        a || (++a).toString() && a && console.log(\"PASS\");\n    }\n    expect: {\n        var a = 0;\n        a || (++a).toString() && a && console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5722: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        keep_fnames: true,\n        side_effects: true,\n    }\n    input: {\n        var a = true;\n        a && function f() {\n            return 42;\n        }(a++) ? null + (console.log(\"PASS\") && a++) : \"\";\n    }\n    expect: {\n        var a = true;\n        a && (void a++, console.log(\"PASS\")) && a++;\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/const.js",
    "content": "mangle_block: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var o = \"PASS\";\n        {\n            const a = \"FAIL\";\n        }\n        console.log(o);\n    }\n    expect: {\n        var o = \"PASS\";\n        {\n            const a = \"FAIL\";\n        }\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nmangle_block_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var o = \"PASS\";\n        {\n            const a = \"FAIL\";\n        }\n        console.log(o);\n    }\n    expect: {\n        var o = \"PASS\";\n        {\n            const c = \"FAIL\";\n        }\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_1: {\n    mangle = {}\n    input: {\n        try {\n            throw \"eeeee\";\n        } catch (c) {\n            const e = typeof d;\n        }\n        console.log(typeof a, typeof b);\n    }\n    expect: {\n        try {\n            throw \"eeeee\";\n        } catch (o) {\n            const e = typeof d;\n        }\n        console.log(typeof a, typeof b);\n    }\n    expect_stdout: \"undefined undefined\"\n}\n\nmangle_catch_2: {\n    mangle = {}\n    input: {\n        console.log(function f() {\n            try {} catch (e) {\n                const f = 0;\n            }\n        }());\n    }\n    expect: {\n        console.log(function o() {\n            try {} catch (c) {\n                const o = 0;\n            }\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nretain_block: {\n    options = {}\n    input: {\n        {\n            const a = \"FAIL\";\n        }\n        var a = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        {\n            const a = \"FAIL\";\n        }\n        var a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\nretain_catch: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {} catch (a) {\n            const a = \"aa\";\n        }\n    }\n    expect: {\n        try {} catch (a) {\n            const a = \"aa\";\n        }\n    }\n    expect_stdout: true\n}\n\nif_dead_branch: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n    }\n    input: {\n        console.log(function() {\n            if (0) {\n                const a = 0;\n            }\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            0;\n            {\n                const a = void 0;\n            }\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nretain_tail_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                const b = \"bar\";\n                while (console.log(\"baz\"));\n                console.log(b);\n            } else {\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                const b = \"bar\";\n                while (console.log(\"baz\"));\n                console.log(b);\n            } else {\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: true\n}\n\nretain_tail_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                const b = \"baz\";\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                const b = \"baz\";\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: true\n}\n\nmerge_vars_1: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        const a = console;\n        console.log(typeof a);\n        var b = typeof a;\n        console.log(b);\n    }\n    expect: {\n        const a = console;\n        console.log(typeof a);\n        var b = typeof a;\n        console.log(b);\n    }\n    expect_stdout: [\n        \"object\",\n        \"object\",\n    ]\n}\n\nmerge_vars_2: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            var b = function f() {\n                const c = a && f;\n                c.var += 0;\n            }();\n            console.log(b);\n        })(1 && --a);\n    }\n    expect: {\n        var a = 0;\n        1 && --a,\n        b = function f() {\n            const c = a && f;\n            c.var += 0;\n        }(),\n        void console.log(b);\n        var b;\n    }\n    expect_stdout: \"undefined\"\n}\n\nmerge_vars_3: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        {\n            const a = 0;\n            var b = console;\n            console.log(typeof b);\n        }\n        var a = 1;\n        console.log(typeof a);\n    }\n    expect: {\n        {\n            const a = 0;\n            var b = console;\n            console.log(typeof b);\n        }\n        var a = 1;\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nmerge_vars_4: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        console.log(typeof a);\n        {\n            var b = console;\n            console.log(typeof b);\n            const a = 0;\n        }\n    }\n    expect: {\n        var a = 1;\n        console.log(typeof a);\n        {\n            var b = console;\n            console.log(typeof b);\n            const a = 0;\n        }\n    }\n    expect_stdout: true\n}\n\nuse_before_init_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        a = \"foo\";\n        const a = \"bar\";\n    }\n    expect: {\n        a = \"foo\";\n        const a = \"bar\";\n    }\n    expect_stdout: true\n}\n\nuse_before_init_2: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            a = \"foo\";\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        const a = \"bar\";\n    }\n    expect: {\n        try {\n            a = \"foo\";\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        const a = \"bar\";\n    }\n    expect_stdout: true\n}\n\nuse_before_init_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            a;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        const a = 42;\n    }\n    expect: {\n        try {\n            a;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        const a = 42;\n    }\n    expect_stdout: true\n}\n\nuse_before_init_4: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        try {\n            console.log(a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        const a = \"FAIL\";\n    }\n    expect: {\n        try {\n            console.log(a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        const a = \"FAIL\";\n    }\n    expect_stdout: true\n}\n\ncollapse_block: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        unsafe: true,\n    }\n    input: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n    }\n    expect: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n    }\n    expect_stdout: \"object\"\n}\n\nreduce_block_1: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n    }\n    expect: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n    }\n    expect_stdout: \"object\"\n}\n\nreduce_block_2: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nreduce_block_2_toplevel: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nhoist_props: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        {\n            const o = {\n                p: \"PASS\",\n            };\n            console.log(o.p);\n        }\n    }\n    expect: {\n        {\n            const o = {\n                p: \"PASS\",\n            };\n            console.log(o.p);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nloop_block_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        do {\n            const o = console;\n            console.log(typeof o.log);\n        } while (!console);\n    }\n    expect: {\n        do {\n            const o = console;\n            console.log(typeof o.log);\n        } while (!console);\n    }\n    expect_stdout: \"function\"\n}\n\nloop_block_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        do {\n            const o = {};\n            (function() {\n                console.log(typeof this, o.p++);\n            })();\n        } while (!console);\n    }\n    expect: {\n        do {\n            const o = {};\n            (function() {\n                console.log(typeof this, o.p++);\n            })();\n        } while (!console);\n    }\n    expect_stdout: \"object NaN\"\n}\n\ndo_continue: {\n    options = {\n        loops: true,\n    }\n    input: {\n        try {\n            do {\n                {\n                    const a = 0;\n                    continue;\n                }\n            } while ([ A ]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            do {\n                const a = 0;\n                continue;\n            } while ([ A ]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\ncatch_ie8_1: {\n    options = {\n        ie: true,\n        unused: true,\n    }\n    input: {\n        try {} catch (a) {}\n        console.log(function a() {\n            const a = 0;\n        }());\n    }\n    expect: {\n        try {} catch (a) {}\n        console.log(function() {\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\ncatch_ie8_2: {\n    options = {\n        dead_code: true,\n        ie: true,\n        passes: 2,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {} catch (a) {\n            const b = 0;\n        }\n        try {} catch (b) {}\n        console.log(function() {\n            return this;\n        }().b);\n    }\n    expect: {\n        console.log(function() {\n            return this;\n        }().b);\n    }\n    expect_stdout: \"undefined\"\n}\n\ndead_block_after_return: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        (function(a) {\n            console.log(a);\n            return;\n            {\n                const a = 0;\n            }\n        })();\n    }\n    expect: {\n        (function(a) {\n            console.log(a);\n            return;\n            {\n                const a = void 0;\n            }\n        })();\n    }\n    expect_stdout: true\n}\n\nif_return_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(b) {\n            if (console) {\n                const b = a;\n                return b;\n            } else\n                while (console.log(\"FAIL 1\"));\n            return b;\n        }\n        console.log(f(\"FAIL 2\"));\n    }\n    expect: {\n        var a = \"PASS\";\n        function f(b) {\n            if (console) {\n                const b = a;\n                return b;\n            } else\n                while (console.log(\"FAIL 1\"));\n            return b;\n        }\n        console.log(f(\"FAIL 2\"));\n    }\n    expect_stdout: true\n}\n\ndo_if_continue_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        do {\n            if (console) {\n                console.log(\"PASS\");\n                {\n                    const a = 0;\n                    var b;\n                    continue;\n                }\n            }\n        } while (b);\n    }\n    expect: {\n        do {\n            if (console) {\n                console.log(\"PASS\");\n                {\n                    const a = 0;\n                    var b;\n                }\n            }\n        } while (b);\n    }\n    expect_stdout: \"PASS\"\n}\n\ndo_if_continue_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        do {\n            if (console) {\n                console.log(\"PASS\");\n                {\n                    const a = 0;\n                    A = 0;\n                    continue;\n                }\n            }\n        } while (A);\n    }\n    expect: {\n        do {\n            if (console) {\n                console.log(\"PASS\");\n                {\n                    const a = 0;\n                    A = 0;\n                }\n            }\n        } while (A);\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_unused: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            const b = a, c = b;\n            0 && c.p++;\n        }\n        console.log(f());\n    }\n    expect: {\n        function f(a) {\n            const b = a;\n            b;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"undefined\"\n}\n\nlegacy_scope: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = 42;\n        }\n        var a;\n    }\n    expect: {\n        {\n            const a = 42;\n        }\n        var a;\n    }\n    expect_stdout: true\n}\n\nhoist_vars: {\n    options = {\n        hoist_vars: true,\n    }\n    input: {\n        {\n            const a = \"FAIL\";\n            var b = 42;\n        }\n        var a = \"PASS\";\n        console.log(a, b);\n    }\n    expect: {\n        var b;\n        {\n            const a = \"FAIL\";\n            b = 42;\n        }\n        var a = \"PASS\";\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\nissue_4191: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = function() {};\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        {\n            const a = function() {};\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nissue_4193: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {} catch (e) {\n            var a;\n        } finally {\n            const a = 0;\n        }\n        console.log(a);\n    }\n    expect: {\n        var a;\n        {\n            const a = 0;\n        }\n        console.log(a);\n    }\n    expect_stdout: true\n}\n\nissue_4195: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        console.log(function f(a) {\n            (function a() {\n                {\n                    const b = f, a = 0;\n                    b;\n                }\n            })();\n            a && f;\n        }());\n    }\n    expect: {\n        console.log(function f(o) {\n            (function o() {\n                {\n                    const n = f, o = 0;\n                    n;\n                }\n            })();\n            o && f;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4197: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0;\n        try {\n            const b = function() {\n                a = 1;\n                b[1];\n            }();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = 0;\n        try {\n            const b = function() {\n                a = 1;\n                b[1];\n            }();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4198: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                {\n                    const e = \"FAIL\";\n                }\n                return function() {\n                    return e;\n                }();\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                {\n                    const e = \"FAIL\";\n                }\n                return function() {\n                    return e;\n                }();\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4202: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        {\n            const o = {};\n            (function() {\n                function f() {\n                    o.p = 42;\n                }\n                f(f);\n            })();\n            console.log(o.p++);\n        }\n    }\n    expect: {\n        {\n            const o = {};\n            function f() {\n                o.p = 42;\n            }\n            f(f);\n            console.log(o.p++);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\nissue_4205: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = function(b) {\n            var c = function() {\n                switch (0) {\n                  case a:\n                    return 0;\n                  case b:\n                  case console.log(\"PASS\"):\n                }\n            }();\n            {\n                const b = c;\n            }\n        }();\n    }\n    expect: {\n        var a = function(b) {\n            var c = function() {\n                switch (0) {\n                  case a:\n                    return 0;\n                  case b:\n                  case console.log(\"PASS\"):\n                }\n            }();\n            {\n                const b = c;\n            }\n        }();\n    }\n    expect_stdout: true\n}\n\nissue_4207: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = function() {};\n            console.log(a.length);\n        }\n    }\n    expect: {\n        {\n            const a = function() {};\n            console.log(a.length);\n        }\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4218: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = function() {};\n            var b = 0 * a;\n        }\n        console.log(typeof a, b);\n    }\n    expect: {\n        {\n            const a = function() {};\n            var b = 0 * a;\n        }\n        console.log(typeof a, b);\n    }\n    expect_stdout: true\n}\n\nissue_4210: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        (function() {\n            try {\n                throw 42;\n            } catch (e) {\n                const a = typeof e;\n                console.log(a);\n            } finally {\n                return a = \"foo\";\n            }\n        })();\n        console.log(typeof a);\n    }\n    expect: {\n        (function() {\n            try {\n                throw 42;\n            } catch (e) {\n                const a = typeof e;\n                console.log(a);\n            } finally {\n                return a = \"foo\";\n            }\n        })();\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nissue_4212_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log({\n            get b() {\n                const a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect: {\n        console.log({\n            get b() {\n                const a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect_stdout: true\n}\n\nissue_4212_2: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        console.log({\n            get b() {\n                const a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect: {\n        console.log({\n            get b() {\n                const a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect_stdout: true\n}\n\nissue_4216: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n    }\n    input: {\n        if (a = 0) {\n            const a = 0;\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        a = 0;\n        {\n            const a = void 0;\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nskip_braces: {\n    beautify = {\n        beautify: true,\n        braces: true,\n    }\n    input: {\n        if (console)\n            const a = 42;\n        else\n            const b = null;\n        console.log(typeof a, typeof b);\n    }\n    expect_exact: [\n        \"if (console) const a = 42; else const b = null;\",\n        \"\",\n        \"console.log(typeof a, typeof b);\",\n    ]\n    expect_stdout: true\n}\n\nissue_4220: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        sequences: true,\n        toplevel: true,\n    }\n    input: {\n        if (console) {\n            var o = console;\n            for (var k in o);\n        } else {\n            const a = 0;\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        if (console) {\n            var o;\n            for (var k in console);\n        } else {\n            const a = 0;\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nissue_4222: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = function() {\n                return function() {};\n            };\n            var b = a();\n        }\n        b();\n        console.log(typeof a);\n    }\n    expect: {\n        {\n            const a = function() {\n                return function() {};\n            };\n            var b = a();\n        }\n        b();\n        console.log(typeof a);\n    }\n    expect_stdout: true\n}\n\nissue_4225: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        const a = void typeof b;\n        const b = 42;\n        console.log(a, b);\n    }\n    expect: {\n        const a = void b;\n        const b = 42;\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\nissue_4229: {\n    options = {\n        ie: true,\n        side_effects: true,\n    }\n    input: {\n        (function f() {\n            f;\n            const f = 42;\n        })();\n    }\n    expect: {\n        (function f() {\n            f;\n            const f = 42;\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_4231: {\n    options = {\n        ie: true,\n        side_effects: true,\n    }\n    input: {\n        typeof a == 0;\n        console.log(typeof function a() {\n            const a = 0;\n        });\n    }\n    expect: {\n        console.log(typeof function a() {\n            const a = 0;\n        });\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4245: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        const a = f();\n        function f() {\n            typeof a;\n        }\n    }\n    expect: {\n        const a = f();\n        function f() {\n            a,\n            1;\n        }\n    }\n    expect_stdout: true\n}\n\nissue_4248: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                a = \"PASS\";\n                b[a];\n                const b = 0;\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                a = \"PASS\";\n                b[a];\n                const b = 0;\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4261_1: {\n    options = {\n        inline: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = 42;\n            (function() {\n                function f() {\n                    console.log(a);\n                }\n                function g() {\n                    while (f());\n                }\n                (function() {\n                    while (g());\n                })();\n            })();\n        }\n    }\n    expect: {\n        {\n            const a = 42;\n            (function() {\n                function g() {\n                    while (void console.log(a));\n                }\n                (function() {\n                    while (g());\n                })();\n            })();\n        }\n    }\n    expect_stdout: \"42\"\n}\n\nissue_4261_2: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        {\n            const a = 42;\n            (function() {\n                function f() {\n                    console.log(a);\n                }\n                function g() {\n                    while (f());\n                }\n                (function() {\n                    while (g());\n                })();\n            })();\n        }\n    }\n    expect: {\n        {\n            const a = 42;\n            function g() {\n                while (void console.log(a));\n            }\n            while (g());\n        }\n    }\n    expect_stdout: \"42\"\n}\n\nissue_4274_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;;) {\n            if (console.log(\"PASS\")) {\n                const a = 0;\n            } else {\n                break;\n                var a;\n            }\n        }\n    }\n    expect: {\n        for (; console.log(\"PASS\");) {\n            {\n                const a = 0;\n            }\n            var a;\n        }\n    }\n    expect_stdout: true\n}\n\nissue_4274_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;;) {\n            if (!console.log(\"PASS\")) {\n                break;\n                var a;\n            } else {\n                const a = 0;\n            }\n        }\n    }\n    expect: {\n        for (; console.log(\"PASS\");) {\n            {\n                const a = 0;\n            }\n            var a;\n        }\n    }\n    expect_stdout: true\n}\n\nissue_4290_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        const a = 0;\n        var a;\n    }\n    expect: {\n        const a = 0;\n        var a;\n    }\n    expect_stdout: true\n}\n\nissue_4305_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            const arguments = function() {\n                while (console.log(\"PASS\"));\n            };\n            arguments();\n        })();\n    }\n    expect: {\n        (function() {\n            const arguments = function() {\n                while (console.log(\"PASS\"));\n            };\n            arguments();\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_4305_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            const a = function() {\n                while (console.log(\"aaaaa\"));\n            };\n            a();\n        })();\n    }\n    expect: {\n        (function(a) {\n            const a = function() {\n                while (console.log(\"aaaaa\"));\n            };\n            a();\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_4365_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        const arguments = 42;\n    }\n    expect: {\n        const arguments = 42;\n    }\n    expect_stdout: true\n}\n\nissue_4365_2: {\n    options = {\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        const arguments = 42;\n    }\n    expect: {\n        const arguments = 42;\n    }\n    expect_stdout: true\n}\n\nissue_4527: {\n    mangle = {}\n    input: {\n        (function() {\n            try {\n                throw 1;\n            } catch (a) {\n                try {\n                    const a = FAIL;\n                } finally {\n                    if (!b)\n                        return console.log(\"aaaa\");\n                }\n            }\n            var b;\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                throw 1;\n            } catch (a) {\n                try {\n                    const a = FAIL;\n                } finally {\n                    if (!t)\n                        return console.log(\"aaaa\");\n                }\n            }\n            var t;\n        })();\n    }\n    expect_stdout: \"aaaa\"\n}\n\nissue_4689: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"PASS\";\n        console.log(a);\n        for (const a in 42);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"PASS\";\n        console.log(a);\n        for (const a in 42);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4691: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        toplevel: true,\n    }\n    input: {\n        function A() {}\n        A.prototype.f = function() {\n            if (!this)\n                return;\n            const a = \"PA\";\n            function g(b) {\n                h(a + b);\n            }\n            [ \"SS\" ].forEach(function(c) {\n                g(c);\n            });\n        };\n        function h(d) {\n            console.log(d);\n        }\n        new A().f();\n    }\n    expect: {\n        function A() {}\n        A.prototype.f = function() {\n            if (this) {\n                const a = \"PA\";\n                [ \"SS\" ].forEach(function(c) {\n                    g(c);\n                });\n                function g(b) {\n                    h(a + b);\n                }\n            }\n        };\n        function h(d) {\n            console.log(d);\n        }\n        new A().f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4848: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            a(function() {\n                console.log(b);\n            });\n            if (!console)\n                return;\n            const b = \"PASS\";\n        }\n        var g;\n        f(function(h) {\n            g = h;\n        });\n        g();\n    }\n    expect: {\n        function f(a) {\n            a(function() {\n                console.log(b);\n            });\n            if (!console)\n                return;\n            const b = \"PASS\";\n        }\n        var g;\n        f(function(h) {\n            g = h;\n        });\n        g();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4954_1: {\n    rename = true\n    input: {\n        \"use strict\";\n        (function() {\n            {\n                const a = \"foo\";\n                console.log(a);\n            }\n            {\n                const a = \"bar\";\n                console.log(a);\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            {\n                const a = \"foo\";\n                console.log(a);\n            }\n            {\n                const b = \"bar\";\n                console.log(b);\n            }\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4954_2: {\n    mangle = {}\n    input: {\n        \"use strict\";\n        const a = null;\n        (function(b) {\n            for (const a in null);\n            for (const a in b)\n                console.log(\"PASS\");\n        })([ null ]);\n    }\n    expect: {\n        \"use strict\";\n        const a = null;\n        (function(o) {\n            for (const n in null);\n            for (const n in o)\n                console.log(\"PASS\");\n        })([ null ]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4960: {\n    mangle = {}\n    input: {\n        \"use strict\";\n        var a;\n        (function() {\n            {\n                const a = console.log(\"PASS\");\n            }\n            try {} catch (e) {\n                const a = console.log(\"FAIL\");\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        var a;\n        (function() {\n            {\n                const o = console.log(\"PASS\");\n            }\n            try {} catch (o) {\n                const c = console.log(\"FAIL\");\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4965_1: {\n    mangle = {}\n    input: {\n        \"use strict\";\n        try {\n            c;\n        } catch (a) {\n            {\n                const a = 1;\n            }\n            {\n                const a = console.log(typeof c);\n            }\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            c;\n        } catch (t) {\n            {\n                const c = 1;\n            }\n            {\n                const t = console.log(typeof c);\n            }\n        }\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_4965_2: {\n    mangle = {}\n    input: {\n        \"use strict\";\n        try {\n            throw 1;\n        } catch (e) {\n            try {\n                {\n                    const e = 2;\n                }\n            } finally {\n                const e = 3;\n                console.log(typeof t);\n            }\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            throw 1;\n        } catch (o) {\n            try {\n                {\n                    const t = 2;\n                }\n            } finally {\n                const o = 3;\n                console.log(typeof t);\n            }\n        }\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5254: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        do {\n            (function() {\n                const a = console.log;\n                a && a(\"foo\");\n            })();\n        } while (console.log(\"bar\"));\n    }\n    expect: {\n        do {\n            const a = console.log;\n            a && a(\"foo\");\n        } while (console.log(\"bar\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_5260: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"foo\", o;\n        while (console.log(\"bar\"));\n        o = {\n            baz: function(b) {\n                console.log(a, b);\n            },\n        };\n        for (const a in o)\n            o[a](a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"foo\", o;\n        while (console.log(\"bar\"));\n        o = {\n            baz: function(b) {\n                console.log(a, b);\n            },\n        };\n        for (const a in o)\n            o[a](a);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo baz\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5319: {\n    options = {\n        collapse_vars: true,\n        merge_vars: true,\n    }\n    input: {\n        (function(a, c) {\n            var b = a, c = b;\n            {\n                const a = c;\n                console.log(c());\n            }\n        })(function() {\n            return \"PASS\";\n        });\n    }\n    expect: {\n        (function(a, c) {\n            var b = a, c;\n            {\n                const a = c = b;\n                console.log(c());\n            }\n        })(function() {\n            return \"PASS\";\n        });\n    }\n    expect_stdout: true\n}\n\nissue_5338: {\n    options = {\n        unused: true,\n    }\n    input: {\n        const a = a;\n    }\n    expect: {\n        const a = a;\n    }\n    expect_stdout: true\n}\n\nissue_5476: {\n    mangle = {\n        keep_fargs: true,\n    }\n    input: {\n        console.log(function(n) {\n            const a = 42;\n        }());\n    }\n    expect: {\n        console.log(function(n) {\n            const o = 42;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5516: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            try {} catch (a) {\n                (function f() {\n                    a;\n                })();\n            }\n            {\n                const a = function() {};\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            try {} catch (a) {\n                void a;\n            }\n            {\n                const a = function() {};\n                return a;\n            }\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_5580_1: {\n    mangle = {}\n    input: {\n        \"use strict\";\n        console.log(function(a, b, c) {\n            try {\n                FAIL;\n            } catch (e) {\n                return function() {\n                    var d = e, i, j;\n                    {\n                        const e = j;\n                    }\n                    return a;\n                }();\n            } finally {\n                const e = 42;\n            }\n        }(\"PASS\"));\n    }\n    expect: {\n        \"use strict\";\n        console.log(function(r, n, t) {\n            try {\n                FAIL;\n            } catch (o) {\n                return function() {\n                    var n = o, t, c;\n                    {\n                        const o = c;\n                    }\n                    return r;\n                }();\n            } finally {\n                const c = 42;\n            }\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5580_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                return function() {\n                    console.log(e);\n                    {\n                        const e = \"FAIL 1\";\n                    }\n                }();\n            } finally {\n                const e = \"FAIL 2\";\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                console.log(e);\n                {\n                    const e = \"FAIL 1\";\n                }\n                return;\n            } finally {\n                var e = \"FAIL 2\";\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5591: {\n    options = {\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console.log(\"baz\"))\n                    return;\n                else {\n                    const a = 42;\n                    return;\n                }\n                break;\n              case null:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console.log(\"baz\"))\n                    return;\n                else {\n                    const a = 42;\n                    return;\n                }\n              case null:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5656: {\n    options = {\n        collapse_vars: true,\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = a;\n            b++;\n            {\n                const a = b;\n            }\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = a;\n            {\n                const a = ++b;\n            }\n        }());\n    }\n    expect_stdout: true\n}\n\nissue_5660: {\n    options = {\n        merge_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            try {\n                a;\n                var b;\n                return b;\n            } catch (e) {\n                var a = \"FAIL\";\n                const b = null;\n                return a;\n            }\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            try {\n                var b;\n                return b;\n            } catch (e) {\n                var a = \"FAIL\";\n                const b = null;\n                return a;\n            }\n        }\n        console.log(f());\n    }\n    expect_stdout: true\n}\n\nissue_5787: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            const a = 42;\n            switch (a) {\n              case 42:\n                const a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            const a = 42;\n            switch (a) {\n              case 42:\n                const a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect_stdout: true\n}\n\nissue_5930_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var a;\n            (f = a) && f();\n            {\n                const a = 42;\n                var f;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a;\n            (f = a) && f();\n            {\n                const a = 42;\n                var f;\n            }\n        }());\n    }\n    expect_stdout: true\n}\n\nissue_5930_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            f = function g(a) {\n                a.p;\n            }();\n            f && f();\n            {\n                const a = 42;\n                var b = false;\n                var f;\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            var a;\n            (f = void a.p) && f();\n            {\n                const a = 42;\n                var f;\n            }\n        })();\n    }\n    expect_stdout: TypeError(\"Cannot read properties of undefined\")\n    node_version: \">=4\"\n}\n"
  },
  {
    "path": "test/compress/dead-code.js",
    "content": "dead_code_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            a();\n            b();\n            x = 10;\n            return;\n            if (x) {\n                y();\n            }\n        }\n    }\n    expect: {\n        function f() {\n            a();\n            b();\n            x = 10;\n            return;\n        }\n    }\n}\n\ndead_code_2_should_warn: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            g();\n            x = 10;\n            throw new Error(\"foo\");\n            // completely discarding the `if` would introduce some\n            // bugs.  UglifyJS v1 doesn't deal with this issue; in v2\n            // we copy any declarations to the upper scope.\n            if (x) {\n                y();\n                var x;\n                function g(){};\n                // but nested declarations should not be kept.\n                (function(){\n                    var q;\n                    function y(){};\n                })();\n            }\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            g();\n            x = 10;\n            throw new Error(\"foo\");\n            {\n                var x;\n                function g(){};\n            }\n        }\n        f();\n    }\n    expect_stdout: true\n    expect_warnings: [\n        \"WARN: Dropping unreachable code [test/compress/dead-code.js:8,12]\",\n    ]\n}\n\ndead_code_constant_boolean_should_warn_more: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        side_effects: true,\n    }\n    input: {\n        while (!((foo && bar) || (x + \"0\"))) {\n            console.log(\"unreachable\");\n            var foo;\n            function bar() {}\n        }\n        for (var x = 10, y; x && (y || x) && (!typeof x); ++x) {\n            asdf();\n            foo();\n            var moo;\n        }\n        bar();\n    }\n    expect: {\n        {\n            var foo;\n            function bar() {}\n        }\n        // nothing for the while\n        // as for the for, it should keep:\n        var x = 10, y;\n        var moo;\n        bar();\n    }\n    expect_stdout: true\n    expect_warnings: [\n        \"WARN: + in boolean context always true [test/compress/dead-code.js:1,33]\",\n        \"WARN: Boolean || always true [test/compress/dead-code.js:1,16]\",\n        \"WARN: Dropping unreachable code [test/compress/dead-code.js:1,45]\",\n        \"WARN: Boolean expression always true [test/compress/dead-code.js:6,47]\",\n        \"WARN: Boolean && always false [test/compress/dead-code.js:6,28]\",\n        \"WARN: Dropping unreachable code [test/compress/dead-code.js:6,63]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:1,15]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/dead-code.js:6,28]\",\n    ]\n    node_version: \"<=4\"\n}\n\ntrim_try: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {\n            var a;\n        } catch (e) {\n            console.log(\"FAIL\");\n        } finally {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a;\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\ntrim_finally_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {\n            console.log(\"PASS\");\n        } finally {\n            var a;\n        }\n    }\n    expect: {\n        console.log(\"PASS\");\n        var a;\n    }\n    expect_stdout: \"PASS\"\n}\n\ntrim_finally_2: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {\n            console.log(\"PASS\");\n        } catch (e) {\n        } finally {\n            var a;\n        }\n    }\n    expect: {\n        try {\n            console.log(\"PASS\");\n            var a;\n        } catch (e) {\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\ntry_catch_finally: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        var a = 1;\n        !function() {\n            try {\n                if (false) throw x;\n            } catch (a) {\n                var a = 2;\n                console.log(\"FAIL\");\n            } finally {\n                a = 3;\n                console.log(\"PASS\");\n            }\n        }();\n        try {\n            console.log(a);\n        } finally {\n        }\n    }\n    expect: {\n        var a = 1;\n        !function() {\n            var a;\n            a = 3;\n            console.log(\"PASS\");\n        }();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"1\",\n    ]\n}\n\ncollapse_vars_assignment: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        passes: 2,\n        unused: true,\n    }\n    input: {\n        function f0(c) {\n            var a = 3 / c;\n            return a = a;\n        }\n    }\n    expect: {\n        function f0(c) {\n            return 3 / c;\n        }\n    }\n}\n\ncollapse_vars_lvalues_drop_assign: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        unused: true,\n    }\n    input: {\n        function f0(x) { var i = ++x; return x += i; }\n        function f1(x) { var a = (x -= 3); return x += a; }\n        function f2(x) { var z = x, a = ++z; return z += a; }\n    }\n    expect: {\n        function f0(x) { var i = ++x; return x + i; }\n        function f1(x) { var a = (x -= 3); return x + a; }\n        function f2(x) { var z = x, a = ++z; return z + a; }\n    }\n}\n\ncollapse_vars_misc: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        unused: true,\n    }\n    input: {\n        function f10(x) { var a = 5, b = 3; return a += b; }\n        function f11(x) { var a = 5, b = 3; return a += --b; }\n    }\n    expect: {\n        function f10(x) { return 5 + 3; }\n        function f11(x) { var b = 3; return 5 + --b; }\n    }\n}\n\nreturn_assignment: {\n    options = {\n        dead_code: true,\n        unused: true,\n    }\n    input: {\n        function f1(a, b, c) {\n            return a = x(), b = y(), b = a && (c >>= 5);\n        }\n        function f2() {\n            return e = x();\n        }\n        function f3(e) {\n            return e = x();\n        }\n        function f4() {\n            var e;\n            return e = x();\n        }\n        function f5(a) {\n            try {\n                return a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f6(a) {\n            try {\n                return a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function y() {\n            console.log(\"y\");\n        }\n        function test(inc) {\n            var counter = 0;\n            x = function() {\n                counter += inc;\n                if (inc < 0) throw counter;\n                return counter;\n            };\n            [ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {\n                e = null;\n                try {\n                    i += 1;\n                    console.log(\"result \" + f(10 * i, 100 * i, 1000 * i));\n                } catch (x) {\n                    console.log(\"caught \" + x);\n                }\n                if (null !== e) console.log(\"e: \" + e);\n            });\n        }\n        var x, e;\n        test(1);\n        test(-1);\n    }\n    expect: {\n        function f1(a, b, c) {\n            return a = x(), y(), a && (c >> 5);\n        }\n        function f2() {\n            return e = x();\n        }\n        function f3(e) {\n            return x();\n        }\n        function f4() {\n            return x();\n        }\n        function f5(a) {\n            try {\n                return x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f6(a) {\n            try {\n                return a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function y() {\n            console.log(\"y\");\n        }\n        function test(inc) {\n            var counter = 0;\n            x = function() {\n                counter += inc;\n                if (inc < 0) throw counter;\n                return counter;\n            };\n            [ f1, f2, f3, f4, f5, f6 ].forEach(function(f, i) {\n                e = null;\n                try {\n                    i += 1;\n                    console.log(\"result \" + f(10 * i, 100 * i, 1000 * i));\n                } catch (x) {\n                    console.log(\"caught \" + x);\n                }\n                if (null !== e) console.log(\"e: \" + e);\n            });\n        }\n        var x, e;\n        test(1);\n        test(-1);\n    }\n    expect_stdout: [\n        \"y\",\n        \"result 31\",\n        \"result 2\",\n        \"e: 2\",\n        \"result 3\",\n        \"result 4\",\n        \"result 5\",\n        \"6\",\n        \"result 6\",\n        \"caught -1\",\n        \"caught -2\",\n        \"caught -3\",\n        \"caught -4\",\n        \"50\",\n        \"result undefined\",\n        \"60\",\n        \"caught -6\",\n    ]\n}\n\nthrow_assignment: {\n    options = {\n        dead_code: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            throw a = x();\n        }\n        function f2(a) {\n            throw a = x();\n        }\n        function f3() {\n            var a;\n            throw a = x();\n        }\n        function f4() {\n            try {\n                throw a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f5(a) {\n            try {\n                throw a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f6() {\n            var a;\n            try {\n                throw a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f7() {\n            try {\n                throw a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function f8(a) {\n            try {\n                throw a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function f9() {\n            var a;\n            try {\n                throw a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function test(inc) {\n            var counter = 0;\n            x = function() {\n                counter += inc;\n                if (inc < 0) throw counter;\n                return counter;\n            };\n            [ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {\n                a = null;\n                try {\n                    f(10 * (1 + i));\n                } catch (x) {\n                    console.log(\"caught \" + x);\n                }\n                if (null !== a) console.log(\"a: \" + a);\n            });\n        }\n        var x, a;\n        test(1);\n        test(-1);\n    }\n    expect: {\n        function f1() {\n            throw a = x();\n        }\n        function f2(a) {\n            throw x();\n        }\n        function f3() {\n            throw x();\n        }\n        function f4() {\n            try {\n                throw a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f5(a) {\n            try {\n                throw a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f6() {\n            var a;\n            try {\n                throw a = x();\n            } catch (b) {\n                console.log(a);\n            }\n        }\n        function f7() {\n            try {\n                throw a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function f8(a) {\n            try {\n                throw a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function f9() {\n            var a;\n            try {\n                throw a = x();\n            } finally {\n                console.log(a);\n            }\n        }\n        function test(inc) {\n            var counter = 0;\n            x = function() {\n                counter += inc;\n                if (inc < 0) throw counter;\n                return counter;\n            };\n            [ f1, f2, f3, f4, f5, f6, f7, f8, f9 ].forEach(function(f, i) {\n                a = null;\n                try {\n                    f(10 * (1 + i));\n                } catch (x) {\n                    console.log(\"caught \" + x);\n                }\n                if (null !== a) console.log(\"a: \" + a);\n            });\n        }\n        var x, a;\n        test(1);\n        test(-1);\n    }\n    expect_stdout: [\n        \"caught 1\",\n        \"a: 1\",\n        \"caught 2\",\n        \"caught 3\",\n        \"4\",\n        \"a: 4\",\n        \"5\",\n        \"6\",\n        \"7\",\n        \"caught 7\",\n        \"a: 7\",\n        \"8\",\n        \"caught 8\",\n        \"9\",\n        \"caught 9\",\n        \"caught -1\",\n        \"caught -2\",\n        \"caught -3\",\n        \"null\",\n        \"50\",\n        \"undefined\",\n        \"null\",\n        \"caught -7\",\n        \"80\",\n        \"caught -8\",\n        \"undefined\",\n        \"caught -9\",\n    ]\n}\n\nissue_2597: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f(b) {\n            try {\n                try {\n                    throw \"foo\";\n                } catch (e) {\n                    return b = true;\n                }\n            } finally {\n                b && (a = \"PASS\");\n            }\n        }\n        var a = \"FAIL\";\n        f();\n        console.log(a);\n    }\n    expect: {\n        function f(b) {\n            try {\n                try {\n                    throw \"foo\";\n                } catch (e) {\n                    return b = true;\n                }\n            } finally {\n                b && (a = \"PASS\");\n            }\n        }\n        var a = \"FAIL\";\n        f();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2666: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f(a) {\n            return a = {\n                p: function() {\n                    return a;\n                }\n            };\n        }\n        console.log(typeof f().p());\n    }\n    expect: {\n        function f(a) {\n            return a = {\n                p: function() {\n                    return a;\n                }\n            };\n        }\n        console.log(typeof f().p());\n    }\n    expect_stdout: \"object\"\n}\n\nissue_2692: {\n    options = {\n        dead_code: true,\n        reduce_vars: false,\n    }\n    input: {\n        function f(a) {\n            return a = g;\n            function g() {\n                return a;\n            }\n        }\n        console.log(typeof f()());\n    }\n    expect: {\n        function f(a) {\n            return a = g;\n            function g() {\n                return a;\n            }\n        }\n        console.log(typeof f()());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2701: {\n    options = {\n        dead_code: true,\n        inline: false,\n    }\n    input: {\n        function f(a) {\n            return a = function() {\n                return function() {\n                    return a;\n                };\n            }();\n        }\n        console.log(typeof f()());\n    }\n    expect: {\n        function f(a) {\n            return a = function() {\n                return function() {\n                    return a;\n                };\n            }();\n        }\n        console.log(typeof f()());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2749: {\n    options = {\n        dead_code: true,\n        inline: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 2, c = \"PASS\";\n        while (a--)\n            (function() {\n                return b ? c = \"FAIL\" : b = 1;\n                try {\n                } catch (b) {\n                    var b;\n                }\n            })();\n        console.log(c);\n    }\n    expect: {\n        var a = 2, c = \"PASS\";\n        while (a--)\n            b = void 0, b ? c = \"FAIL\" : 1;\n        var b;\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2860_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a ^= 1;\n        }());\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2860_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a ^= 1;\n        }());\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2929: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                return null.p = a = 1;\n            } catch (e) {\n                return a ? \"PASS\" : \"FAIL\";\n            }\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                return null.p = a = 1;\n            } catch (e) {\n                return a ? \"PASS\" : \"FAIL\";\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3402: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        functions: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        var f = function f() {\n            f = 42;\n            console.log(typeof f);\n        };\n        \"function\" == typeof f && f();\n        \"function\" == typeof f && f();\n        console.log(typeof f);\n    }\n    expect: {\n        function f() {\n            console.log(typeof f);\n        }\n        f();\n        f();\n        console.log(typeof f);\n    }\n    expect_stdout: [\n        \"function\",\n        \"function\",\n        \"function\",\n    ]\n}\n\nissue_3406: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function f(a) {\n            return delete (f = a);\n        }());\n    }\n    expect: {\n        console.log(function f(a) {\n            return delete (0, a);\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nfunction_assign: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function() {\n            var a = \"PASS\";\n            function h(c) {\n                return c;\n            }\n            h.p = function(b) {\n                return b;\n            }.p = a;\n            return h;\n        }().p);\n    }\n    expect: {\n        console.log(function() {\n            var a = \"PASS\";\n            function h(c) {\n                return c;\n            }\n            h.p = a;\n            return h;\n        }().p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3552: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            (1..p += 42) && (a = \"FAIL\");\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            (1..p += 42) && (a = \"FAIL\");\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nunreachable_assign: {\n    options = {\n        dead_code: true,\n        strings: true,\n    }\n    input: {\n        console.log(A = \"P\" + (A = \"A\" + (B = \"S\" + (A = B = \"S\"))), A, B);\n    }\n    expect: {\n        console.log(A = \"P\" + \"A\" + (B = \"S\" + \"S\"), A, B);\n    }\n    expect_stdout: \"PASS PASS SS\"\n}\n\ncatch_return_assign: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return e = \"PASS\";\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return \"PASS\";\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\ncatch_return_assign_may_throw: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return e = console.log(\"PASS\");\n            }\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return console.log(\"PASS\");\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nfinally_return_assign: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                throw \"FAIL\";\n            } finally {\n                return a = \"PASS\";\n            }\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                throw \"FAIL\";\n            } finally {\n                return \"PASS\";\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nlast_assign_statement: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f(a) {\n            a = a(\"PASS\");\n        }\n        f(console.log);\n    }\n    expect: {\n        function f(a) {\n            a(\"PASS\");\n        }\n        f(console.log);\n    }\n    expect_stdout: \"PASS\"\n}\n\nlast_assign_if_else: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                a = console.log(\"foo\");\n            else {\n                console.log(\"bar\");\n                a = console.log(\"baz\");\n            }\n        }\n        f(42);\n        f(null);\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                console.log(\"foo\");\n            else {\n                console.log(\"bar\");\n                console.log(\"baz\");\n            }\n        }\n        f(42);\n        f(null);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nlast_assign_catch: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                e = console.log(\"PASS\");\n            }\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nlast_assign_finally: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f(a) {\n            try {\n                throw a.log;\n            } catch (e) {\n                a = e;\n            } finally {\n                a = a(\"PASS\");\n            }\n        }\n        f(console);\n    }\n    expect: {\n        function f(a) {\n            try {\n                throw a.log;\n            } catch (e) {\n                a = e;\n            } finally {\n                a(\"PASS\");\n            }\n        }\n        f(console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nconsecutive_assignments: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        while (a = void 0, a = \"PASS\", console.log(a));\n        var a;\n    }\n    expect: {\n        while (void 0, a = \"PASS\", console.log(a));\n        var a;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3578: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = \"FAIL\", b, c;\n        try {\n            b = c.p = b = 0;\n        } catch (e) {\n            b += 42;\n            b && (a = \"PASS\");\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\", b, c;\n        try {\n            b = c.p = b = 0;\n        } catch (e) {\n            b += 42;\n            b && (a = \"PASS\");\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3830_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var o = {\n            set p(v) {\n                o = o.p = o = v;\n            }\n        };\n        o.p = \"PASS\";\n        console.log(o);\n    }\n    expect: {\n        var o = {\n            set p(v) {\n                o = o.p = o = v;\n            }\n        };\n        o.p = \"PASS\";\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3830_2: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = o[a] = a = v;\n            }\n        };\n        o[a] = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = o[a] = a = v;\n            }\n        };\n        o[a] = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3830_3: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            return a;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = o[f()] = a = v;\n            }\n        };\n        o[f()] = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        function f() {\n            return a;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = o[f()] = a = v;\n            }\n        };\n        o[f()] = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3830_4: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            return o;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = f()[a] = a = v;\n            }\n        };\n        f()[a] = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        function f() {\n            return o;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = f()[a] = a = v;\n            }\n        };\n        f()[a] = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3830_5: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            return o;\n        }\n        function g() {\n            return a;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = f()[g()] = a = v;\n            }\n        };\n        f()[g()] = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        function f() {\n            return o;\n        }\n        function g() {\n            return a;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                a = f()[g()] = a = v;\n            }\n        };\n        f()[g()] = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3830_6: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            return o;\n        }\n        function g() {\n            return a;\n        }\n        function h(v) {\n            a = f()[g()] = a = v;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                h(v);\n            }\n        };\n        o.FAIL = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        function f() {\n            return o;\n        }\n        function g() {\n            return a;\n        }\n        function h(v) {\n            a = f()[g()] = a = v;\n        }\n        var a = \"FAIL\";\n        var o = {\n            set FAIL(v) {\n                h(v);\n            }\n        };\n        o.FAIL = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nredundant_assignments: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = a = \"PASS\", b = \"FAIL\";\n        b = b = \"PASS\";\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"PASS\", b = \"FAIL\";\n        b = \"PASS\";\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nself_assignments_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = \"PASS\";\n        a = a;\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        a;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nself_assignments_2: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"q\", o = {\n            p: \"PASS\",\n        };\n        o.p = o.p;\n        o[a] = o[a];\n        console.log(o.p, o[a]);\n    }\n    expect: {\n        var a = \"q\", o = {\n            p: \"PASS\",\n        };\n        console.log(o.p, o[a]);\n    }\n    expect_stdout: \"PASS undefined\"\n}\n\nself_assignments_3: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"q\", o = {\n            p: \"FAIL\",\n            get q() {\n                return \"PASS\";\n            },\n            set q(v) {\n                this.p = v;\n            },\n        };\n        o.p = o.p;\n        o[a] = o[a];\n        console.log(o.p, o[a]);\n    }\n    expect: {\n        var a = \"q\", o = {\n            p: \"FAIL\",\n            get q() {\n                return \"PASS\";\n            },\n            set q(v) {\n                this.p = v;\n            },\n        };\n        o.p = o.p;\n        o[a] = o[a];\n        console.log(o.p, o[a]);\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nself_assignments_4: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var i = 0, l = [ \"PASS\" ];\n        l[0] = l[0];\n        l[i] = l[i];\n        console.log(l[0], i);\n    }\n    expect: {\n        var i = 0, l = [ \"PASS\" ];\n        console.log(l[0], i);\n    }\n    expect_stdout: \"PASS 0\"\n}\n\nself_assignments_5: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var i = 0, l = [ \"FAIL\", \"PASS\" ];\n        l[0] = l[0];\n        l[i] = l[i];\n        l[i++] = l[i++];\n        console.log(l[0], i);\n    }\n    expect: {\n        var i = 0, l = [ \"FAIL\", \"PASS\" ];\n        l[0] = l[1];\n        console.log(l[0], 2);\n    }\n    expect_stdout: \"PASS 2\"\n}\n\nself_assignments_6: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            p: \"PASS\",\n        };\n        console.log(o.p = o.p);\n    }\n    expect: {\n        var o = {\n            p: \"PASS\",\n        };\n        console.log(o.p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3967: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            a = 0 in (a = \"PASS\");\n        } catch (e) {}\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            a = 0 in (a = \"PASS\");\n        } catch (e) {}\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4051: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {\n            delete (A = A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            delete (A = A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4366: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        function f() {\n            return \"PASS\";\n            ({\n                p: 42,\n                get p() {},\n            });\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            return \"PASS\";\n        }\n        console.log(f());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4570: {\n    options = {\n        dead_code: true,\n        inline: true,\n    }\n    input: {\n        var a = function(b) {\n            return a += b;\n        }() ? 0 : a;\n        console.log(a);\n    }\n    expect: {\n        var a = (a += void 0) ? 0 : a;\n        console.log(a);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5030: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        (function(a, b) {\n            a = function f() {\n                if (a)\n                    if (b--)\n                        setImmediate(f);\n                    else\n                        console.log(\"FAIL\");\n                else\n                    console.log(\"PASS\");\n            }();\n        })(42, 1);\n    }\n    expect: {\n        (function(a, b) {\n            a = function f() {\n                if (a)\n                    if (b--)\n                        setImmediate(f);\n                    else\n                        console.log(\"FAIL\");\n                else\n                    console.log(\"PASS\");\n            }();\n        })(42, 1);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=0.12\"\n}\n\nissue_5106_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(typeof function(a) {\n            return a = arguments;\n        }(\"FAIL\")[0]);\n    }\n    expect: {\n        console.log(typeof function(a) {\n            return a = arguments;\n        }(\"FAIL\")[0]);\n    }\n    expect_stdout: \"object\"\n}\n\nissue_5106_2: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function(a) {\n            return a = arguments;\n        }(\"PASS\")[0]);\n    }\n    expect: {\n        \"use strict\";\n        console.log(function(a) {\n            return arguments;\n        }(\"PASS\")[0]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5506: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {\n            (function(a) {\n                var b = 1;\n                (function f() {\n                    try {\n                        b-- && f();\n                    } catch (c) {}\n                    console.log(a);\n                    a = 42 in (a = \"bar\");\n                })();\n            })(\"foo\");\n        } catch (e) {}\n    }\n    expect: {\n        try {\n            (function(a) {\n                var b = 1;\n                (function f() {\n                    try {\n                        b-- && f();\n                    } catch (c) {}\n                    console.log(a);\n                    a = 42 in (a = \"bar\");\n                })();\n            })(\"foo\");\n        } catch (e) {}\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_5641: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        dead_code: true,\n    }\n    input: {\n        function f(a) {\n            if (a || b) {\n                var b = \"PASS\", c = b && console.log(b);\n            } else\n                var d = a || b;\n        }\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            var b, c, d;\n            (a || b) && (b = \"PASS\") && console.log(b);\n        }\n        f(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5882_1: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        console.log(delete (42..p = NaN));\n    }\n    expect: {\n        console.log(delete (0, NaN));\n    }\n    expect_stdout: \"true\"\n}\n\nissue_5882_2: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (42..p = NaN));\n    }\n    expect: {\n        console.log(delete (0, NaN));\n    }\n    expect_stdout: \"true\"\n}\n\nissue_5882_3: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (42..p = Infinity));\n    }\n    expect: {\n        console.log(delete (1 / 0));\n    }\n    expect_stdout: \"true\"\n}\n"
  },
  {
    "path": "test/compress/debugger.js",
    "content": "keep_debugger: {\n    options = {\n        drop_debugger: false,\n    }\n    input: {\n        debugger;\n    }\n    expect: {\n        debugger;\n    }\n}\n\ndrop_debugger: {\n    options = {\n        drop_debugger: true,\n    }\n    input: {\n        debugger;\n        if (foo) debugger;\n    }\n    expect: {\n        if (foo);\n    }\n}\n"
  },
  {
    "path": "test/compress/default-values.js",
    "content": "arrow_1: {\n    input: {\n        console.log(((a = \"PASS\") => a)());\n    }\n    expect_exact: 'console.log(((a=\"PASS\")=>a)());'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\narrow_2: {\n    input: {\n        console.log((([ a = \"FAIL\" ]) => a)([ \"PASS\" ]));\n    }\n    expect_exact: 'console.log((([a=\"FAIL\"])=>a)([\"PASS\"]));'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\narrow_3: {\n    input: {\n        (([ a = console ] = null) => a.log(\"PASS\"))(\"\");\n    }\n    expect_exact: '(([a=console]=null)=>a.log(\"PASS\"))(\"\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nassign: {\n    input: {\n        [ a = \"PASS\" ] = [];\n        console.log(a);\n    }\n    expect_exact: '[a=\"PASS\"]=[];console.log(a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndeclaration_var: {\n    input: {\n        var [ a = \"PASS\" ] = [ , ];\n        console.log(a);\n    }\n    expect_exact: 'var[a=\"PASS\"]=[,];console.log(a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndeclaration_const: {\n    input: {\n        const [ a = \"FAIL\" ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect_exact: 'const[a=\"FAIL\"]=[\"PASS\"];console.log(a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndeclaration_let: {\n    input: {\n        let [ a = \"PASS\" ] = [ void 42 ];\n        console.log(a);\n    }\n    expect_exact: 'let[a=\"PASS\"]=[void 42];console.log(a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nobject_shorthand_assign: {\n    input: {\n        ({ a = \"PASS\" } = 42);\n        console.log(a);\n    }\n    expect_exact: '({a=\"PASS\"}=42);console.log(a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nobject_shorthand_declaration: {\n    input: {\n        var { a = \"PASS\" } = 42;\n        console.log(a);\n    }\n    expect_exact: 'var{a=\"PASS\"}=42;console.log(a);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nobject_shorthand_function: {\n    input: {\n        (function({ a = \"PASS\" }) {\n            console.log(a);\n        })(42);\n    }\n    expect_exact: '(function({a=\"PASS\"}){console.log(a)})(42);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nretain_arguments_1: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        console.log(function(a = \"FAIL\") {\n            return arguments[0];\n        }() || \"PASS\");\n    }\n    expect: {\n        console.log(function(a = \"FAIL\") {\n            return arguments[0];\n        }() || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nretain_arguments_2: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        console.log(function(a, b = null) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\", 42));\n    }\n    expect: {\n        console.log(function(a, b = null) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\", 42));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nprocess_boolean_returns: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a = console.log(\"FAIL 1\")) {\n            return a() ? \"PASS\" : \"FAIL 2\";\n        }(function() {\n            return 42;\n        }));\n    }\n    expect: {\n        console.log(function(a = console.log(\"FAIL 1\")) {\n            return 42 ? \"PASS\" : \"FAIL 2\";\n        }(function() {\n            return 1;\n        }));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_arg_sequence: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a = (console.log(\"bar\"), console.log)) {\n            a(\"foo\");\n        })();\n    }\n    expect: {\n        (function(a = console.log(\"bar\")) {\n            (0, console.log)(\"foo\");\n        })();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=6\"\n}\n\ncollapse_in_arg: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(a, b = a) {\n            b(\"PASS\");\n        })(console.log);\n    }\n    expect: {\n        (function(a) {\n            a(\"PASS\");\n        })(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_value_1: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function(a = \"PASS\") {\n            return a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_value_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(a = console) {\n            return a;\n        })().log(\"PASS\");\n    }\n    expect: {\n        (function() {\n            return console;\n        })().log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nflatten_if: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (console.log(\"PASS\")) {\n            var [\n                a = function b() {\n                    for (c in b);\n                },\n            ] = 0;\n        }\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\") && ([\n            a = function b() {\n                for (c in b);\n            },\n        ] = 0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmaintain_if: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (a)\n            for (;;);\n        else\n            var [ a = \"PASS\" ] = [];\n        console.log(a);\n    }\n    expect: {\n        if (a)\n            for (;;);\n        else\n            var [ a = \"PASS\" ] = [];\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_funarg: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(...function(a = \"foo\", b = \"bar\", c = \"baz\") {\n            return [ a, b, c ];\n        }(void 0, null));\n    }\n    expect: {\n        console.log(...function() {\n            return [ \"foo\", null, \"baz\" ];\n        }());\n    }\n    expect_stdout: \"foo null baz\"\n    node_version: \">=6\"\n}\n\nreduce_array: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var [ a = \"foo\", b = \"bar\", c = \"baz\" ] = [ void 0, null ];\n        console.log(a, b, c);\n    }\n    expect: {\n        var [ c = \"baz\" ] = [];\n        console.log(\"foo\", null, c);\n    }\n    expect_stdout: \"foo null baz\"\n    node_version: \">=6\"\n}\n\nreduce_object: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var { a = \"foo\", b = \"bar\", c = \"baz\" } = { a: void 0, b: null };\n        console.log(a, b, c);\n    }\n    expect: {\n        var { c = \"baz\" } = {};\n        console.log(\"foo\", null, c);\n    }\n    expect_stdout: \"foo null baz\"\n    node_version: \">=6\"\n}\n\nevaluate_iife: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(function(a = \"PASS\") {\n            return a;\n        }());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunsafe_evaluate_iife_1: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function([ a ] = []) {\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function([ a ] = []) {\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunsafe_evaluate_iife_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function([ a ] = []) {\n            return a[0];\n        }([ [ \"PASS\" ] ]));\n    }\n    expect: {\n        console.log(function([ a ] = []) {\n            return a[0];\n        }([ [ \"PASS\" ] ]));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ninline_direct: {\n    options = {\n        default_values: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a = \"FAIL\") {\n            return a;\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ninline_constant: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function(a = console.log(\"foo\")) {\n            return \"bar\";\n        }(void console.log(\"baz\")));\n    }\n    expect: {\n        console.log((void console.log(\"baz\"), console.log(\"foo\"), \"bar\"));\n    }\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=6\"\n}\n\ninline_destructured: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function([ a ] = []) {\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(([ [] = [] ] = [], \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ninline_function: {\n    options = {\n        default_values: true,\n        inline: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        (function(a = console.log(\"foo\"), b = console.log(\"bar\")) {\n            console.log(\"baz\");\n        }(void console.log(\"moo\"), 42));\n    }\n    expect: {\n        console.log(\"moo\"),\n        console.log(\"foo\"),\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"moo\",\n        \"foo\",\n        \"baz\",\n    ]\n    node_version: \">=6\"\n}\n\ninline_loop_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        while (function f(a = \"PASS\") {\n            console.log(a);\n        }());\n    }\n    expect: {\n        while (a = \"PASS\", void console.log(a));\n        var a;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ninline_loop_2: {\n    options = {\n        inline: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        while (function(a = [ \"PASS\" ]) {\n            var a = function f(b) {\n                console.log(a[b]);\n            }(0);\n        }());\n    }\n    expect: {\n        while (a = [ \"PASS\" ],\n            b = void 0,\n            b = 0,\n            void (a = void console.log(a[b])));\n        var a, b;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ninline_side_effects_1: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 42;\n        (function(b = --a) {})(console);\n        console.log(a);\n    }\n    expect: {\n        var a = 42;\n        [ b = --a ] = [ console ],\n        void 0;\n        var b;\n        console.log(a);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\ninline_side_effects_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var a = 42;\n        (function(b = --a) {})(console);\n        console.log(a);\n    }\n    expect: {\n        var a = 42;\n        [ [][0] = --a ] = [ console ];\n        console.log(a);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\ndrop_empty_iife: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a = console.log(\"foo\")) {}(void console.log(\"baz\")));\n    }\n    expect: {\n        console.log((console.log(\"baz\"), void console.log(\"foo\")));\n    }\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=6\"\n}\n\nretain_empty_iife: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var a;\n        try {\n            (function(a = a) {})();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a;\n        try {\n            (function(a = a) {})();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_new_function: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        new function(a = console.log(\"PASS\")) {}();\n    }\n    expect: {\n        void console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nretain_fargs: {\n    options = {\n        unused: true,\n    }\n    input: {\n        (function([ a = console.log(\"PASS\") ]) {})([]);\n    }\n    expect: {\n        (function([ a = console.log(\"PASS\") ]) {})([]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_fargs: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function(a = 42, b = console.log(\"foo\"), c = true) {\n            return \"bar\";\n        }(console.log(\"baz\"), \"moo\", false));\n    }\n    expect: {\n        console.log(function(b = console.log(\"foo\")) {\n            return \"bar\";\n        }((console.log(\"baz\"), \"moo\")));\n    }\n    expect_stdout: [\n        \"baz\",\n        \"bar\",\n    ]\n    expect_warnings: [\n        \"WARN: Dropping unused default argument c [test/compress/default-values.js:1,61]\",\n        \"WARN: Side effects in default value of unused variable b [test/compress/default-values.js:1,37]\",\n        \"WARN: Dropping unused default argument assignment a [test/compress/default-values.js:1,29]\",\n    ]\n    node_version: \">=6\"\n}\n\nhoist_vars: {\n    options = {\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        var [ b = 42 ] = [];\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"PASS\", [ b = 42 ] = [];\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nunused_var_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var [ a = 42 ] = [ console.log(\"PASS\") ];\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunused_var_2: {\n    options = {\n        pure_getters: \"strict\",\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var {\n            p: [ a ] = \"\" + console.log(\"FAIL\"),\n        } = {\n            p: [ console.log(\"PASS\") ],\n        };\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunused_value_assign_1: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        [] = [ console.log(\"PASS\") ];\n    }\n    expect: {\n        [ console.log(\"PASS\") ];\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunused_value_assign_2: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        [ a = console.log(\"FAIL\") ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect: {\n        [ a ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunused_value_var_1: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        var [] = [ console.log(\"PASS\") ];\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nunused_value_var_2: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        var [ a = console.log(\"FAIL\") ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect: {\n        var a = [ \"PASS\" ][0];\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_var_1: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var N = 1, [ {\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        } ] = [ {}, {\n            x1: \"PASS\",\n        } ];\n        console.log(v);\n    }\n    expect: {\n        var N = 1, [ {\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        } ] = [ {}, {\n            x1: \"PASS\",\n        } ];\n        console.log(v);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_var_1_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var N = 1, [ {\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        } ] = [ {}, {\n            x1: \"PASS\",\n        } ];\n        console.log(v);\n    }\n    expect: {\n        var o = 1, [ {\n            pname: a = \"x\",\n            i: e = o,\n        }, {\n            [a + e]: l,\n        } ] = [ {}, {\n            x1: \"PASS\",\n        } ];\n        console.log(l);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_var_2: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var N = 1, [ {\n            pname: p = \"x\",\n            i: n = N,\n        } = {}, {\n            [p + n]: v,\n        } ] = [ , {\n            x1: \"PASS\",\n        } ];\n        console.log(v);\n    }\n    expect: {\n        var N = 1, [ {\n            pname: p = \"x\",\n            i: n = N,\n        } = {}, {\n            [p + n]: v,\n        } ] = [ , {\n            x1: \"PASS\",\n        } ];\n        console.log(v);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_var_2_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var N = 1, [ {\n            pname: p = \"x\",\n            i: n = N,\n        } = {}, {\n            [p + n]: v,\n        } ] = [ , {\n            x1: \"PASS\",\n        } ];\n        console.log(v);\n    }\n    expect: {\n        var o = 1, [ {\n            pname: a = \"x\",\n            i: e = o,\n        } = {}, {\n            [a + e]: l,\n        } ] = [ , {\n            x1: \"PASS\",\n        } ];\n        console.log(l);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_function_1: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var N = 1;\n        (function(o, {\n            pname: p,\n        } = o, {\n            [p + N]: v,\n        } = o) {\n            let N;\n            console.log(v);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var N = 1;\n        (function(n, {\n            pname: e,\n        } = n, {\n            [e + N]: o,\n        } = n) {\n            let a;\n            console.log(o);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_function_1_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var N = 1;\n        (function(o, {\n            pname: p,\n        } = o, {\n            [p + N]: v,\n        } = o) {\n            let N;\n            console.log(v);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var l = 1;\n        (function(n, {\n            pname: e,\n        } = n, {\n            [e + l]: o,\n        } = n) {\n            let a;\n            console.log(o);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_function_2: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var N = 1;\n        (function({\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        }) {\n            let N;\n            console.log(v);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var N = 1;\n        (function({\n            pname: n = \"x\",\n            i: o = N,\n        }, {\n            [n + o]: e,\n        }) {\n            let l;\n            console.log(e);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_function_2_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var N = 1;\n        (function({\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        }) {\n            let N;\n            console.log(v);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var a = 1;\n        (function({\n            pname: n = \"x\",\n            i: o = a,\n        }, {\n            [n + o]: e,\n        }) {\n            let l;\n            console.log(e);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_arrow_1: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var N = 1;\n        ((o, {\n            pname: p,\n        } = o, {\n            [p + N]: v,\n        } = o) => {\n            let N;\n            console.log(v);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var N = 1;\n        ((e, {\n            pname: a,\n        } = e, {\n            [a + N]: l,\n        } = e) => {\n            let n;\n            console.log(l);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6.9.3\"\n}\n\nmangle_arrow_1_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var N = 1;\n        ((o, {\n            pname: p,\n        } = o, {\n            [p + N]: v,\n        } = o) => {\n            let N;\n            console.log(v);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var o = 1;\n        ((e, {\n            pname: a,\n        } = e, {\n            [a + o]: l,\n        } = e) => {\n            let n;\n            console.log(l);\n        })({\n            pname: \"x\",\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6.9.3\"\n}\n\nmangle_arrow_2: {\n    mangle = {\n        toplevel: false,\n    }\n    input: {\n        var N = 1;\n        (({\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        }) => {\n            let N;\n            console.log(v);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var N = 1;\n        (({\n            pname: e = \"x\",\n            i: l = N,\n        }, {\n            [e + l]: o,\n        }) => {\n            let a;\n            console.log(o);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6.9.3\"\n}\n\nmangle_arrow_2_toplevel: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var N = 1;\n        (({\n            pname: p = \"x\",\n            i: n = N,\n        }, {\n            [p + n]: v,\n        }) => {\n            let N;\n            console.log(v);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect: {\n        var n = 1;\n        (({\n            pname: e = \"x\",\n            i: l = n,\n        }, {\n            [e + l]: o,\n        }) => {\n            let a;\n            console.log(o);\n        })({}, {\n            x1: \"PASS\",\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6.9.3\"\n}\n\ncollapse_preceding_simple_arg: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        console.log(function(b, c = \"bar\") {\n            return b + c;\n        }(a, a));\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(function(b, c = \"bar\") {\n            return a + c;\n        }(0, a));\n    }\n    expect_stdout: \"foofoo\"\n    node_version: \">=6\"\n}\n\ndrop_preceding_simple_arg: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        console.log(function(b, c = \"bar\") {\n            return b + c;\n        }(a, a));\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(function(c = \"bar\") {\n            return a + c;\n        }(a));\n    }\n    expect_stdout: \"foofoo\"\n    node_version: \">=6\"\n}\n\nissue_4444: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\";\n        console.log(function(b) {\n            b = a;\n            (function(c = b.p) {})();\n            return a;\n        }());\n    }\n    expect: {\n        var a = \"PASS\";\n        console.log(function(b) {\n            b = a;\n            (function(c = b.p) {})();\n            return a;\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4446_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        a = 42;\n        [ b = 42 ] = [ \"PASS\" ];\n        c = 42;\n        console.log(b, a);\n    }\n    expect: {\n        [ b = 42 ] = [ \"PASS\" ];\n        c = a = 42;\n        console.log(b, a);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nissue_4446_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        a = 42;\n        var [ b = 42 ] = [ \"PASS\" ];\n        c = 42;\n        console.log(b, a);\n    }\n    expect: {\n        var [ b = 42 ] = [ \"PASS\" ];\n        c = a = 42;\n        console.log(b, a);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nissue_4458: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(b = a = \"FAIL\") {\n            console.log(a, b);\n        }\n        f(42);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b = a = \"FAIL\") {\n            console.log(a, b);\n        })(42);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nissue_4460: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log, a = \"FAIL\";\n        var [ b = a ] = (a = \"PASS\", []);\n        log(a, b);\n    }\n    expect: {\n        var log = console.log, a = \"FAIL\";\n        var [ b = a ] = (a = \"PASS\", []);\n        log(a, b);\n    }\n    expect_stdout: \"PASS PASS\"\n    node_version: \">=6\"\n}\n\nissue_4461_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function(b = a && console.log(\"PASS\"), c) {\n            return c;\n        })(void 0, a++);\n    }\n    expect: {\n        var a = 0;\n        (function(b = a && console.log(\"PASS\"), c) {\n            return c;\n        })(void 0, a++);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4461_2: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function([ b = a && console.log(\"PASS\") ], c) {\n            return c;\n        })([], a++);\n    }\n    expect: {\n        var a = 0;\n        (function([ b = a && console.log(\"PASS\") ], c) {\n            return c;\n        })([], a++);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4468: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var {\n                [console.log(\"PASS\")]: b = a && (a.p = 0),\n            } = 0;\n            a;\n        })(1234);\n    }\n    expect: {\n        (function() {\n            var {\n                [console.log(\"PASS\")]: b,\n            } = 0;\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4483: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        if (console)\n            var [ a = \"FAIL\" ] = [], b = a = \"PASS\";\n        console.log(b);\n    }\n    expect: {\n        var a, b;\n        console && ([ a = \"FAIL\" ] = [], b = \"PASS\");\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4485_1: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        (function(a = null) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })();\n    }\n    expect: {\n        (function(a = null) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4485_2: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        (function(a = null) {\n            var arguments = null;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })();\n    }\n    expect: {\n        (function(a = null) {\n            var arguments = null;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4485_3: {\n    options = {\n        unused: true,\n    }\n    input: {\n        (function(a = null) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })();\n    }\n    expect: {\n        (function(a = null) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4496: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        (function f(a = 0) {\n            console.log(function(b) {\n                a && b();\n                return a;\n            }(f));\n        })(42);\n    }\n    expect: {\n        (function f(a = 0) {\n            console.log(function(b) {\n                a && b();\n                return a;\n            }(f));\n        })(42);\n    }\n    expect_stdout: [\n        \"0\",\n        \"42\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4502_1: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = \"PASS\";\n            (function(b = a++) {\n                var a;\n            })(void 0, console.log(a));\n        })();\n    }\n    expect: {\n        (function() {\n            var a = \"PASS\";\n            void 0,\n            console.log(a),\n            a++,\n            void 0;\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4502_2: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = \"PASS\";\n            (function(b = a++) {})(void 0, console.log(a));\n        })();\n    }\n    expect: {\n        (function() {\n            var a = \"PASS\";\n            void 0,\n            console.log(a),\n            a++,\n            void 0;\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4502_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            var a = \"PASS\";\n            (function(b = a++) {})(void 0, console.log(a));\n        })();\n    }\n    expect: {\n        (function() {\n            var a = \"PASS\";\n            console.log(a),\n            a++;\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4502_4: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (function(a, b = console.log(\"FAIL\")) {})(...\"\" + console.log(42));\n    }\n    expect: {\n        [ , [][0] = console.log(\"FAIL\") ] = [ ...\"\" + console.log(42) ];\n    }\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\nissue_4510_1: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        var a = [];\n        var [ , b = console.log(\"PASS\") ] = [ ...a, null ];\n    }\n    expect: {\n        var a = [];\n        var [ , b = console.log(\"PASS\") ] = [ ...a, null ];\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4510_2: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            p: void 0,\n        };\n        var {\n            p: a = console.log(\"PASS\"),\n        } = {\n            p: null,\n            ...o,\n        };\n    }\n    expect: {\n        var o = {\n            p: void 0,\n        };\n        var {\n            p: a = console.log(\"PASS\"),\n        } = {\n            p: null,\n            ...o,\n        };\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_4523: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var a, b;\n            [ a = b = false ] = [ \"FAIL\" ];\n            return b || \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a, b;\n            [ a = b = false ] = [ \"FAIL\" ];\n            return b || \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4540: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function() {\n            function f([ a = 0 ]) {}\n            f([]);\n        }());\n    }\n    expect: {\n        console.log(function() {\n            function f([ a = 0 ]) {}\n            f([]);\n        }());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4548_1: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        A = \"foo\";\n        var a = A;\n        [ b = c = \"bar\" ] = [ console, console.log(a) ];\n        console.log(c);\n        var c;\n    }\n    expect: {\n        A = \"foo\";\n        var a = A;\n        [ b = c = \"bar\" ] = [ console, console.log(a) ];\n        console.log(c);\n        var c;\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4548_2: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        A = \"foo\";\n        var a = A;\n        var [ b = c = \"bar\" ] = [ console, console.log(a) ];\n        console.log(c);\n        var c;\n    }\n    expect: {\n        A = \"foo\";\n        var a = A;\n        var [ b = c = \"bar\" ] = [ console, console.log(a) ];\n        console.log(c);\n        var c;\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4588_1_unused: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function(a = 42) {}.length);\n    }\n    expect: {\n        console.log(function(a = 0) {}.length);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=6\"\n}\n\nissue_4588_2_unused: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b = void 0, c, d = \"foo\") {}.length);\n    }\n    expect: {\n        console.log(function(a, b = 0, c, d) {}.length);\n    }\n    expect_stdout: \"1\"\n    expect_warnings: [\n        \"WARN: Dropping unused default argument assignment d [test/compress/default-values.js:1,47]\",\n        \"WARN: Dropping unused default argument value b [test/compress/default-values.js:1,32]\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4588_1_evaluate: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(a = 42) {}.length);\n    }\n    expect: {\n        console.log(0);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=6\"\n}\n\nissue_4588_2_evaluate: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(a, b = void 0, c, d = \"foo\") {}.length);\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n    node_version: \">=6\"\n}\n\nissue_4817: {\n    options = {\n        ie: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function f(a = console.log(typeof f)) {\n            return 42;\n        })();\n    }\n    expect: {\n        (function f(a = console.log(typeof f)) {\n            return 42;\n        })();\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_4854: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            (function(b = a = \"foo\") {\n                [] = \"foo\";\n            })();\n            a;\n        }());\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4916: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        var log = console.log;\n        (function(b = \"foo\") {\n            b.value = \"FAIL\";\n            b;\n            log(b.value);\n        })();\n    }\n    expect: {\n        var log = console.log;\n        (function(b = \"foo\") {\n            b.value = \"FAIL\";\n            b;\n            log(b.value);\n        })();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4994: {\n    options = {\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b = function() {\n            for (a in { PASS: 42 });\n        }()) {\n            var a;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function(b = function() {\n            for (a in { PASS: 42 });\n        }()) {})();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5057_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        (function() {\n            var b = function(c = (console.log(\"foo\"), b = a)) {\n                a && console.log(\"bar\");\n            }();\n        })();\n    }\n    expect: {\n        var a = 42;\n        console.log(\"foo\"),\n        void (a && console.log(\"bar\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5057_2: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            (function(b = console.log(\"FAIL\")) {})(a);\n        })(42);\n        console.log(typeof b);\n    }\n    expect: {\n        (function(a) {\n            [ b = console.log(\"FAIL\") ] = [ a ],\n            void 0;\n            var b;\n        })(42);\n        console.log(typeof b);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_5057_3: {\n    options = {\n        inline: 3,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            (function f(b) {\n                (function(a = console.log(\"FAIL 1\")) {})(b);\n                console.log(a);\n            })(\"FAIL 2\");\n        })(\"PASS\");\n    }\n    expect: {\n        (function(a) {\n            (function(b) {\n                (function(a = console.log(\"FAIL 1\")) {})(b);\n                console.log(a);\n            })(\"FAIL 2\");\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5057_4: {\n    options = {\n        if_return: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            (function f(b) {\n                (function(a = console.log(\"FAIL 1\")) {})(b);\n                console.log(a);\n            })(\"FAIL 2\");\n        })(\"PASS\");\n    }\n    expect: {\n        (function(a) {\n            var b = \"FAIL 2\";\n            (function(a = console.log(\"FAIL 1\")) {})(b);\n            console.log(a);\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5065: {\n    options = {\n        pure_getters: \"strict\",\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var [ a = console.log(\"PASS\") ] = [ (A = 42).p ];\n    }\n    expect: {\n        var [ a = console.log(\"PASS\") ] = [ (A = 42).p ];\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5138_1: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(function(a, b = a = \"FAIL\") {\n            return a;\n        }() && \"PASS\");\n    }\n    expect: {\n        console.log(function(a, b = a = \"FAIL\") {\n            return a;\n        }() && \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5138_2: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(function(a, b = a = \"FAIL 1\") {\n            return a;\n        }(null, \"FAIL 2\") || \"PASS\");\n    }\n    expect: {\n        console.log((null, \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5192: {\n    options = {\n        dead_code: true,\n        ie: true,\n    }\n    input: {\n        (function a(a,  [] = a = \"PASS\") {\n            console.log(a);\n        })(\"FAIL\");\n    }\n    expect: {\n        (function a(a,  [] = a = \"PASS\") {\n            console.log(a);\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5246_1: {\n    options = {\n        keep_fargs: false,\n        pure_getters: true,\n        unused: true,\n    }\n    input: {\n        console.log(function({} = 42) {\n            return \"PASS\";\n        }(\"foo\"));\n    }\n    expect: {\n        console.log(function() {\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    expect_warnings: [\n        \"INFO: Dropping unused default argument {} [test/compress/default-values.js:1,29]\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5246_2: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function f(a = \"FAIL\", [] = 42) {\n            console.log(a);\n        })(\"PASS\", []);\n    }\n    expect: {\n        (function(a = \"FAIL\") {\n            console.log(a);\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5246_3: {\n    options = {\n        default_values: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function f([ , {} ] = null){}([ , {} ]));\n    }\n    expect: {\n        console.log(function([ {} ]){}([ {} ]));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_5256: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function(arguments = console.log) {\n            console;\n        })();\n        console.log(typeof arguments);\n    }\n    expect: {\n        // Syntax error on Node.js v6\n        (function(arguments = console.log) {\n            console;\n        })();\n        console.log(typeof arguments);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=8\"\n}\n\nissue_5314_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        A = this;\n        new function() {\n            (function(a = console.log(this === A ? \"PASS\" : \"FAIL\")) {})();\n        }();\n    }\n    expect: {\n        A = this;\n        (function() {\n            (function(a = console.log(this === A ? \"PASS\" : \"FAIL\")) {})();\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5314_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        A = this;\n        new function() {\n            ((a = console.log(this === A ? \"FAIL\" : \"PASS\")) => {})();\n        }();\n    }\n    expect: {\n        A = this;\n        new function() {\n            console.log(this === A ? \"FAIL\" : \"PASS\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5336: {\n    options = {\n        default_values: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        do {\n            (function f(b = console.log(\"PASS\")) {\n                a = f;\n            })(42);\n        } while (a());\n    }\n    expect: {\n        var a;\n        do {\n            (function f(b = console.log(\"PASS\")) {\n                a = f;\n            })(42);\n        } while (a());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5340_1: {\n    options = {\n        keep_fargs: true,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b = 42) {})(({ p: a } = true).q);\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (function(b = 0) {})(({ p: a } = true).q);\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_5340_2: {\n    options = {\n        keep_fargs: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b = 42) {})(({ p: a } = true).q);\n        console.log(a);\n    }\n    expect: {\n        var a;\n        [ [][0] = 0 ] = [ ({ p: a } = true).q ];\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_5340_3: {\n    options = {\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b = 42) {})(({ p: a } = true).q);\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (function() {})(a = true.p);\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_5407: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            for (var i = 0; i < 2; i++)\n                (function(b = 4) {\n                    console.log(b);\n                    a = 2;\n                })(a);\n        })();\n    }\n    expect: {\n        (function(a) {\n            for (var i = 0; i < 2; i++)\n                (function(b = 4) {\n                    console.log(b);\n                    a = 2;\n                })(a);\n        })();\n    }\n    expect_stdout: [\n        \"4\",\n        \"2\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5444_1: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 42;\n        var b = function({} = setImmediate(function() {\n            console.log(a++);\n        })) {\n            return this;\n        }();\n        console.log(typeof b);\n    }\n    expect: {\n        var a = 42;\n        var b = function({} = setImmediate(function() {\n            console.log(a++);\n        })) {\n            return this;\n        }();\n        console.log(typeof b);\n    }\n    expect_stdout: [\n        \"object\",\n        \"42\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5444_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, b = a++) {\n            return b;\n        }\n        console.log(f(\"FAIL\") || \"PASS\");\n    }\n    expect: {\n        function f(a, b = a++) {\n            return b;\n        }\n        console.log(f(\"FAIL\") || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5444_3: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, b = function(c = a *= this) {\n            return c;\n        }()) {\n            return b;\n        }\n        console.log(f(\"FAIL\") || \"PASS\");\n    }\n    expect: {\n        function f(a, b = function(c = a *= this) {\n            return c;\n        }()) {\n            return b;\n        }\n        console.log(f(\"FAIL\") || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5448_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a = typeof console.log) {\n            do {\n                var b = [ ...a ];\n            } while (console.log(\"PASS\"));\n        })();\n    }\n    expect: {\n        (function(a = console.log) {\n            do {} while (console.log(\"PASS\"));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5448_2: {\n    options = {\n        keep_fargs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a = typeof console) {\n            do {\n                var b = [ ...a ];\n            } while (console.log(\"PASS\"));\n        })();\n    }\n    expect: {\n        (function(a = 0) {\n            do {} while (console.log(\"PASS\"));\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5448_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var [ a = typeof console ] = [ void console.log(\"PASS\") ];\n        var b = [ ...a ];\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5448_4: {\n    options = {\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var { p: a = typeof console } = { p: void console.log(\"PASS\") };\n        var b = [ ...a ];\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5463: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        if (console.log(\"PASS\"))\n            var a = void 0,\n                b = void 0,\n                b = ([ a = FAIL ] = b && b);\n    }\n    expect: {\n        var a, b, b;\n        console.log(\"PASS\") && (\n            b = a = void 0,\n            b = [a = FAIL] = a\n        );\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5465: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            (function(c = b = \"FAIL 2\") {\n                this && console.log(b || \"PASS\");\n            })(42 - a && a);\n        }\n        f(\"FAIL 1\");\n    }\n    expect: {\n        a = \"FAIL 1\",\n        void function(c = b = \"FAIL 2\") {\n            this && console.log(b || \"PASS\");\n        }(42 - a && a);\n        var a, b;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5485: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        (function f(f, a = console.log(void 0 === f ? \"PASS\" : \"FAIL\")) {})();\n    }\n    expect: {\n        (function f(f, a = console.log(void 0 === f ? \"PASS\" : \"FAIL\")) {})();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_1_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b = 42) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_1_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b = 42) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_2_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f([ b ] = []) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;) {\n                    var [ [] = [] ] = [];\n                    throw \"PASS\";\n                }\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_2_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f([ b ] = []) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;) {\n                    var [ [ , ] = [] ] = [];\n                    throw \"PASS\";\n                }\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_3_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b = 42, c = null) {\n                            c;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_3_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b = 42, c = null) {\n                            c;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_4_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b = 42, [ c ] = []) {\n                            c;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;) {\n                    var [ [] = [] ] = [];\n                    throw \"PASS\";\n                }\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_4_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b = 42, [ c ] = []) {\n                            c;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;) {\n                    var [ [] = [] ] = [];\n                    throw \"PASS\";\n                }\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5536: {\n    options = {\n        inline: true,\n        keep_fargs: true,\n        unused: true,\n    }\n    input: {\n        (function*() {\n            (([], a = 42) => {})([]);\n            console.log(typeof a);\n        })().next();\n    }\n    expect: {\n        (function*() {\n            [ , [][0] = 0 ] = [ [] ],\n            void 0;\n            console.log(typeof a);\n        })().next();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_5566_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            var a = \"foo\";\n            console.log(a, f());\n        })(\"bar\");\n    }\n    expect: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            var a = \"foo\";\n            console.log(a, f());\n        })(\"bar\");\n    }\n    expect_stdout: \"foo bar\"\n    node_version: \">=6\"\n}\n\nissue_5566_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            function a() {}\n            console.log(typeof a, typeof f());\n        })(42);\n    }\n    expect: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            function a() {}\n            console.log(typeof a, typeof f());\n        })(42);\n    }\n    expect_stdout: \"function number\"\n    node_version: \">=6\"\n}\n\nissue_5566_3: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            function a() {}\n            console.log(typeof a, typeof f());\n        })(42);\n    }\n    expect: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            function a() {}\n            console.log(typeof a, typeof f());\n        })(42);\n    }\n    expect_stdout: \"function number\"\n    node_version: \">=6\"\n}\n\nissue_5566_4: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b = function() {\n            return a;\n        }) {\n            var a = 0;\n            b()(\"PASS\");\n        })(console.log);\n    }\n    expect: {\n        (function(a, b = function() {\n            return a;\n        }) {\n            var a = 0;\n            b()(\"PASS\");\n        })(console.log);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5566_5: {\n    options = {\n        hoist_vars: true,\n    }\n    input: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            var a = \"foo\";\n            var b;\n            console.log(a, f());\n        })(\"bar\");\n    }\n    expect: {\n        (function(a, f = function() {\n            return a;\n        }) {\n            var a, b;\n            a = \"foo\";\n            console.log(a, f());\n        })(\"bar\");\n    }\n    expect_stdout: \"foo bar\"\n    node_version: \">=6\"\n}\n\nissue_5651: {\n    options = {\n        ie: true,\n        unused: true,\n    }\n    input: {\n        console.log(function arguments(a = \"FAIL\") {\n            try {} catch (arguments) {\n                var arguments;\n            }\n            return arguments[0];\n        }());\n    }\n    expect: {\n        console.log(function arguments(a = \"FAIL\") {\n            try {} catch (arguments) {\n                var arguments;\n            }\n            return arguments[0];\n        }());\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_5774: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        join_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        unsafe: true,\n    }\n    input: {\n        (function() {\n            while (console.log(\"PASS\")) {\n                if (console) {\n                    a = void 0;\n                    var b = void 0;\n                    var c = void 0;\n                    ([ a = 0 ] = [ b, b ]);\n                    var a;\n                }\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            while (console.log(\"PASS\")) {\n                var a, b, c, a;\n                console && (\n                    c = b = a = void 0,\n                    [ a = 0 ] = [ a, a ]\n                );\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5863: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n    }\n    input: {\n        console.log(typeof function f(a = function() {\n            f = 42;\n            return f;\n        }()) {\n            var f;\n            var f;\n            return a;\n        }());\n    }\n    expect: {\n        console.log(typeof function f(a = function() {\n            f = 42;\n            return f;\n        }()) {\n            var f;\n            return a;\n        }());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_5963: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = Object.create(null);\n        [ a.PASS = 42 ] = [];\n        a.FAIL;\n        for (var p in a)\n            console.log(p);\n    }\n    expect: {\n        var a = Object.create(null);\n        [ a.PASS = 42 ] = [];\n        for (var p in a)\n            console.log(p);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n"
  },
  {
    "path": "test/compress/destructured.js",
    "content": "redefine_arguments_1: {\n    options = {\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        function f([ arguments ]) {}\n    }\n    expect: {\n        function f([]) {}\n    }\n    expect_stdout: true\n    node_version: \">=8\"\n}\n\nredefine_arguments_1_toplevel: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f([ arguments ]) {}\n    }\n    expect: {}\n    expect_stdout: true\n    node_version: \">=8\"\n}\n\nredefine_arguments_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (function([], arguments) {});\n    }\n    expect: {}\n    expect_stdout: true\n    node_version: \">=8\"\n}\n\nredefine_arguments_3: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function([], arguments) {})([]);\n    }\n    expect: {\n        (function() {})();\n    }\n    expect_stdout: true\n    node_version: \">=8\"\n}\n\nredefine_arguments_4: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            (function({}, arguments) {});\n        }\n    }\n    expect: {}\n    expect_stdout: true\n    node_version: \">=8\"\n}\n\nuses_arguments_1_merge_vars: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(typeof function({}) {\n            return arguments;\n        }(42));\n    }\n    expect: {\n        console.log(typeof function({}) {\n            return arguments;\n        }(42));\n    }\n    expect_stdout: \"object\"\n    node_version: \">=6\"\n}\n\nuses_arguments_1_unused: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(typeof function({}) {\n            return arguments;\n        }(42));\n    }\n    expect: {\n        console.log(typeof function({}) {\n            return arguments;\n        }(42));\n    }\n    expect_stdout: \"object\"\n    node_version: \">=6\"\n}\n\nuses_arguments_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(typeof function({ a }) {\n            a[1] = 2;\n            return arguments;\n        }({ a: 42 }));\n    }\n    expect: {\n        console.log(typeof function({ a }) {\n            a[1] = 2;\n            return arguments;\n        }({ a: 42 }));\n    }\n    expect_stdout: \"object\"\n    node_version: \">=6\"\n}\n\nfunarg_merge_vars_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, {\n            [a]: b\n        }) {\n            console.log(b);\n        }\n        f(0, [ \"PASS\" ]);\n    }\n    expect: {\n        function f(a, {\n            [a]: b\n        }) {\n            console.log(b);\n        }\n        f(0, [ \"PASS\" ]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_merge_vars_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a = 0;\n        (function f({\n            [a]: b,\n        }) {\n            var a = typeof b;\n            console.log(a);\n        })([ 42 ]);\n    }\n    expect: {\n        var a = 0;\n        (function f({\n            [a]: b,\n        }) {\n            var a = typeof b;\n            console.log(a);\n        })([ 42 ]);\n    }\n    expect_stdout: \"number\"\n    node_version: \">=6\"\n}\n\nfunarg_side_effects_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function({}) {})();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [ {} ] = [];\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_side_effects_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function({\n                [(a, 0)]: a,\n            }) {})(1);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function({\n                [(a, 0)]: a,\n            }) {})(1);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6.9.2\"\n}\n\nfunarg_side_effects_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function({\n                p: {\n                    [(a, 0)]: a,\n                },\n            }) {})({\n                p: 1,\n            });\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function({\n                p: {\n                    [(a, 0)]: a,\n                },\n            }) {})({\n                p: 1,\n            });\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6.9.2\"\n}\n\nfunarg_unused_1: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function([]) {})([ console.log(\"PASS\") ]);\n    }\n    expect: {\n        (function() {})(console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_unused_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f([ a, b, c ]) {\n            console.log(b);\n        }\n        f([ \"FAIL\", \"PASS\" ]);\n    }\n    expect: {\n        function f([ , b ]) {\n            console.log(b);\n        }\n        f([ \"FAIL\", \"PASS\" ]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_unused_3: {\n    options = {\n        objects: true,\n        evaluate: true,\n        unused: true,\n    }\n    input: {\n        function f({\n            [0]: a,\n        }) {\n            return \"PASS\";\n        }\n        console.log(f([ \"FAIL\" ]));\n    }\n    expect: {\n        function f({}) {\n            return \"PASS\";\n        }\n        console.log(f([ \"FAIL\" ]));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_unused_4: {\n    options = {\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        console.log(function([ a ], { b }, c) {\n            return \"PASS\";\n        }([ 1 ], { b: 2 }, 3));\n    }\n    expect: {\n        console.log(function() {\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_unused_5: {\n    options = {\n        unused: true,\n    }\n    input: {\n        try {\n            (function({\n                [c = 0]: c\n            }) {})(1);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function({\n                [c = 0]: c\n            }) {})(1);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_unused_6_inline: {\n    options = {\n        inline: true,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var {} = (a = console, 42);\n        })();\n        console.log(typeof a);\n    }\n    expect: {\n        void console;\n        console.log(typeof a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nfunarg_unused_6_keep_fargs: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var {} = (a = console, 42);\n        })();\n        console.log(typeof a);\n    }\n    expect: {\n        (function() {\n            console;\n            var {} = 42;\n        })();\n        console.log(typeof a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nfunarg_collapse_vars_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, {}) {\n            return typeof a;\n            var b;\n        }(console, {}));\n    }\n    expect: {\n        console.log(function(a, {}) {\n            return typeof (0, console);\n        }(0, {}));\n    }\n    expect_stdout: \"object\"\n    node_version: \">=6\"\n}\n\nfunarg_collapse_vars_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function([ a ], { b }, c) {\n            return a + b + c;\n        }([ \"P\" ], { b: \"A\" }, \"SS\"));\n    }\n    expect: {\n        console.log(function([ a ], { b }) {\n            return a + b + \"SS\";\n        }([ \"P\" ], { b: \"A\" }));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_collapse_vars_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            (function({}) {})();\n            throw \"PASS\";\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            (function({}) {})();\n            throw \"PASS\";\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_collapse_vars_4: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(b, { log: c }) {\n            c(b);\n        })(a, console);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b, { log: c }) {\n            c(a);\n        })(0, console);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_collapse_vars_5: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        B = \"PASS\";\n        try {\n            console.log(function({}, a) {\n                return a;\n            }(null, A = B));\n        } catch (e) {}\n        console.log(A);\n    }\n    expect: {\n        A = \"FAIL\";\n        B = \"PASS\";\n        try {\n            console.log(function({}, a) {\n                return a;\n            }(null, A = B));\n        } catch (e) {}\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_collapse_vars_6: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        B = \"PASS\";\n        function f() {\n            console.log(function({}, a) {\n                return a;\n            }(null, A = B));\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(A);\n        }\n    }\n    expect: {\n        A = \"FAIL\";\n        B = \"PASS\";\n        function f() {\n            console.log(function({}, a) {\n                return a;\n            }(null, A = B));\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(A);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_reduce_vars_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        try {\n            (function({\n                [a]: b,\n            }, a) {\n                console.log(\"FAIL\");\n            })({});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function({\n                [a]: b,\n            }, a) {\n                console.log(\"FAIL\");\n            })({});\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_reduce_vars_2: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function([ a ], { b }, c) {\n            return a + b + c;\n        }([ \"P\" ], { b: \"A\" }, \"SS\"));\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_reduce_vars_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        (function({\n            [a++]: b\n        }) {})(0);\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function({\n            [a++]: b\n        }) {})(0);\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n    node_version: \">=6\"\n}\n\nfunarg_reduce_vars_4: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        try {\n            (function f({\n                [a = 1]: a,\n            }) {})(2);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function f({\n                [a = 1]: a,\n            }) {})(2);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfunarg_computed_key_scope_1: {\n    rename = true\n    input: {\n        var b = 0;\n        function f({\n            [b]: a\n        }) {\n            var b = 42;\n            console.log(a, b);\n        }\n        f([ \"PASS\" ]);\n    }\n    expect: {\n        var b = 0;\n        function f({\n            [b]: a\n        }) {\n            var c = 42;\n            console.log(a, c);\n        }\n        f([ \"PASS\" ]);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nfunarg_computed_key_scope_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function({\n            [function() {\n                console.log(typeof f);\n            }()]: a\n        }) {\n            function f() {}\n        })(0);\n    }\n    expect: {\n        (function({\n            [function() {\n                console.log(typeof f);\n            }()]: a\n        }) {})(0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nfunarg_computed_key_scope_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function({\n            [function() {\n                (function({\n                    [function() {\n                        console.log(typeof f, typeof g, typeof h);\n                    }()]: a\n                }) {\n                    function f() {}\n                })(1);\n                function g() {}\n            }()]: b\n        }) {\n            function h() {}\n        })(2);\n    }\n    expect: {\n        (function({\n            [function() {\n                (function({\n                    [function() {\n                        console.log(typeof f, typeof function() {}, typeof h);\n                    }()]: a\n                }) {})(1);\n            }()]: b\n        }) {})(2);\n    }\n    expect_stdout: \"undefined function undefined\"\n    node_version: \">=6\"\n}\n\nfunarg_inline: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            function f({}) {\n                return 42;\n            }\n            var a = f();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [ {} ] = [];\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nprocess_returns: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        console.log(function({ length }) {\n            return length ? \"FAIL\" : \"PASS\";\n        }(function() {\n            return 42;\n        }));\n    }\n    expect: {\n        console.log(function({ length }) {\n            return length ? \"FAIL\" : \"PASS\";\n        }(function() {}));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nsimple_const: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        const [ a ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nsimple_let: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        let [ a ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nsimple_var: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var [ a ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_catch: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        try {} catch ({\n            [console.log(\"FAIL\")]: e,\n        }) {} finally {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_catch_var: {\n    options = {\n        unused: true,\n    }\n    input: {\n        try {\n            throw new Error(\"PASS\");\n        } catch ({ name, message }) {\n            console.log(message);\n        }\n    }\n    expect: {\n        try {\n            throw new Error(\"PASS\");\n        } catch ({ message }) {\n            console.log(message);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"PASS\";\n        var {\n            [a.p]: a,\n        } = !console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        var {\n            [a.p]: a,\n        } = !console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function() {\n            [] = [];\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            [] = [];\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            [ a ] = (a = \"FAIL\", [ \"PASS\" ]);\n            return a;\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            [ a ] = (a = \"FAIL\", [ \"PASS\" ]);\n            return a;\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_4: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        try {\n            a = 42;\n            [ 42..p ] = null;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a;\n        try {\n            a = 42;\n            [ 42..p ] = null;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_5: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        try {\n            [] = (a = 42, null);\n            a = 42;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a;\n        try {\n            [] = (a = 42, null);\n            a = 42;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_6: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        try {\n            var [] = (a = 42, null);\n            a = 42;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a;\n        try {\n            var [] = (a = 42, null);\n            a = 42;\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_7: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                [] = (a = \"PASS\", null);\n                return \"PASS\";\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                [] = (a = \"PASS\", null);\n                return \"PASS\";\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_8: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                var {} = (a = \"PASS\", null);\n                return \"PASS\";\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                var {} = (a = \"PASS\", null);\n                return \"PASS\";\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_9: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                var b = function([ c ]) {\n                    if (c)\n                        return \"FAIL 1\";\n                }();\n                a = \"FAIL 2\";\n                return b;\n            } catch (e) {\n                return a;\n            }\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                var b = function([ c ]) {\n                    if (c)\n                        return \"FAIL 1\";\n                }();\n                a = \"FAIL 2\";\n                return b;\n            } catch (e) {\n                return a;\n            }\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nconditionals: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (console.log(\"PASS\")) {\n            var [] = 0;\n        }\n    }\n    expect: {\n        console.log(\"PASS\") && ([] = 0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndead_code: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n    }\n    input: {\n        if (0) {\n            let [] = 42;\n            var { a, b: [ c ] } = null;\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        0;\n        var a, c;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_unused_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        switch (0) {\n          case console.log(a, a):\n            try {\n                throw 42;\n            } catch (a) {\n                var [ a ] = [];\n            }\n        }\n    }\n    expect: {\n        switch (0) {\n          case console.log(a, a):\n            try {\n                throw 42;\n            } catch (a) {\n                var a = [][0];\n            }\n        }\n    }\n    expect_stdout: \"undefined undefined\"\n    node_version: \">=6\"\n}\n\ndrop_unused_2: {\n    options = {\n        merge_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b = [ console.log(\"PASS\"), a ], {\n                p: a,\n            } = 0;\n        }\n        f();\n    }\n    expect: {\n        (function(a) {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_hole: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var [ a ] = [ , ];\n        console.log(a);\n    }\n    expect: {\n        var a = [][0];\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nkeep_key_1: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = {\n            [(console.log(\"PASS\"), 42)]: null,\n        });\n    }\n    expect: {\n        ({} = {\n            [(console.log(\"PASS\"), 42)]: 0,\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nkeep_key_2: {\n    options = {\n        evaluate: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var { 42: a } = { [(console.log(\"PASS\"), 42)](){} };\n    }\n    expect: {\n        var {} = { [(console.log(\"PASS\"), 42)]: 0 };\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nkeep_key_2_pure_getters: {\n    options = {\n        evaluate: true,\n        pure_getters: \"strict\",\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var { 42: a } = { [(console.log(\"PASS\"), 42)](){} };\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nkeep_reference: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = [ {}, 42 ];\n        var [ b, c ] = a;\n        console.log(a[0] === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = [ {}, 42 ];\n        var b = a[0];\n        console.log(a[0] === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmaintain_position_assign: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(([ , ] = [ , \"PASS\" ])[1]);\n    }\n    expect: {\n        console.log([ , \"PASS\" ][1]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmaintain_position_var: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        var [ a, b ] = [ A ];\n        console.log(b || \"PASS\");\n    }\n    expect: {\n        A = \"FAIL\";\n        var b = [ A ][1];\n        console.log(b || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nside_effects_array: {\n    options = {\n        unused: true,\n    }\n    input: {\n        try {\n            var [ a ] = 42;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            var [ a ] = 42;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nside_effects_object: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = null, b = console, { c } = 42;\n        try {\n            c[a = \"PASS\"];\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = null, c = (console, 42..c);\n        try {\n            c[a = \"PASS\"];\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\njoin_vars: {\n    options = {\n        conditionals: true,\n        join_vars: true,\n    }\n    input: {\n        const [ a ] = [ \"PASS\" ];\n        a,\n        console.log(a);\n    }\n    expect: {\n        const [ a ] = [ \"PASS\" ];\n        a,\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nkeep_fargs: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            var {} = a;\n        }(0));\n    }\n    expect: {\n        console.log(function(a) {\n            var {} = a;\n        }(0));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nreduce_vars_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(\"PASS\") && ([ a ] = 0);\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\") && ([ a ] = 0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_vars_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\", b = 42;\n        ({\n            [console.log(a, b)]: b.p\n        } = a = \"PASS\");\n    }\n    expect: {\n        ({\n            [console.log(\"PASS\", 42)]: 42..p\n        } = \"PASS\");\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\ncomputed_key_evaluate: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, {\n            [++a]: b,\n        } = [ \"FAIL 1\", a ? \"FAIL 2\" : \"PASS\" ];\n        console.log(b);\n    }\n    expect: {\n        var a = 0, {\n            [1]: b,\n        } = [ \"FAIL 1\", 0 ? \"FAIL 2\" : \"PASS\" ];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncomputed_key_unused: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var {\n            [console.log(\"bar\")]: a,\n            [console.log(\"baz\")]: { b },\n            [console.log(\"moo\")]: [\n                c,\n                {\n                    [console.log(\"moz\")]: d,\n                    e,\n                },\n            ],\n        } = {\n            [console.log(\"foo\")]: [ null, 42 ],\n        };\n    }\n    expect: {\n        var {\n            [console.log(\"bar\")]: a,\n            [console.log(\"baz\")]: {},\n            [console.log(\"moo\")]: [\n                ,\n                {\n                    [console.log(\"moz\")]: d,\n                },\n            ],\n        } = {\n            [console.log(\"foo\")]: [ null, 42 ],\n        };\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"moo\",\n        \"moz\",\n    ]\n    node_version: \">=6\"\n}\n\nfor_in_1: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var { a } in console.log(\"PASS\"));\n    }\n    expect: {\n        for (var { a } in console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfor_in_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a;\n        for (var { b } in console.log(\"PASS\"));\n    }\n    expect: {\n        var a, b;\n        for ({ b } in console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfor_in_3: {\n    options = {\n        merge_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        for (var { length: a } in [ 42 ])\n            console.log(a);\n    }\n    expect: {\n        for (var { length: a } in [ 42 ])\n            console.log(a);\n    }\n    expect_stdout: \"1\"\n    node_version: \">=6\"\n}\n\nfn_name_evaluate: {\n    options = {\n        evaluate: true,\n        objects: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        console.log(function f({\n            [typeof f]: a,\n        }) {\n            var f;\n            return a;\n        }({\n            function: \"PASS\",\n            undefined: \"FAIL\",\n        }));\n    }\n    expect: {\n        console.log(function f({\n            function: a,\n        }) {\n            var f;\n            return a;\n        }({\n            function: \"PASS\",\n            undefined: \"FAIL\",\n        }));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nfn_name_unused: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function f({\n            [typeof f]: a,\n        }) {\n            var f;\n            return a;\n        }({\n            function: \"PASS\",\n            undefined: \"FAIL\",\n        }));\n    }\n    expect: {\n        console.log(function f({\n            [typeof f]: a,\n        }) {\n            var f;\n            return a;\n        }({\n            function: \"PASS\",\n            undefined: \"FAIL\",\n        }));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nhoist_vars: {\n    options = {\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        var [ b ] = [ 42 ];\n        console.log(a, b);\n    }\n    expect: {\n        var a = \"PASS\", b = [ 42 ][0];\n        console.log(a, b);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nsingleton_1: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var [ a ] = \"P\", b, o = {};\n        [ { 1: o.p } ] = [ \"FAIL\" ];\n        ({ foo: [ o.q ] } = { foo: \"S\" });\n        [ b = \"S\" ] = [];\n        console.log(a + o.p + o.q + b);\n    }\n    expect: {\n        var b, a = \"P\"[0], o = {};\n        o.p = [ \"FAIL\"[\"1\"] ][0];\n        o.q = { foo: \"S\"[0] }.foo;\n        [ b = \"S\" ] = [];\n        console.log(a + o.p + o.q + b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nsingleton_2: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        pure_getters: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var [ a ] = \"P\", b, o = {};\n        [ { 1: o.p } ] = [ \"FAIL\" ];\n        ({ foo: [ o.q ] } = { foo: \"S\" });\n        [ b = \"S\" ] = [];\n        console.log(a + o.p + o.q + b);\n    }\n    expect: {\n        var b, a = \"P\", o = {};\n        o.p = \"A\";\n        o.q = \"S\";\n        [ b = \"S\" ] = [];\n        console.log(a + o.p + o.q + b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nsingleton_side_effects: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        [ 42[console.log(\"foo\")] ] = [ console.log(\"bar\") ];\n    }\n    expect: {\n        [ 42[console.log(\"foo\")] ] = [ console.log(\"bar\") ];\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=6\"\n}\n\nmangle_properties: {\n    mangle = {\n        properties: {\n            domprops: true,\n        },\n    }\n    input: {\n        function f({ p: a }) {\n            return a;\n        }\n        console.log(f({ p: \"PASS\" }));\n    }\n    expect_exact: 'function f({n}){return n}console.log(f({n:\"PASS\"}));'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4280: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var {\n            1: a,\n        } = 2;\n        console.log(a);\n    }\n    expect: {\n        var {} = 2;\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4282: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            ({\n                [a = \"bar\"]: 0[console.log(a)],\n            } = 0);\n        })(\"foo\");\n    }\n    expect: {\n        (function(a) {\n            ({\n                [a = \"bar\"]: 0[console.log(a)],\n            } = 0);\n        })(\"foo\");\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4284_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a, {\n            0: b,\n        } = a = \"foo\";\n        console.log(a, b);\n    }\n    expect: {\n        var a, {\n            0: b,\n        } = a = \"foo\";\n        console.log(a, b);\n    }\n    expect_stdout: \"foo f\"\n    node_version: \">=6\"\n}\n\nissue_4284_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, {\n            [console.log(a)]: b,\n        } = (a = \"PASS\", 0);\n        var c = a;\n    }\n    expect: {\n        var a, {\n            [console.log(a)]: b,\n        } = (a = \"PASS\", 0);\n        var c = a;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4284_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a, b;\n        ({\n            [console.log(a)]: b,\n        } = (a = \"PASS\", 0));\n        var c = a;\n    }\n    expect: {\n        var a, b;\n        ({\n            [console.log(a)]: b,\n        } = (a = \"PASS\", 0));\n        var c = a;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4286_1: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        (0 && a)[{ a } = b = a];\n        console.log(b);\n    }\n    expect: {\n        var a = \"PASS\", b;\n        (0 && a)[{ a } = b = a];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4286_2: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        a = [ \"PASS\" ];\n        var b, { a } = b = a;\n        console.log(b[0]);\n    }\n    expect: {\n        var b, { a } = b = a = [ \"PASS\" ];\n        console.log(b[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4288: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f({\n            [new function() {\n                console.log(typeof b);\n            }()]: a,\n        }) {\n            var b = a;\n            b++;\n        }\n        f(0);\n    }\n    expect: {\n        function f({\n            [new function() {\n                console.log(typeof b);\n            }()]: a,\n        }) {\n            var a = a;\n            a++;\n        }\n        f(0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4294: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        A = \"PASS\";\n        (function() {\n            var a = function({\n                [a]: {},\n            }) {}({\n                [a]: 0,\n            });\n            var b = A;\n            console.log(b);\n        })();\n    }\n    expect: {\n        A = \"PASS\";\n        (function() {\n            var a = function({\n                [a]: {},\n            }) {}({\n                [a]: 0,\n            });\n            var b = A;\n            console.log(b);\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4297: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function(a) {\n            return { a } = a;\n        }(function() {}));\n    }\n    expect: {\n        console.log(typeof function(a) {\n            return { a } = a;\n        }(function() {}));\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_4298: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function() {\n            var a = {\n                object: \"PASS\",\n            };\n            function f({\n                [typeof a]: b,\n            }) {\n                var a = b;\n                return a;\n            }\n            var c = f(a);\n            console.log(c);\n        })();\n    }\n    expect: {\n        (function() {\n            var a = {\n                object: \"PASS\",\n            };\n            function f({\n                [typeof a]: b,\n            }) {\n                var a = b;\n                return a;\n            }\n            var c = f(a);\n            console.log(c);\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4301: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        try {\n            console.log(function() {\n                var a, b = console;\n                return {\n                    [a = b]: a.p,\n                } = \"foo\";\n            }());\n        } catch (e) {\n            console.log(\"bar\");\n        }\n    }\n    expect: {\n        try {\n            console.log(function() {\n                var a, b = console;\n                return {\n                    [a = b]: a.p,\n                } = \"foo\";\n            }());\n        } catch (e) {\n            console.log(\"bar\");\n        }\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4308: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        console.log(function({\n            [a = \"FAIL\"]: b\n        }, c) {\n            return c;\n        }(0, a));\n    }\n    expect: {\n        var a = \"PASS\";\n        console.log(function({\n            [a = \"FAIL\"]: b\n        }, c) {\n            return c;\n        }(0, a));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4312: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function f(b, c) {\n            return function({\n                [a = b]: d,\n            }) {}(c && c);\n        })(\"PASS\", \"FAIL\");\n        console.log(a);\n    }\n    expect: {\n        b = \"PASS\",\n        c = \"FAIL\",\n        [\n            {\n                [c = b]: d,\n            },\n        ] = [ c && c ],\n        void 0;\n        var b, c, d;\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4315: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console;\n        }\n        var a = function() {\n            if ([ 0[f && f] ] = [])\n                return this;\n        }(), b;\n        do {\n            console.log(\"PASS\");\n        } while (0 && (b = 0), b && a);\n    }\n    expect: {\n        [ 0[function() {\n            console\n        }] ] = [];\n        do {\n            console.log(\"PASS\");\n        } while (void 0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4319: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a) {\n            while (!a);\n        }\n        console.log(function({}) {\n            return f(console);\n        }(0));\n    }\n    expect: {\n        function f(a) {\n            while (!a);\n        }\n        console.log(([ {} ] = [ 0 ], f(console)));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4321: {\n    options = {\n        inline: 3,\n        keep_fargs: false,\n    }\n    input: {\n        try {\n            console.log(function({}) {\n                return function() {\n                    while (!console);\n                }();\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            console.log(([ {} ] = [], function() {\n                while (!console);\n            }()));\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4323: {\n    options = {\n        ie: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function b({\n            [function a() {\n                console.log(typeof a);\n            }()]: d,\n        }) {})(0);\n        (function c(e) {\n            e.p;\n        })(1, console.log);\n    }\n    expect: {\n        var a = 0;\n        [\n            {\n                [function a() {\n                    console.log(typeof a);\n                }()]: d,\n            },\n        ] = [ 0 ],\n        void 0;\n        var d;\n        e = 1,\n        console.log,\n        void e.p;\n        var e;\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_4355: {\n    options = {\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function({\n            [function() {\n                for (a in \"foo\");\n            }()]: b,\n        }) {\n            var a;\n        })(0);\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (function({\n            [function() {\n                for (a in \"foo\");\n            }()]: b,\n        }) {})(0);\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n    node_version: \">=6\"\n}\n\nissue_4372_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        a += {\n            [console.log(a)]: a,\n        } = a = \"PASS\";\n    }\n    expect: {\n        var a = \"FAIL\";\n        a += {\n            [console.log(a)]: a,\n        } = a = \"PASS\";\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4372_2: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a;\n        [ a ] = a = [ \"PASS\", \"FAIL\" ];\n        console.log(a);\n    }\n    expect: {\n        var a;\n        [ a ] = a = [ \"PASS\", \"FAIL\" ];\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4383: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(a) {\n            [ a[0] ] = [];\n            return a.length;\n        }([]));\n    }\n    expect: {\n        console.log(function(a) {\n            [ a[0] ] = [];\n            return a.length;\n        }([]));\n    }\n    expect_stdout: \"1\"\n    node_version: \">=6\"\n}\n\nissue_4386: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        function f({}) {\n            return arguments[0];\n        }\n        console.log(f(\"PASS\"));\n    }\n    expect: {\n        function f({}) {\n            return arguments[0];\n        }\n        console.log(f(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4395: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        console.log(function(a, {}) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\", 42));\n    }\n    expect: {\n        console.log(function(a, {}) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\", 42));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4399: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        console.log(function({\n            [arguments[1]]: a,\n        }, b) {\n            return a;\n        }([ \"PASS\" ], 0));\n    }\n    expect: {\n        console.log(function({\n            [arguments[1]]: a,\n        }, b) {\n            return a;\n        }([ \"PASS\" ], 0));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4420: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 1;\n            try {\n                throw [ \"FAIL\", \"PASS\" ];\n            } catch ({\n                [a]: b,\n            }) {\n                let a = 0;\n                return b;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a = 1;\n            try {\n                throw [ \"FAIL\", \"PASS\" ];\n            } catch ({\n                [a]: b,\n            }) {\n                return b;\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4425: {\n    rename = true\n    input: {\n        var a;\n        console.log(function() {\n            try {\n                try {\n                    throw 42;\n                } catch ({\n                    [a]: a,\n                }) {}\n                return \"FAIL\";\n            } catch (e) {\n                return \"PASS\";\n            }\n        }());\n    }\n    expect: {\n        var a;\n        console.log(function() {\n            try {\n                try {\n                    throw 42;\n                } catch ({\n                    [b]: b,\n                }) {}\n                return \"FAIL\";\n            } catch (c) {\n                return \"PASS\";\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nissue_4436_Infinity: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function({\n            [delete Infinity]: a,\n        }) {\n            var Infinity;\n            return a;\n        }({\n            true: \"FAIL\",\n            false: \"PASS\",\n        }));\n    }\n    expect: {\n        console.log(function({\n            [delete Infinity]: a,\n        }) {\n            return a;\n        }({\n            true: \"FAIL\",\n            false: \"PASS\",\n        }));\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4436_NaN: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function({\n            [delete NaN]: a,\n        }) {\n            var NaN;\n            return a;\n        }({\n            true: \"FAIL\",\n            false: \"PASS\",\n        }));\n    }\n    expect: {\n        console.log(function({\n            [delete NaN]: a,\n        }) {\n            return a;\n        }({\n            true: \"FAIL\",\n            false: \"PASS\",\n        }));\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4436_undefined: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function({\n            [delete undefined]: a,\n        }) {\n            var undefined;\n            return a;\n        }({\n            true: \"FAIL\",\n            false: \"PASS\",\n        }));\n    }\n    expect: {\n        console.log(function({\n            [delete undefined]: a,\n        }) {\n            return a;\n        }({\n            true: \"FAIL\",\n            false: \"PASS\",\n        }));\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4446: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        a = \"PASS\";\n        var a = [ a[0] ] = [ a ];\n        console.log(a[0]);\n    }\n    expect: {\n        a = \"PASS\";\n        var a = [ a[0] ] = [ a ];\n        console.log(a[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4456: {\n    options = {\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var o = {\n            set p(v) {\n                console.log(v);\n            },\n        };\n        [ function() {\n            try {\n                return o;\n            } catch ({}) {}\n        }().p ] = [ \"PASS\" ];\n    }\n    expect: {\n        var o = {\n            set p(v) {\n                console.log(v);\n            },\n        };\n        [ function() {\n            try {\n                return o;\n            } catch ({}) {}\n        }().p ] = [ \"PASS\" ];\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4485_1: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        (function([]) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })([]);\n    }\n    expect: {\n        (function([]) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })([]);\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4485_2: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        (function([]) {\n            var arguments = null;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })([]);\n    }\n    expect: {\n        (function([]) {\n            var arguments = null;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })([]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4485_3: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function([]) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })([]);\n    }\n    expect: {\n        (function([]) {\n            var arguments;\n            try {\n                arguments.length;\n            } catch (e) {\n                console.log(\"PASS\");\n            }\n        })([]);\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4500: {\n    options = {\n        evaluate: true,\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f(b) {\n            return [ b ] = [], b;\n        }(\"FAIL\");\n        console.log(a || \"PASS\");\n    }\n    expect: {\n        var a = function f(b) {\n            return [ b ] = [], b;\n        }(\"FAIL\");\n        console.log(a || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4504: {\n    options = {\n        inline: true,\n        merge_vars: true,\n    }\n    input: {\n        A = \"FAIL\";\n        (function f(a) {\n            ({\n                [console.log(a)]: 0[(b => console + b)(A)]\n            } = 0);\n        })(\"PASS\");\n    }\n    expect: {\n        A = \"FAIL\";\n        (function f(a) {\n            ({\n                [console.log(a)]: 0[b = A, console + b]\n            } = 0);\n            var b;\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4508: {\n    options = {\n        inline: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var i = 0; i < 2; i++)\n            (function f([ a ]) {\n                var a = console.log(a) && b, b = null;\n            })([ \"PASS\" ]);\n    }\n    expect: {\n        for (var i = 0; i < 2; i++)\n            [ [ a ] ] = [ [ \"PASS\" ] ],\n            b = void 0,\n            a = console.log(a) && b,\n            b = null,\n            void 0;\n        var a, b;\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4512: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console.log(function([ a, b = a ]) {}([]));\n    }\n    expect: {\n        console.log(function([ a, b = a ]) {}([]));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4519_1: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n    }\n    input: {\n        try {\n            (function() {\n                var [ arguments ] = [];\n                arguments[0];\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function() {\n                var [ arguments ] = [];\n                arguments[0];\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4519_2: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function() {\n                var [ arguments ] = [];\n                arguments[0];\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function() {\n                var [ arguments ] = [];\n                arguments[0];\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4554: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a = \"FAIL\";\n        try {\n            (function({}, b) {\n                return b;\n            })(void 0, a = A);\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        A = \"PASS\";\n        var a = \"FAIL\";\n        try {\n            (function({}, b) {\n                return b;\n            })(void 0, a = A);\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4584: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        try {\n            (function f({\n                [console.log(a = \"FAIL\")]: a,\n            }) {})(0);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function f({\n                [console.log(a = \"FAIL\")]: a,\n            }) {})(0);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4608_1: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n    }\n    input: {\n        (function() {\n            [ arguments ] = [ \"foo\" ];\n            console.log(arguments[0]);\n        })();\n    }\n    expect: {\n        (function() {\n            [ arguments ] = [ \"foo\" ];\n            console.log(arguments[0]);\n        })();\n    }\n    expect_stdout: \"f\"\n    node_version: \">=6\"\n}\n\nissue_4608_2: {\n    options = {\n        arguments: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function(a) {\n            [ arguments ] = [ \"foo\" ];\n            console.log(arguments[0]);\n        })();\n    }\n    expect: {\n        (function(a) {\n            [ arguments ] = [ \"foo\" ];\n            console.log(arguments[0]);\n        })();\n    }\n    expect_stdout: \"f\"\n    node_version: \">=6\"\n}\n\nissue_4994: {\n    options = {\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function([\n            {\n                [function() {\n                    for (a in { PASS: null });\n                }()]: b,\n            },\n        ]) {\n            var a;\n        })([ 42 ]);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function([\n            {\n                [function() {\n                    for (a in { PASS: null });\n                }()]: b,\n            },\n        ]) {})([ 42 ]);\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5017: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = function() {};\n        var b = c = a;\n        var c = [ c ] = [ c ];\n        console.log(c[0] === a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = function() {};\n        var b = a;\n        var c = [ c ] = [ c = a ];\n        console.log(c[0] === a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5071_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(([ , a ] = [ \"PA\", , ]).join(\"SS\"));\n    }\n    expect: {\n        var a;\n        console.log(([ , a ] = [ \"PA\", , ]).join(\"SS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5071_2: {\n    options = {\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var a;\n        ([ a ] = []).p = console.log(\"PASS\");\n    }\n    expect: {\n        var a;\n        ([ a ] = []).p = console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5074_getter: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = { get [(console.log(\"PASS\"), 42)]() {} });\n    }\n    expect: {\n        ({} = { [(console.log(\"PASS\"), 42)]: 0 });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5074_getter_pure_getters: {\n    options = {\n        evaluate: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = { get [(console.log(\"PASS\"), 42)]() {} });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5074_setter: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = { set [(console.log(\"PASS\"), 42)](v) {} });\n    }\n    expect: {\n        ({} = { [(console.log(\"PASS\"), 42)]: 0 });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5074_setter_pure_getters: {\n    options = {\n        evaluate: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = { set [(console.log(\"PASS\"), 42)](v) {} });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5074_method: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = { [(console.log(\"PASS\"), 42)]() {} });\n    }\n    expect: {\n        ({} = { [(console.log(\"PASS\"), 42)]: 0 });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5074_method_pure_getters: {\n    options = {\n        evaluate: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        ({} = { [(console.log(\"PASS\"), 42)]() {} });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5085_1: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        var [ b ] = [ 42, a ], c = b ? 0 : a = \"FAIL\";\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        42;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5085_2: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(b) {\n            [ b ] = [ 42, a ];\n            var c = b ? 0 : a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b) {\n            0;\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5087_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            (function() {\n                (function([ b ]) {\n                    b && console.log(b);\n                })([ a ]);\n            })();\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            var b;\n            (b = a) && console.log(b);\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5087_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        properties: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            (function() {\n                (function([ b ]) {\n                    b && console.log(b);\n                })([ a ]);\n            })();\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        a && console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5114_1: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function({}, a) {})(42);\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        [ {} ] = [ 42 ],\n        void 0;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5114_2: {\n    options = {\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function f([], a) {\n            f.length;\n        })([]);\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        0;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5114_3: {\n    options = {\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function f(a, {}) {\n            f.length;\n        })(null, 42);\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        0;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5153_array_assign: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = function*() {\n            yield b;\n        }(), b;\n        [ b ] = b = a;\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = function*() {\n            yield b;\n        }(), b;\n        [ b ] = b = a;\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5153_array_var: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = function*() {\n            yield b;\n        }(), [ b ] = b = a;\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = function*() {\n            yield b;\n        }(), [ b ] = b = a;\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5153_object_assign: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = {\n            get p() {\n                return b;\n            },\n        }, b;\n        ({\n            p: b\n        } = b = a);\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = {\n            get p() {\n                return b;\n            },\n        }, b;\n        ({\n            p: b\n        } = b = a);\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5153_object_var: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        var a = {\n            get p() {\n                return b;\n            },\n        }, {\n            p: b\n        } = b = a;\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = {\n            get p() {\n                return b;\n            },\n        }, {\n            p: b\n        } = b = a;\n        console.log(a === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5168: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        (function a({\n            [console.log(typeof function() {\n                ++a;\n                return a;\n            }())]: b,\n        }) {\n            var a;\n        })({});\n    }\n    expect: {\n        (function a({\n            [console.log(typeof function() {\n                ++a;\n                return a;\n            }())]: b,\n        }) {\n            var a;\n        })({});\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_5189_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        [ a.p ] = a = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        var a;\n        [ a.p ] = a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5189_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        ({ p: a.q } = a = \"PASS\");\n        console.log(a);\n    }\n    expect: {\n        var a;\n        ({ p: a.q } = a = \"PASS\");\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5222: {\n    options = {\n        hoist_props: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            do {\n                (function() {\n                    var a = {\n                        p: [ a ] = [],\n                    };\n                })();\n            } while (console.log(\"PASS\"));\n        }\n        f();\n    }\n    expect: {\n        do {\n            a = void 0,\n            a = {\n                p: [ a ] = [],\n            };\n        } while (console.log(\"PASS\"));\n        var a;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5288_1: {\n    options = {\n        conditionals: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        while (function([]) {}([ function f() {\n            if (console)\n                return console.log(\"PASS\");\n            else {\n                let a = 0;\n            }\n        }() ]));\n    }\n    expect: {\n        while (function() {\n            if (console)\n                console.log(\"PASS\");\n        }(), void 0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5288_2: {\n    options = {\n        conditionals: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        while (function([]) {}([ function f() {\n            if (console)\n                return console.log(\"PASS\");\n            else {\n                let a = 0;\n            }\n        }() ]));\n    }\n    expect: {\n        while (console && console.log(\"PASS\"), void 0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5314_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        A = this;\n        new function() {\n            (function({\n                [console.log(this === A ? \"PASS\" : \"FAIL\")]: a,\n            }) {})(42);\n        }();\n    }\n    expect: {\n        A = this;\n        (function() {\n            (function({\n                [console.log(this === A ? \"PASS\" : \"FAIL\")]: a,\n            }) {})(42);\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5314_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        A = this;\n        new function() {\n            (({\n                [console.log(this === A ? \"FAIL\" : \"PASS\")]: a,\n            }) => {})(42);\n        }();\n    }\n    expect: {\n        A = this;\n        new function() {\n            [ {\n                [console.log(this === A ? \"FAIL\" : \"PASS\")]: [][0],\n            } ] = [ 42 ];\n        }();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5370: {\n    options = {\n        dead_code: true,\n        ie: true,\n        unused: true,\n    }\n    input: {\n        console.log(function arguments({}) {\n            return arguments;\n            try {} catch (e) {\n                var arguments;\n            }\n        }(42));\n    }\n    expect: {\n        console.log(function arguments({}) {\n            return arguments;\n            var arguments;\n        }(42));\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_5405_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var [ a ] = [ {} ];\n        console.log(a === a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var [ a ] = [ {} ];\n        console.log(true ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5405_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var { p: a } = { p: [] };\n        console.log(a === a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var { p: a } = { p: [] };\n        console.log(true ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5423: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b;\n        function f({\n            [function() {\n                if (++a)\n                    return 42;\n            }()]: c\n        }) {}\n        f(b = f);\n        console.log(typeof b);\n    }\n    expect: {\n        var a, b;\n        function f({\n            [function() {\n                if (++a)\n                    return 42;\n            }()]: c\n        }) {}\n        f(b = f);\n        console.log(typeof b);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_5454: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var a = 42, a = {\n                p: [ a ] = [],\n            };\n            return \"PASS\";\n        }\n        console.log(f());\n    }\n    expect: {\n        console.log(function(a) {\n            a = 42, a = {\n                p: [ a ] = [],\n            };\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5485: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        (function f({\n            p: f,\n            [console.log(void 0 === f ? \"PASS\" : \"FAIL\")]: a,\n        }) {})(42);\n    }\n    expect: {\n        (function f({\n            p: f,\n            [console.log(void 0 === f ? \"PASS\" : \"FAIL\")]: a,\n        }) {})(42);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f([ b ]) {\n                            b;\n                            throw \"PASS\";\n                        })([]);\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f([ b ]) {\n                            b;\n                            throw \"PASS\";\n                        })([]);\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5573: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log;\n        var a = \"FAIL\";\n        (function([ { [log(a)]: b } ]) {\n            A = 42;\n        })((a = \"PASS\", [ {} ]));\n        log(a, A);\n    }\n    expect: {\n        var log = console.log;\n        var a = \"FAIL\";\n        (function([ { [log(a)]: b } ]) {\n            A = 42;\n        })((a = \"PASS\", [ {} ]));\n        log(a, A);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS 42\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5651: {\n    options = {\n        ie: true,\n        unused: true,\n    }\n    input: {\n        console.log(function arguments({}) {\n            try {} catch (arguments) {\n                var arguments;\n            }\n            return arguments[0];\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(function arguments({}) {\n            try {} catch (arguments) {\n                var arguments;\n            }\n            return arguments[0];\n        }(\"PASS\"));\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_5843_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var { p: a } = {\n            __proto__: {\n                p: \"PASS\",\n            },\n        };\n        console.log(a);\n    }\n    expect: {\n        var a = {\n            __proto__: {\n                p: \"PASS\",\n            },\n        }.p;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5843_2: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        ({ p: a } = {\n            __proto__: {\n                p: \"PASS\",\n            },\n        });\n        console.log(a);\n    }\n    expect: {\n        var a;\n        a = {\n            __proto__: {\n                p: \"PASS\",\n            },\n        }.p;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5844: {\n    options = {\n        inline: true,\n    }\n    input: {\n        try {\n            (function(a) {\n                [ a.p ] = 42;\n            })(console.log(\"PASS\"));\n        } catch (e) {}\n    }\n    expect: {\n        try {\n            (function(a) {\n                [ a.p ] = 42;\n            })(console.log(\"PASS\"));\n        } catch (e) {}\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5854_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = a;\n            a++;\n            [ b[0] ] = [ \"foo\" ];\n            return a;\n        }([]) ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function(a) {\n            var b = a;\n            a++;\n            [ b[0] ] = [ \"foo\" ];\n            return a;\n        }([]) ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5854_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = a;\n            a++;\n            ({ p: b[0] } = { p: \"foo\" });\n            return a;\n        }([]) ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function(a) {\n            var b = a;\n            a++;\n            ({ p: b[0] } = { p: \"foo\" });\n            return a;\n        }([]) ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = {};\n        var { p: { q: b } } = {\n            p: a,\n            r: a.q = \"PASS\",\n        };\n        console.log(b);\n    }\n    expect: {\n        var a = {};\n        var { q: b } = {\n            p: a,\n            r: a.q = \"PASS\",\n        }.p;\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_2: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = {}, b;\n        ({ p: { q: b } } = {\n            p: a,\n            r: a.q = \"PASS\",\n        });\n        console.log(b);\n    }\n    expect: {\n        var b, a = {};\n        ({ q: b } = {\n            p: a,\n            r: a.q = \"PASS\",\n        }.p);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_3: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = {};\n        var [ { p: b } ] = [ a, a.p = \"PASS\" ];\n        console.log(b);\n    }\n    expect: {\n        var a = {};\n        var { p: b } = [ a, a.p = \"PASS\" ][0];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_4: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = {}, b;\n        [ { p: b } ] = [ a, a.p = \"PASS\" ];\n        console.log(b);\n    }\n    expect: {\n        var b, a = {};\n        ({ p: b } = [ a, a.p = \"PASS\" ][0]);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_5: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = [];\n        var [ [ b ] ] = [ a, a[0] = \"PASS\" ];\n        console.log(b);\n    }\n    expect: {\n        var a = [];\n        var [ b ] = [ a, a[0] = \"PASS\" ][0];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_6: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = [], b;\n        [ [ b ] ] = [ a, a[0] = \"PASS\" ];\n        console.log(b);\n    }\n    expect: {\n        var b, a = [];\n        [ b ] = [ a, a[0] = \"PASS\" ][0];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_7: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = {};\n        var [ { p: b }, c ] = [ a, a.p = {} ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = {};\n        var [ { p: b }, c ] = [ a, a.p = {} ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_8: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = {}, b, c;\n        [ { p: b }, c ] = [ a, a.p = {} ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var b, c, a = {};\n        [ { p: b }, c ] = [ a, a.p = {} ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_9: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = {};\n        var [ b, { p: c } ] = [ a.p = {}, a ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = {};\n        var [ b, c ] = [ a.p = {}, a.p ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_10: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = {}, b, c;\n        [ b, { p: c } ] = [ a.p = {}, a ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var b, c, a = {};\n        [ b, c ] = [ a.p = {}, a.p ];\n        console.log(b === c ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_11: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = {};\n        var { p: { q: b } } = { p: a = { q: {} } };\n        console.log(a.q === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = {};\n        var b = { p: (a = { q: {} }).q }.p;\n        console.log(a.q === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5866_12: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = {}, b;\n        ({ p: { q: b } } = { p: a = { q: {} } });\n        console.log(a.q === b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var b, a = {};\n        b = { p: (a = { q: {} }).q }.p;\n        console.log(a.q === b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5899_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log, a, b;\n        a = \"foo\";\n        log(a && a);\n        b = { p: a } = a;\n        log(a);\n    }\n    expect: {\n        var log = console.log, a, b;\n        log((a = \"foo\") && a);\n        b = { p: a } = a;\n        log(a);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5899_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var log = console.log, a, b;\n        a = \"foo\";\n        log(a && a);\n        b = [ a ] = a;\n        log(a);\n    }\n    expect: {\n        var log = console.log, a, b;\n        log((a = \"foo\") && a);\n        b = [ a ] = a;\n        log(a);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"f\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5963_array: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = Object.create(null);\n        [ a.PASS ] = [ 42 ];\n        a.FAIL;\n        for (var p in a)\n            console.log(p);\n    }\n    expect: {\n        var a = Object.create(null);\n        [ a.PASS ] = [ 42 ];\n        for (var p in a)\n            console.log(p);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5963_object: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = Object.create(null);\n        ({ p: a.PASS } = { p: 42 });\n        a.FAIL;\n        for (var p in a)\n            console.log(p);\n    }\n    expect: {\n        var a = Object.create(null);\n        ({ p: a.PASS } = { p: 42 });\n        for (var p in a)\n            console.log(p);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n"
  },
  {
    "path": "test/compress/directives.js",
    "content": "simple_statement_is_not_a_directive: {\n    input: {\n        \"use strict\"\n            .split(\" \")\n            .forEach(function(s) {\n                console.log(s);\n            });\n        console.log(!this); // is strict mode?\n        (function() {\n            \"directive\"\n            \"\"\n            \"use strict\"\n            \"hello world\"\n                .split(\" \")\n                .forEach(function(s) {\n                    console.log(s);\n                });\n            console.log(!this); // is strict mode?\n        })();\n    }\n    expect: {\n        \"use strict\".split(\" \").forEach(function(s) {\n            console.log(s);\n        });\n        console.log(!this);\n        (function() {\n            \"directive\";\n            \"\";\n            \"use strict\";\n            \"hello world\".split(\" \").forEach(function(s) {\n                console.log(s);\n            });\n            console.log(!this);\n        })();\n    }\n    expect_stdout: [\n        \"use\",\n        \"strict\",\n        \"false\",\n        \"hello\",\n        \"world\",\n        \"true\",\n    ]\n}\n\ndrop_lone_use_strict: {\n    options = {\n        directives: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            \"use strict\";\n        }\n        function f2() {\n            \"use strict\";\n            function f3() {\n                \"use strict\";\n            }\n        }\n        (function f4() {\n            \"use strict\";\n        })();\n    }\n    expect: {\n        function f1() {\n        }\n        function f2() {\n        }\n        (function() {})();\n    }\n}\n\nissue_3166: {\n    options = {\n        directives: true,\n    }\n    input: {\n        \"foo\";\n        \"use strict\";\n        function f() {\n            \"use strict\";\n            \"bar\";\n            \"use asm\";\n        }\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            \"use asm\";\n        }\n    }\n}\n\nvalid_after_invalid_1: {\n    input: {\n        console.log(typeof function() {\n            \"use\\x20strict\";\n            \"use strict\";\n            return this;\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            \"use\\x20strict\";\n            \"use strict\";\n            return this;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nvalid_after_invalid_2: {\n    options = {\n        directives: true,\n    }\n    input: {\n        console.log(typeof function() {\n            \"use\\x20strict\";\n            \"use strict\";\n            return this;\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            \"use strict\";\n            return this;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5368_1: {\n    expression = true\n    options = {\n        directives: true,\n        expression: true,\n    }\n    input: {\n        \"foo\"\n    }\n    expect_exact: '\"foo\"'\n    expect_stdout: \"foo\"\n}\n\nissue_5368_2: {\n    expression = true\n    options = {\n        directives: true,\n        expression: true,\n    }\n    input: {\n        (function() {\n            \"foo\";\n        })()\n    }\n    expect_exact: \"function(){}()\"\n    expect_stdout: \"undefined\"\n}\n\nissue_5368_3: {\n    options = {\n        directives: true,\n        expression: true,\n    }\n    input: {\n        \"foo\";\n        (function() {\n            \"bar\";\n        })();\n    }\n    expect: {\n        (function() {})();\n    }\n}\n"
  },
  {
    "path": "test/compress/drop-console.js",
    "content": "drop_console_1: {\n    options = {}\n    input: {\n        console.log('foo');\n        console.log.apply(console, arguments);\n    }\n    expect: {\n        console.log('foo');\n        console.log.apply(console, arguments);\n    }\n}\n\ndrop_console_2: {\n    options = {\n        drop_console: true,\n    }\n    input: {\n        console.log('foo');\n        console.log.apply(console, arguments);\n    }\n    expect: {\n        // with regular compression these will be stripped out as well\n        void 0;\n        void 0;\n    }\n}\n"
  },
  {
    "path": "test/compress/drop-unused.js",
    "content": "unused_funarg_1: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a, b, c, d, e) {\n            return a + b;\n        }(14, 28));\n    }\n    expect: {\n        console.log(function(a, b) {\n            return a + b;\n        }(14, 28));\n    }\n    expect_stdout: \"42\"\n}\n\nunused_funarg_2: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a, b, c, d, e) {\n            return a + c;\n        }(14, 21, 28));\n    }\n    expect: {\n        console.log(function(a, c) {\n            return a + c;\n        }(14, 28));\n    }\n    expect_stdout: \"42\"\n}\n\nunused_nested_function: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            function g() {\n                something();\n            }\n            return x + y;\n        }\n    };\n    expect: {\n        function f(x, y) {\n            return x + y;\n        }\n    }\n}\n\nunused_circular_references_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            // circular reference\n            function g() {\n                return h();\n            }\n            function h() {\n                return g();\n            }\n            return x + y;\n        }\n    };\n    expect: {\n        function f(x, y) {\n            return x + y;\n        }\n    }\n}\n\nunused_circular_references_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var foo = 1, bar = baz, baz = foo + bar, qwe = moo();\n            return x + y;\n        }\n    };\n    expect: {\n        function f(x, y) {\n            moo();              // keeps side effect\n            return x + y;\n        }\n    }\n}\n\nunused_circular_references_3: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            var g = function() { return h() };\n            var h = function() { return g() };\n            return x + y;\n        }\n    };\n    expect: {\n        function f(x, y) {\n            return x + y;\n        }\n    }\n}\n\nunused_keep_setter_arg: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var x = {\n            _foo: null,\n            set foo(val) {\n            },\n            get foo() {\n                return this._foo;\n            }\n        }\n    }\n    expect: {\n        var x = {\n            _foo: null,\n            set foo(val) {\n            },\n            get foo() {\n                return this._foo;\n            }\n        }\n    }\n}\n\nunused_var_in_catch: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function foo() {\n            try {\n                foo();\n            } catch (ex) {\n                var x = 10;\n            }\n        }\n    }\n    expect: {\n        function foo() {\n            try {\n                foo();\n            } catch (ex) {}\n        }\n    }\n}\n\nused_var_in_catch: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function foo() {\n            try {\n                foo();\n            } catch (ex) {\n                var x = 10;\n            }\n            return x;\n        }\n    }\n    expect: {\n        function foo() {\n            try {\n                foo();\n            } catch (ex) {\n                var x = 10;\n            }\n            return x;\n        }\n    }\n}\n\nkeep_fnames: {\n    options = {\n        keep_fnames: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            return function bar(baz) {};\n        }\n    }\n    expect: {\n        function foo() {\n            return function bar(baz) {};\n        }\n    }\n}\n\ndrop_assign: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var a;\n            a = 1;\n        }\n        function f2() {\n            var a = 1;\n            a = 2;\n        }\n        function f3(a) {\n            a = 1;\n        }\n        function f4() {\n            var a;\n            return a = 1;\n        }\n        function f5() {\n            var a;\n            return function() {\n                a = 1;\n            };\n        }\n    }\n    expect: {\n        function f1() {\n            1;\n        }\n        function f2() {\n            2;\n        }\n        function f3(a) {\n            1;\n        }\n        function f4() {\n            return 1;\n        }\n        function f5() {\n            return function() {\n                1;\n            };\n        }\n    }\n}\n\nkeep_assign: {\n    options = {\n        unused: \"keep_assign\",\n    }\n    input: {\n        function f1() {\n            var a;\n            a = 1;\n        }\n        function f2() {\n            var a = 1;\n            a = 2;\n        }\n        function f3(a) {\n            a = 1;\n        }\n        function f4() {\n            var a;\n            return a = 1;\n        }\n        function f5() {\n            var a;\n            return function() {\n                a = 1;\n            };\n        }\n    }\n    expect: {\n        function f1() {\n            var a;\n            a = 1;\n        }\n        function f2() {\n            var a = 1;\n            a = 2;\n        }\n        function f3(a) {\n            a = 1;\n        }\n        function f4() {\n            var a;\n            return a = 1;\n        }\n        function f5() {\n            var a;\n            return function() {\n                a = 1;\n            };\n        }\n    }\n}\n\ndrop_toplevel_funcs: {\n    options = {\n        toplevel: \"funcs\",\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a, b = 1, c = g;\n        a = 2;\n        function g() {}\n        console.log(b = 3);\n    }\n}\n\ndrop_toplevel_vars: {\n    options = {\n        toplevel: \"vars\",\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        function f(d) {\n            return function() {\n                2;\n            };\n        }\n        2;\n        function g() {}\n        function h() {}\n        console.log(3);\n    }\n}\n\ndrop_toplevel_all: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        2;\n        console.log(3);\n    }\n}\n\ndrop_toplevel_retain: {\n    options = {\n        top_retain: \"f,a,o\",\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a;\n        function f(d) {\n            return function() {\n                2;\n            };\n        }\n        a = 2;\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n    expect_warnings: [\n        \"INFO: Retaining variable a\",\n        \"INFO: Retaining variable f\",\n        \"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]\",\n        \"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]\",\n        \"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]\",\n        \"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]\",\n    ]\n}\n\ndrop_toplevel_retain_array: {\n    options = {\n        top_retain: [\n            \"f\",\n            \"a\",\n            \"o\"\n        ],\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a;\n        function f(d) {\n            return function() {\n                2;\n            };\n        }\n        a = 2;\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n    expect_warnings: [\n        \"INFO: Retaining variable a\",\n        \"INFO: Retaining variable f\",\n        \"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]\",\n        \"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]\",\n        \"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]\",\n        \"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]\",\n    ]\n}\n\ndrop_toplevel_retain_regex: {\n    options = {\n        top_retain: /^[fao]$/,\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a;\n        function f(d) {\n            return function() {\n                2;\n            };\n        }\n        a = 2;\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n    expect_warnings: [\n        \"INFO: Retaining variable a\",\n        \"INFO: Retaining variable f\",\n        \"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]\",\n        \"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]\",\n        \"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]\",\n        \"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]\",\n    ]\n}\n\ndrop_toplevel_all_retain: {\n    options = {\n        top_retain: \"f,a,o\",\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a;\n        function f(d) {\n            return function() {\n                2;\n            };\n        }\n        a = 2;\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n    expect_warnings: [\n        \"INFO: Retaining variable a\",\n        \"INFO: Retaining variable f\",\n        \"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]\",\n        \"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]\",\n        \"INFO: Dropping unused function g [test/compress/drop-unused.js:8,17]\",\n        \"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]\",\n    ]\n}\n\ndrop_toplevel_funcs_retain: {\n    options = {\n        top_retain: \"f,a,o\",\n        toplevel: \"funcs\",\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        console.log(b = 3);\n    }\n    expect_stdout: \"3\"\n    expect_warnings: [\n        \"INFO: Retaining variable a\",\n        \"INFO: Retaining variable f\",\n        \"WARN: Dropping unused function h [test/compress/drop-unused.js:9,17]\",\n    ]\n}\n\ndrop_toplevel_vars_retain: {\n    options = {\n        top_retain: \"f,a,o\",\n        toplevel: \"vars\",\n        unused: true,\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a;\n        function f(d) {\n            return function() {\n                2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n    expect_warnings: [\n        \"INFO: Retaining variable a\",\n        \"INFO: Retaining variable f\",\n        \"INFO: Dropping unused variable b [test/compress/drop-unused.js:1,15]\",\n        \"INFO: Dropping unused variable c [test/compress/drop-unused.js:1,22]\",\n    ]\n}\n\ndrop_toplevel_keep_assign: {\n    options = {\n        toplevel: true,\n        unused: \"keep_assign\",\n    }\n    input: {\n        var a, b = 1, c = g;\n        function f(d) {\n            return function() {\n                c = 2;\n            };\n        }\n        a = 2;\n        function g() {}\n        function h() {}\n        console.log(b = 3);\n    }\n    expect: {\n        var a, b = 1;\n        a = 2;\n        console.log(b = 3);\n    }\n}\n\ndrop_fargs: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            var b = a;\n        }());\n    }\n    expect: {\n        console.log(function() {}());\n    }\n    expect_stdout: \"undefined\"\n}\n\ndrop_fnames: {\n    options = {\n        keep_fnames: false,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return function g() {\n                var a = g;\n            };\n        }\n    }\n    expect: {\n        function f() {\n            return function() {};\n        }\n    }\n}\n\nglobal_var: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function foo(b) {\n            a;\n            b;\n            c;\n            typeof c === \"undefined\";\n            c + b + a;\n            b && b.ar();\n            return b;\n        }\n    }\n    expect: {\n        var a;\n        function foo(b) {\n            c;\n            c;\n            b && b.ar();\n            return b;\n        }\n    }\n}\n\niife: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a;\n            ~function() {}(b);\n        }\n    }\n    expect: {\n        function f() {\n            b;\n        }\n    }\n}\n\ndrop_instanceof: {\n    options = {\n        booleans: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect: {\n        console.log(!1, (Math, !1));\n    }\n    expect_stdout: \"false false\"\n}\n\nkeep_instanceof_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        var f;\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect: {\n        function f() {}\n        var f;\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect_stdout: \"false false\"\n}\n\nkeep_instanceof_2: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        var f = Object;\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect: {\n        function f() {}\n        var f = Object;\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect_stdout: \"true true\"\n}\n\nkeep_instanceof_3: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        f = Object;\n        function f() {}\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect: {\n        f = Object;\n        function f() {}\n        console.log({} instanceof f, Math instanceof f);\n    }\n    expect_stdout: \"true true\"\n}\n\nissue_1539: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a, b;\n            a = b = 42;\n            return a;\n        }\n    }\n    expect: {\n        function f() {\n            return 42;\n        }\n    }\n}\n\nvardef_value: {\n    options = {\n        keep_fnames: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g(){\n                return x();\n            }\n            var a = g();\n            return a(42);\n        }\n    }\n    expect: {\n        function f() {\n            var a = function(){\n                return x();\n            }();\n            return a(42);\n        }\n    }\n}\n\nassign_binding: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a;\n            a = f.g, a();\n        }\n    }\n    expect: {\n        function f() {\n            (0, f.g)();\n        }\n    }\n}\n\nassign_chain: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a, b;\n            x = a = y = b = 42;\n        }\n    }\n    expect: {\n        function f() {\n            x = y = 42;\n        }\n    }\n}\n\nissue_1583: {\n    options = {\n        keep_fargs: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function m(t) {\n            (function(e) {\n                t = e();\n            })(function() {\n                return (function(a) {\n                    return a;\n                })(function(a) {});\n            });\n        }\n    }\n    expect: {\n        function m(t) {\n            (function(e) {\n                (function() {\n                    return (function(a) {\n                        return function(a) {};\n                    })();\n                })();\n            })();\n        }\n    }\n}\n\nissue_1656: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        for (var a=0;;);\n    }\n    expect_exact: \"for (;;);\"\n}\n\nissue_1709: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(\n            function x() {\n                var x = 1;\n                return x;\n            }(),\n            function z() {\n                function z() {}\n                return z;\n            }()\n        );\n    }\n    expect: {\n        console.log(\n            function() {\n                var x = 1;\n                return x;\n            }(),\n            function() {\n                function z() {}\n                return z;\n            }()\n        );\n    }\n    expect_stdout: true\n}\n\nissue_1715_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        function f() {\n            a++;\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        function f() {\n            a++;\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1715_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        function f() {\n            a++;\n            try {\n                x();\n            } catch (a) {\n                var a = 2;\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        function f() {\n            a++;\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1715_3: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        function f() {\n            a++;\n            try {\n                console;\n            } catch (a) {\n                var a = 2 + x();\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        function f() {\n            a++;\n            try {\n                console;\n            } catch (a) {\n                var a;\n                x();\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1715_4: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        !function a() {\n            a++;\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        !function() {\n            a++;\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\ndelete_assign_1: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(delete (a = undefined));\n        console.log(delete (a = void 0));\n        console.log(delete (a = Infinity));\n        console.log(delete (a = 1 / 0));\n        console.log(delete (a = NaN));\n        console.log(delete (a = 0 / 0));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n    ]\n}\n\ndelete_assign_2: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        keep_infinity: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(delete (a = undefined));\n        console.log(delete (a = void 0));\n        console.log(delete (a = Infinity));\n        console.log(delete (a = 1 / 0));\n        console.log(delete (a = NaN));\n        console.log(delete (a = 0 / 0));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n    ]\n}\n\ndrop_var: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(a, b);\n        var a = 1, b = 2;\n        console.log(a, b);\n        var a = 3;\n        console.log(a, b);\n    }\n    expect: {\n        console.log(a, b);\n        var a = 1, b = 2;\n        console.log(a, b);\n        a = 3;\n        console.log(a, b);\n    }\n    expect_stdout: [\n        \"undefined undefined\",\n        \"1 2\",\n        \"3 2\",\n    ]\n}\n\nissue_1830_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        !function() {\n            L: for (var b = console.log(1); !1;) continue L;\n        }();\n    }\n    expect: {\n        !function() {\n            L: for (console.log(1); !1;) continue L;\n        }();\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1830_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        !function() {\n            L: for (var a = 1, b = console.log(a); --a;) continue L;\n        }();\n    }\n    expect: {\n        !function() {\n            var a = 1;\n            L: for (console.log(a); --a;) continue L;\n        }();\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1838: {\n    options = {\n        join_vars: true,\n        loops: true,\n        unused: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        function f() {\n            var b = a;\n            while (c);\n        }\n    }\n    expect_exact: [\n        \"function f() {\",\n        \"    for (a; c; );\",\n        \"}\",\n    ]\n}\n\nvar_catch_toplevel: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            a--;\n            try {\n                a++;\n                x();\n            } catch (a) {\n                if (a) var a;\n                var a = 10;\n            }\n        }\n        f();\n    }\n    expect: {\n        !function() {\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }();\n    }\n}\n\nissue_2105_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        !function(factory) {\n            factory();\n        }(function() {\n            return function(fn) {\n                fn()().prop();\n            }(function() {\n                function bar() {\n                    var quux = function() {\n                        console.log(\"PASS\");\n                    }, foo = function() {\n                        console.log;\n                        quux();\n                    };\n                    return { prop: foo };\n                }\n                return bar;\n            });\n        });\n    }\n    expect: {\n        ({\n            prop: function() {\n                console.log;\n                console.log(\"PASS\");\n            }\n        }).prop();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2105_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 3,\n        properties: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        !function(factory) {\n            factory();\n        }(function() {\n            return function(fn) {\n                fn()().prop();\n            }(function() {\n                function bar() {\n                    var quux = function() {\n                        console.log(\"PASS\");\n                    }, foo = function() {\n                        console.log;\n                        quux();\n                    };\n                    return { prop: foo };\n                }\n                return bar;\n            });\n        });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2105_3: {\n    options = {\n        inline: true,\n        join_vars: true,\n        passes: 3,\n        reduce_vars: true,\n        side_effects: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        !function(factory) {\n            factory();\n        }(function() {\n            return function(fn) {\n                fn()().prop();\n            }(function() {\n                function bar() {\n                    var quux = function() {\n                        console.log(\"PASS\");\n                    }, foo = function() {\n                        console.log;\n                        quux();\n                    };\n                    return { prop: foo };\n                }\n                return bar;\n            });\n        });\n    }\n    expect: {\n        ({\n            prop: function() {\n                console.log,\n                console.log(\"PASS\");\n            },\n        }).prop();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2226_1: {\n    options = {\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var a = b;\n            a += c;\n        }\n        function f2(a) {\n            a <<= b;\n        }\n        function f3(a) {\n            --a;\n        }\n        function f4() {\n            var a = b;\n            return a *= c;\n        }\n        function f5(a) {\n            x(a /= b);\n        }\n    }\n    expect: {\n        function f1() {\n            b;\n            c;\n        }\n        function f2(a) {\n            b;\n        }\n        function f3(a) {\n            0;\n        }\n        function f4() {\n            var a = b;\n            return a *= c;\n        }\n        function f5(a) {\n            x(a /= b);\n        }\n    }\n}\n\nissue_2226_2: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            a += b;\n            return a;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(a, b) {\n            return a += 2;\n        }(1));\n    }\n    expect_stdout: \"3\"\n}\n\nissue_2226_3: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            a += b;\n            return a;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(a, b) {\n            return a += 2;\n        }(1));\n    }\n    expect_stdout: \"3\"\n}\n\nissue_2288: {\n    options = {\n        unused: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        function foo(o) {\n            for (var j = o.a, i = 0; i < 0; i++);\n            for (var i = 0; i < 0; i++);\n        }\n    }\n    expect: {\n        function foo(o) {\n            o.a;\n            for (var i = 0; i < 0; i++);\n            for (i = 0; i < 0; i++);\n        }\n    }\n}\n\nissue_2516_1: {\n    options = {\n        collapse_vars: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            function qux(x) {\n                bar.call(null, x);\n            }\n            function bar(x) {\n                var FOUR = 4;\n                var trouble = x || never_called();\n                var value = (FOUR - 1) * trouble;\n                console.log(value == 6 ? \"PASS\" : value);\n            }\n            Baz = qux;\n        }\n        var Baz;\n        foo();\n        Baz(2);\n    }\n    expect: {\n        function foo() {\n            Baz = function(x) {\n                (function(x) {\n                    var trouble = x || never_called();\n                    var value = (4 - 1) * trouble;\n                    console.log(6 == value ? \"PASS\" : value);\n                }).call(null, x);\n            };\n        }\n        var Baz;\n        foo();\n        Baz(2);\n    }\n}\n\nissue_2516_2: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            function qux(x) {\n                bar.call(null, x);\n            }\n            function bar(x) {\n                var FOUR = 4;\n                var trouble = x || never_called();\n                var value = (FOUR - 1) * trouble;\n                console.log(value == 6 ? \"PASS\" : value);\n            }\n            Baz = qux;\n        }\n        var Baz;\n        foo();\n        Baz(2);\n    }\n    expect: {\n        function foo() {\n            Baz = function(x) {\n                (function(x) {\n                    var value = (4 - 1) * (x || never_called());\n                    console.log(6 == value ? \"PASS\" : value);\n                }).call(null, x);\n            };\n        }\n        var Baz;\n        foo();\n        Baz(2);\n    }\n}\n\ndefun_lambda_same_name: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(n) {\n            return n ? n * f(n - 1) : 1;\n        }\n        console.log(function f(n) {\n            return n ? n * f(n - 1) : 1;\n        }(5));\n    }\n    expect: {\n        console.log(function f(n) {\n            return n ? n * f(n - 1) : 1;\n        }(5));\n    }\n    expect_stdout: \"120\"\n}\n\nissue_2660_1: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 2;\n        function f(b) {\n            return b && f() || a--;\n        }\n        f(1);\n        console.log(a);\n    }\n    expect: {\n        var a = 2;\n        (function f(b) {\n            return b && f() || a--;\n        })(1);\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2660_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        function f(b) {\n            b && f();\n            --a, a.toString();\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        (function f(b) {\n            b && f(),\n            (--a).toString();\n        })(),\n        console.log(a);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_2665: {\n    options = {\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        function g() {\n            a-- && g();\n        }\n        typeof h == \"function\" && h();\n        function h() {\n            typeof g == \"function\" && g();\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        (function g() {\n            a-- && g();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"-1\"\n}\n\ndouble_assign_1: {\n    options = {\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var a = {};\n            var a = [];\n            return a;\n        }\n        function f2() {\n            var a = {};\n            a = [];\n            return a;\n        }\n        function f3() {\n            a = {};\n            var a = [];\n            return a;\n        }\n        function f4(a) {\n            a = {};\n            a = [];\n            return a;\n        }\n        function f5(a) {\n            var a = {};\n            a = [];\n            return a;\n        }\n        function f6(a) {\n            a = {};\n            var a = [];\n            return a;\n        }\n        console.log(f1(), f2(), f3(), f4(), f5(), f6());\n    }\n    expect: {\n        function f1() {\n            return [];\n        }\n        function f2() {\n            var a;\n            a = [];\n            return a;\n        }\n        function f3() {\n            return [];\n        }\n        function f4(a) {\n            a = [];\n            return a;\n        }\n        function f5(a) {\n            a = [];\n            return a;\n        }\n        function f6(a) {\n            a = [];\n            return a;\n        }\n        console.log(f1(), f2(), f3(), f4(), f5(), f6());\n    }\n    expect_stdout: true\n}\n\ndouble_assign_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var i = 0; i < 2; i++)\n            a = void 0, a = {}, console.log(a);\n        var a;\n    }\n    expect: {\n        for (var i = 0; i < 2; i++)\n            a = {}, console.log(a);\n        var a;\n    }\n}\n\ndouble_assign_3: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var i = 0; i < 2; i++)\n            a = void 0, a = { a: a }, console.log(a);\n        var a;\n    }\n    expect: {\n        for (var i = 0; i < 2; i++)\n            a = void 0, a = { a: a }, console.log(a);\n        var a;\n    }\n}\n\ncascade_drop_assign: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = a = \"PASS\";\n        console.log(b);\n    }\n    expect: {\n        var b = \"PASS\";\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nchained_3: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            var c = a, c = b;\n            b++;\n            return c;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(a, b) {\n            var c = b;\n            +b;\n            return c;\n        }(0, 2));\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2768: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\", c = 1;\n        var c = function(b) {\n            var d = b = a;\n            var e = --b + (d && (a = \"PASS\"));\n        }();\n        console.log(a, typeof c);\n    }\n    expect: {\n        var a = \"FAIL\";\n        d = a;\n        var c = void (d && (a = \"PASS\"));\n        var d;\n        console.log(a, typeof c);\n    }\n    expect_stdout: \"PASS undefined\"\n}\n\nissue_2846: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            var a = 0;\n            b && b(a);\n            return a++;\n        }\n        var c = f();\n        console.log(c);\n    }\n    expect: {\n        var c = function(a, b) {\n            a = 0;\n            b && b(a);\n            return +a;\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_805_1: {\n    options = {\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var unused = function() {};\n            unused.prototype[a()] = 42;\n            (unused.prototype.bar = function() {\n                console.log(\"bar\");\n            })();\n            return unused;\n        })(function() {\n            console.log(\"foo\");\n            return \"foo\";\n        });\n    }\n    expect: {\n        console.log(\"foo\"),\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_805_2: {\n    options = {\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            function unused() {}\n            unused.prototype[a()] = 42;\n            (unused.prototype.bar = function() {\n                console.log(\"bar\");\n            })();\n            return unused;\n        })(function() {\n            console.log(\"foo\");\n            return \"foo\";\n        });\n    }\n    expect: {\n        console.log(\"foo\"),\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_2995: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            a.b = b = function() {};\n            b.c = \"PASS\";\n        }\n        var o = {};\n        f(o);\n        console.log(o.b.c);\n    }\n    expect: {\n        function f(a) {\n            var b;\n            a.b = b = function() {};\n            b.c = \"PASS\";\n        }\n        var o = {};\n        f(o);\n        console.log(o.b.c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3146_1: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(f) {\n            f(\"g()\");\n        })(function(a) {\n            eval(a);\n            function g(b) {\n                if (!b) b = \"PASS\";\n                console.log(b);\n            }\n        });\n    }\n    expect: {\n        (function(f) {\n            f(\"g()\");\n        })(function(a) {\n            eval(a);\n            function g(b) {\n                if (!b) b = \"PASS\";\n                console.log(b);\n            }\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3146_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(f) {\n            f(\"g()\");\n        })(function(a) {\n            eval(a);\n            function g(b) {\n                if (!b) b = \"PASS\";\n                console.log(b);\n            }\n        });\n    }\n    expect: {\n        (function(f) {\n            f(\"g()\");\n        })(function(a) {\n            eval(a);\n            function g(b) {\n                if (!b) b = \"PASS\";\n                console.log(b);\n            }\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3146_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var g = \"PASS\";\n        (function(f) {\n            var g = \"FAIL\";\n            f(\"console.log(g)\", g[g]);\n        })(function(a) {\n            eval(a);\n        });\n    }\n    expect: {\n        var g = \"PASS\";\n        (function(f) {\n            var g = \"FAIL\";\n            f(\"console.log(g)\", g[g]);\n        })(function(a) {\n            eval(a);\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3146_4: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var g = \"PASS\";\n        (function(f) {\n            var g = \"FAIL\";\n            f(\"console.log(g)\", g[g]);\n        })(function(a) {\n            eval(a);\n        });\n    }\n    expect: {\n        var g = \"PASS\";\n        (function(f) {\n            var g = \"FAIL\";\n            f(\"console.log(g)\", g[g]);\n        })(function(a) {\n            eval(a);\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3192_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n        (function(a) {\n            \"use strict\";\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n    }\n    expect: {\n        (function(a) {\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n        (function(a) {\n            \"use strict\";\n            console.log(\"foo\", arguments[0]);\n        })(\"bar\");\n    }\n    expect_stdout: [\n        \"foo foo\",\n        \"foo bar\",\n    ]\n}\n\nissue_3192_2: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            console.log(\"foo\", arguments[0]);\n        })(\"bar\");\n    }\n    expect_stdout: \"foo bar\"\n}\n\nissue_3233: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = function b() {\n            b.c = \"PASS\";\n        };\n        a();\n        console.log(a.c);\n    }\n    expect: {\n        var a = function b() {\n            b.c = \"PASS\";\n        };\n        a();\n        console.log(a.c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3375: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        var a = c = [], c = --b + (\"function\" == typeof f && f());\n        var a = c && c[a];\n        console.log(a, b);\n    }\n    expect: {\n        var b = 1;\n        var a = [], c = --b + (\"function\" == typeof f && f());\n        a = c && c[a];\n        console.log(a, b);\n    }\n    expect_stdout: \"0 0\"\n}\n\nissue_3427_1: {\n    options = {\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            a = a || {};\n        })();\n    }\n    expect: {}\n}\n\nissue_3427_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        (function() {\n            var s = \"PASS\";\n            console.log(s = s || \"FAIL\");\n        })();\n    }\n    expect: {\n        (function() {\n            var s = \"PASS\";\n            console.log(s = s || \"FAIL\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3495: {\n    options = {\n        dead_code: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {\n            f = 0;\n            var a = f.p;\n        }());\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3497: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(function(b) {\n            (b += a).p = 0;\n        }());\n    }\n    expect: {\n        var a;\n        console.log(function(b) {\n            (b += a).p = 0;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3515_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            this[c++] = 0;\n            var expr20 = !0;\n            for (var key20 in expr20);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function() {\n            for (var key20 in !(this[c++] = 0));\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3515_2: {\n    options = {\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        function f() {\n            typeof b === \"number\";\n            delete a;\n        }\n        var b = f(a = \"PASS\");\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        function f() {\n            delete a;\n        }\n        f(a = \"PASS\");\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3515_3: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f() {\n                c = \"PASS\";\n            }\n            var a = f();\n            var a = function g(b) {\n                b && (b.p = this);\n            }(a);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function() {\n            function f() {\n                c = \"PASS\";\n            }\n            (function(b) {\n                b && (b.p = this);\n            })(f());\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nfunction_assign: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = \"PASS\";\n            function g(b) {\n                return b;\n            }\n            g.p = a;\n            function h(c) {\n                return c;\n            }\n            h.p = a;\n            return h;\n        }().p);\n    }\n    expect: {\n        console.log(function() {\n            var a = \"PASS\";\n            function h(c) {\n                return c;\n            }\n            h.p = a;\n            return h;\n        }().p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3598: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                var b = void 0;\n                a = \"PASS\";\n                c.p = 0;\n                var c = b[!1];\n            })();\n        } catch (e) {}\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                a = \"PASS\";\n                (void ((void 0).p = 0))[!1];\n            })();\n        } catch (e) {}\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nself_assign: {\n    options = {\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function d(a) {\n            a = a;\n        }\n        function e(a, b) {\n            a = b;\n            b = a;\n        }\n        function f(a, b, c) {\n            a = b;\n            b = c;\n            c = a;\n        }\n        function g(a, b, c) {\n            a = a * b + c;\n        }\n    }\n    expect: {\n        function d(a) {}\n        function e(a, b) {}\n        function f(a, b, c) {}\n        function g(a, b, c) {}\n    }\n}\n\nfunction_argument_reference: {\n    options = {\n        keep_fargs: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 1, b = 42;\n        function f(a) {\n            b <<= a;\n        }\n        f();\n        console.log(a, b);\n    }\n    expect: {\n        var a = 1, b = 42;\n        function f(a) {\n            b <<= a;\n        }\n        f();\n        console.log(a, b);\n    }\n    expect_stdout: \"1 42\"\n}\n\nfunction_parameter_ie8: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            function f() {\n                console.log(\"PASS\");\n            }\n            f(a = 1 + a);\n        })();\n    }\n    expect: {\n        (function() {\n            (function() {\n                console.log(\"PASS\");\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3664: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a, b = (a = (a = [ b && console.log(\"FAIL\") ]).p = 0, 0);\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            a = (a = [ b && console.log(\"FAIL\") ]).p = 0;\n            var a, b = 0;\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3673: {\n    options = {\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (a = [ a ]).p = 42;\n        console.log(\"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3746: {\n    options = {\n        keep_fargs: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        try {\n            A;\n        } catch (e) {\n            var e;\n        }\n        (function f(a) {\n            e = a;\n        })();\n        console.log(\"PASS\");\n    }\n    expect: {\n        try {\n            A;\n        } catch (e) {\n            var e;\n        }\n        (function(a) {\n            e = a;\n        })();\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_duplicated_side_effects: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        for (var i = 1; i--;)\n            var a = 0, b = ++a;\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        for (var i = 1; i--;)\n            a = 0, ++a;\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\ndrop_duplicated_var_catch: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f() {\n            try {\n                x();\n            } catch (a) {\n                var a, a;\n            }\n        }\n    }\n    expect: {\n        function f() {\n            try {\n                x();\n            } catch (a) {\n                var a;\n            }\n        }\n    }\n}\n\nissue_3802_1: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        a += 0;\n        var a = function() {};\n        console.log(typeof a);\n    }\n    expect: {\n        var a = 0;\n        a += 0;\n        a = function() {};\n        console.log(typeof a);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3802_2: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        a += 0;\n        var a = function() {};\n        console.log(typeof a);\n    }\n    expect: {\n        0;\n        var a = function() {};\n        console.log(typeof a);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3899: {\n    options = {\n        assignments: true,\n        evaluate: true,\n        functions: true,\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        a = a + 1;\n        var a = function f(b) {\n            return function() {\n                return b;\n            };\n        }(2);\n        console.log(typeof a);\n    }\n    expect: {\n        console.log(typeof function() {\n            return 2;\n        });\n    }\n    expect_stdout: \"function\"\n}\n\ncross_scope_assign_chain: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = 0;\n        (function() {\n            a = b;\n            a++;\n            while (b++);\n        })();\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a, b = 0;\n        (function() {\n            a = b;\n            a++;\n            while (b++);\n        })();\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nassign_if_assign_read: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var b;\n            do {\n                b = \"FAIL\";\n                if (Array.isArray(a)) {\n                    b = a[0];\n                    console.log(b);\n                }\n            } while (!console);\n        })([ \"PASS\" ]);\n    }\n    expect: {\n        (function(a) {\n            var b;\n            do {\n                \"FAIL\";\n                if (Array.isArray(a)) {\n                    b = a[0];\n                    console.log(b);\n                }\n            } while (!console);\n        })([ \"PASS\" ]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3951: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = console.log(\"PASS\");\n        console.log(a);\n        a = \"0\";\n        console.log(a.p = 0);\n        a && a;\n    }\n    expect: {\n        var a = console.log(\"PASS\");\n        console.log(a);\n        a = \"0\";\n        console.log(a.p = 0);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n        \"0\",\n    ]\n}\n\nissue_3956: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            function f(b) {\n                console.log(b);\n                a = 1;\n            }\n            var c = f(c += 0);\n            (function(d) {\n                console.log(d);\n            })(console.log(a) ^ 1, c);\n        })();\n    }\n    expect: {\n        var d;\n        console.log(NaN),\n        d = 1 ^ console.log(1),\n        console.log(d);\n    }\n    expect_stdout: [\n        \"NaN\",\n        \"1\",\n        \"1\",\n    ]\n}\n\nissue_3962_1: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        function f(b, c) {\n            do {\n                var d = console + e, e = 0..toString() === b;\n            } while (0);\n            if (c) console.log(\"PASS\");\n        }\n        var a = f(a--, 1);\n        a;\n    }\n    expect: {\n        var a = 0;\n        (function(c) {\n            do {\n                console;\n                0..toString();\n            } while (0);\n            if (c) console.log(\"PASS\");\n        })(1);\n        void 0;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3962_2: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        function f(b, c) {\n            do {\n                var d = console + e, e = 0..toString() === b;\n            } while (0);\n            if (c) console.log(\"PASS\");\n        }\n        var a = f(a--, 1);\n        a;\n    }\n    expect: {\n        var a = 0;\n        (function(c) {\n            do {\n                console;\n                0..toString();\n            } while (0);\n            if (c) console.log(\"PASS\");\n        })(1);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3986: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        (function() {\n            try {\n                throw 42;\n            } catch (e) {\n                a++;\n            }\n            b = b && 0;\n        })(b *= a);\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b = 0;\n        (function() {\n            try {\n                throw 42;\n            } catch (e) {\n                a++;\n            }\n            b = b && 0;\n        })(b *= a);\n        console.log(b);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4017_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        console.log(function f() {\n            var b = c &= 0;\n            var c = a++ + (A = a);\n            var d = c && c[f];\n        }());\n    }\n    expect: {\n        var a = 0;\n        console.log(function() {\n            c &= 0;\n            var c = a++ + (A = a);\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4017_2: {\n    options = {\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        console.log(function f() {\n            var b = c &= 0;\n            var c = a++ + (A = a);\n            var d = c && c[f];\n        }());\n    }\n    expect: {\n        var a = 0;\n        console.log(function() {\n            0;\n            a++,\n            A = a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4025: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 0, c = 0, d = a++;\n        try {\n            var e = console.log(c), f = b;\n        } finally {\n            var d = b = 1, d = c + 1;\n            c = 0;\n        }\n        console.log(a, b, d);\n    }\n    expect: {\n        try {\n            console.log(0);\n        } finally {\n            0;\n        }\n        console.log(1, 1, 1);\n    }\n    expect_stdout: [\n        \"0\",\n        \"1 1 1\",\n    ]\n}\n\nforin_var_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var k;\n        for (k in [ 1, 2 ])\n            console.log(k);\n        for (k in { PASS: 3 })\n            console.log(k);\n        console.log(k);\n    }\n    expect: {\n        for (var k in [ 1, 2 ])\n            console.log(k);\n        for (k in { PASS: 3 })\n            console.log(k);\n        console.log(k);\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nforin_var_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            switch (0) {\n              case function() {\n                    for (a in 0);\n                }:\n                var b = 0;\n            }\n            for (var c = 0; a;);\n            var a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            switch (0) {\n              case function() {\n                    for (a in 0);\n                }:\n            }\n            for (; a;);\n            var a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4133: {\n    options = {\n        evaluate: true,\n        merge_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        var b = [ a-- ], c = b && b[c];\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        console.log(0);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4144: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            var b = console, c = ++b;\n        })(console.log(\"PASS\"), 0);\n    }\n    expect: {\n        (function(b) {\n            b = console,\n            ++b;\n        })(console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4146: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            function g() {}\n            var a = g;\n            var c = b;\n            c.p;\n            console.log(typeof a);\n        }\n        f(\"FAIL\", 42);\n    }\n    expect: {\n        (function(a, b) {\n            a = function () {};\n            var c = b;\n            c.p;\n            console.log(typeof a);\n        })(0, 42);\n    }\n    expect_stdout: \"function\"\n}\n\nvar_catch_redefined: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw \"PASS\";\n        } catch (a) {\n            function f() {\n                return a;\n            }\n            console.log(a);\n        }\n        f();\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            throw \"PASS\";\n        } catch (a) {\n            function f() {\n                return a;\n            }\n            console.log(a);\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nsingle_use_catch_redefined: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n        }\n        console.log(g());\n    }\n    expect: {\n        var a = 1;\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n        }\n        console.log(g());\n    }\n    expect_stdout: true\n}\n\nissue_4184: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = function() {}, b = [ a, 1 && b, a = {} ];\n            try {\n                throw 42;\n            } catch (a) {\n                {\n                    console.log(a);\n                }\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            var b = [ function() {}, 1 && b, {} ];\n            try {\n                throw 42;\n            } catch (a) {\n                console.log(a);\n            }\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nissue_4235_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        (function() {\n            {\n                const f = 0;\n            }\n            (function f() {\n                var f = console.log(f);\n            })();\n        })();\n    }\n    expect: {\n        void function() {\n            var f = console.log(f);\n        }();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4235_2: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        (function() {\n            {\n                const f = 0;\n            }\n            (function f() {\n                var f = console.log(f);\n            })();\n        })();\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4404: {\n    options = {\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            arguments[0] = \"PASS\";\n            console.log(a);\n        }\n        f(\"FAIL\");\n    }\n    expect: {\n        function f(a) {\n            arguments[0] = \"PASS\";\n            console.log(a);\n        }\n        f(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4413: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(arguments) {\n            var arguments = function() {};\n            return arguments.length;\n        }());\n    }\n    expect: {\n        console.log(function(arguments) {\n            return function() {}.length;\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4464_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var a = function() {};\n            return [ arguments, a ];\n        }\n        console.log(typeof f()[1]);\n    }\n    expect: {\n        function f(a) {\n            a = function() {};\n            return [ arguments, a ];\n        }\n        console.log(typeof f()[1]);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4464_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var a = function() {};\n            return [ arguments, a ];\n        }\n        console.log(typeof f(42)[0][0]);\n    }\n    expect: {\n        function f(a) {\n            a = function() {};\n            return [ arguments, a ];\n        }\n        console.log(typeof f(42)[0][0]);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4464_3: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function a(a) {\n            var a = function() {};\n            return [ arguments[0], a ];\n        })(42).forEach(function(b) {\n            console.log(typeof b);\n        });\n    }\n    expect: {\n        (function(a) {\n            a = function() {};\n            return [ arguments[0], a ];\n        })(42).forEach(function(b) {\n            console.log(typeof b);\n        });\n    }\n    expect_stdout: [\n        \"function\",\n        \"function\",\n    ]\n}\n\nissue_4558_1: {\n    options = {\n        evaluate: true,\n        pure_getters: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        var b = 1, b = c >>>= a;\n        var c = 0;\n        b && 0[a++],\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        var b = c >>>= a;\n        var c = 0;\n        b && a++,\n        console.log(a);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4558_2: {\n    options = {\n        evaluate: true,\n        ie: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = 1;\n            var b = (a = NaN) || (console.log(\"PASS\"), 2);\n            return a;\n        })();\n    }\n    expect: {\n        (function() {\n            var a;\n            (a = NaN) || console.log(\"PASS\");\n            return a;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4662: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        function f(b, c) {\n            console.log(b, c);\n        }\n        f(++a, a = a, a);\n    }\n    expect: {\n        var a = 0;\n        (function(b, c) {\n            console.log(b, c);\n        })(++a, a = 1);\n    }\n    expect_stdout: \"1 1\"\n}\n\nissue_4806_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        O = {\n            f: function() {\n                console.log(this === O ? \"FAIL\" : \"PASS\");\n            },\n        };\n        var a;\n        (a = 42, O.f)();\n        a;\n    }\n    expect: {\n        O = {\n            f: function() {\n                console.log(this === O ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (0, O.f)();\n        42;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4806_2: {\n    options = {\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        O = {\n            f: function() {\n                console.log(this === O ? \"FAIL\" : \"PASS\");\n            },\n        };\n        var a;\n        (a = 42, O.f)();\n        a;\n    }\n    expect: {\n        O = {\n            f: function() {\n                console.log(this === O ? \"FAIL\" : \"PASS\");\n            },\n        },\n        (0, O.f)();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4806_3: {\n    options = {\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        O = {\n            f: function() {\n                console.log(this === O ? \"FAIL\" : \"PASS\");\n            },\n        };\n        var a;\n        (a = 42, O.f)();\n        a;\n    }\n    expect: {\n        O = {\n            f: function() {\n                console.log(this === O ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (0, O.f)();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4834: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            new function(a, b) {\n                b;\n                b.p;\n            }(42);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            b.p;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        var b;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4912_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = A = function() {};\n        A;\n        a.prototype = {\n            f: function() {\n                console.log(\"PASS\");\n            },\n        };\n        new A().f();\n    }\n    expect: {\n        var a = A = function() {};\n        A;\n        a.prototype = {\n            f: function() {\n                console.log(\"PASS\");\n            },\n        };\n        new A().f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4912_2: {\n    options = {\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var g, f = function() {};\n            f.p = {};\n            (g = f.p.q = function() {}).r = \"PASS\";\n            return f;\n        }().p.q.r);\n    }\n    expect: {\n        console.log(function() {\n            var g, f = function() {};\n            f.p = {};\n            (f.p.q = function() {}).r = \"PASS\";\n            return f;\n        }().p.q.r);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4912_3: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(f, g) {\n            f = function() {};\n            f.p = {};\n            g = f.p.q = function() {};\n            g.r = \"PASS\";\n            return f;\n        }().p.q.r);\n    }\n    expect: {\n        console.log(function(f, g) {\n            f = function() {};\n            f.p = {};\n            g = f.p.q = function() {};\n            g.r = \"PASS\";\n            return f;\n        }().p.q.r);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5079: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        do {\n            (a = 123456).p = a;\n            a.q = null;\n        } while (console.log(\"PASS\"));\n    }\n    expect: {\n        do {\n            0, 0, null;\n        } while (console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5224: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            try {\n                var b = function() {\n                    var a = \"FAIL 1\";\n                    null && a;\n                    a = console.log(a);\n                }(new function(c, d) {\n                    console.log(d);\n                    a;\n                }(\"FAIL 2\", Infinity));\n            } finally {\n                return f;\n            }\n        }\n        f();\n    }\n    expect: {\n        (function f() {\n            try {\n                (function() {\n                    var a = \"FAIL 1\";\n                    null;\n                    console.log(a);\n                })(function() {\n                    console.log(1 / 0);\n                    a;\n                }());\n            } finally {\n                return f;\n            }\n        })();\n    }\n    expect_stdout: \"Infinity\"\n}\n\nissue_5271: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            do {\n                var a = b = 0 ^ f, b = b;\n            } while (console.log(42 - b));\n        }\n        f();\n    }\n    expect: {\n        (function f() {\n            do {\n                var b;\n                b = 0 ^ f;\n            } while (console.log(42 - b));\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5533_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5533_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(b) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5908_1: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = function(b) {\n            function f() {}\n            b = f.prototype;\n            b.p = 42;\n            b.q = \"PASS\";\n            return f;\n        }();\n        console.log(a.prototype.q);\n    }\n    expect: {\n        var a = function(b) {\n            function f() {}\n            (b = f.prototype).p = 42;\n            b.q = \"PASS\";\n            return f;\n        }();\n        console.log(a.prototype.q);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5908_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = function(b) {\n            function f() {}\n            (b = f.prototype).p = 42;\n            b.q = \"PASS\";\n            return f;\n        }();\n        console.log(a.prototype.q);\n    }\n    expect: {\n        var a = function(b) {\n            function f() {}\n            (b = f.prototype).p = 42;\n            b.q = \"PASS\";\n            return f;\n        }();\n        console.log(a.prototype.q);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5918: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b) {\n            b.p = 42;\n        })(a = function() {\n            arguments;\n        });\n        for (var i in a)\n            console.log(\"PASS\");\n    }\n    expect: {\n        var a;\n        (function(b) {\n            b.p = 42;\n        })(a = function() {\n            arguments;\n        });\n        for (var i in a)\n            console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/evaluate.js",
    "content": "and: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        // compress these\n\n        a = true     && condition;\n        a = 1        && console.log(\"a\");\n        a = 2 * 3    && 2 * condition;\n        a = 5 == 5   && condition + 3;\n        a = \"string\" && 4 - condition;\n        a = 5 + \"\"   && condition / 5;\n        a = -4.5     && 6 << condition;\n        a = 6        && 7;\n\n        a = false     && condition;\n        a = NaN       && console.log(\"b\");\n        a = 0         && console.log(\"c\");\n        a = undefined && 2 * condition;\n        a = null      && condition + 3;\n        a = 2 * 3 - 6 && 4 - condition;\n        a = 10 == 7   && condition / 5;\n        a = !\"string\" && 6 % condition;\n        a = 0         && 7;\n\n        // don't compress these\n\n        a = condition        && true;\n        a = console.log(\"a\") && 2;\n        a = 4 - condition    && \"string\";\n        a = 6 << condition   && -4.5;\n\n        a = condition        && false;\n        a = console.log(\"b\") && NaN;\n        a = console.log(\"c\") && 0;\n        a = 2 * condition    && undefined;\n        a = condition + 3    && null;\n\n    }\n    expect: {\n        var a;\n\n        a = condition;\n        a = console.log(\"a\");\n        a = 2 * condition;\n        a = condition + 3;\n        a = 4 - condition;\n        a = condition / 5;\n        a = 6 << condition;\n        a = 7;\n\n        a = false;\n        a = NaN;\n        a = 0;\n        a = void 0;\n        a = null;\n        a = 0;\n        a = false;\n        a = false;\n        a = 0;\n\n        a = condition        && true;\n        a = console.log(\"a\") && 2;\n        a = 4 - condition    && \"string\";\n        a = 6 << condition   && -4.5;\n\n        a = condition        && false;\n        a = console.log(\"b\") && NaN;\n        a = console.log(\"c\") && 0;\n        a = 2 * condition    && void 0;\n        a = condition + 3    && null;\n    }\n}\n\nor: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        // compress these\n\n        a = true     || condition;\n        a = 1        || console.log(\"a\");\n        a = 2 * 3    || 2 * condition;\n        a = 5 == 5   || condition + 3;\n        a = \"string\" || 4 - condition;\n        a = 5 + \"\"   || condition / 5;\n        a = -4.5     || 6 << condition;\n        a = 6        || 7;\n\n        a = false     || condition;\n        a = 0         || console.log(\"b\");\n        a = NaN       || console.log(\"c\");\n        a = undefined || 2 * condition;\n        a = null      || condition + 3;\n        a = 2 * 3 - 6 || 4 - condition;\n        a = 10 == 7   || condition / 5;\n        a = !\"string\" || 6 % condition;\n        a = null      || 7;\n\n        a = console.log(undefined && condition || null);\n        a = console.log(undefined || condition && null);\n\n        // don't compress these\n\n        a = condition        || true;\n        a = console.log(\"a\") || 2;\n        a = 4 - condition    || \"string\";\n        a = 6 << condition   || -4.5;\n\n        a = condition        || false;\n        a = console.log(\"b\") || NaN;\n        a = console.log(\"c\") || 0;\n        a = 2 * condition    || undefined;\n        a = condition + 3    || null;\n\n    }\n    expect: {\n        var a;\n\n        a = true;\n        a = 1;\n        a = 6;\n        a = true;\n        a = \"string\";\n        a = \"5\";\n        a = -4.5;\n        a = 6;\n\n        a = condition;\n        a = console.log(\"b\");\n        a = console.log(\"c\");\n        a = 2 * condition;\n        a = condition + 3;\n        a = 4 - condition;\n        a = condition / 5;\n        a = 6 % condition;\n        a = 7;\n\n        a = console.log(null);\n        a = console.log(condition && null);\n\n        a = condition        || true;\n        a = console.log(\"a\") || 2;\n        a = 4 - condition    || \"string\";\n        a = 6 << condition   || -4.5;\n\n        a = condition        || false;\n        a = console.log(\"b\") || NaN;\n        a = console.log(\"c\") || 0;\n        a = 2 * condition    || void 0;\n        a = condition + 3    || null;\n    }\n}\n\nunary_prefix: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        a = !0 && b;\n        a = !0 || b;\n        a = ~1 && b;\n        a = ~1 || b;\n        a = -2 && b;\n        a = -2 || b;\n        a = +3 && b;\n        a = +3 || b;\n    }\n    expect: {\n        a = b;\n        a = !0;\n        a = b;\n        a = -2;\n        a = b;\n        a = -2;\n        a = b;\n        a = 3;\n    }\n}\n\nnegative_zero: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\n            -\"\",\n            - -\"\",\n            1 / (-0),\n            1 / (-\"\")\n        );\n    }\n    expect: {\n        console.log(\n            -0,\n            0,\n            -1/0,\n            -1/0\n        );\n    }\n    expect_stdout: true\n}\n\npositive_zero: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\n            +\"\",\n            + -\"\",\n            1 / (+0),\n            1 / (+\"\")\n        );\n    }\n    expect: {\n        console.log(\n            0,\n            -0,\n            1/0,\n            1/0\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_constant: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(true.a, false.a);\n        console.log(true.valueOf(), false.valueOf());\n        try {\n            console.log(null.a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        try {\n            console.log(undefined.a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        console.log(void 0, void 0);\n        console.log(true, false);\n        try {\n            console.log(null.a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        try {\n            console.log((void 0).a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: [\n        \"undefined undefined\",\n        \"true false\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nunsafe_object: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o = { a: 1 };\n        console.log(\n            o + 1,\n            o.a + 1,\n            o.b + 1,\n            o.a.b + 1\n        );\n    }\n    expect: {\n        var o = { a: 1 };\n        console.log(\n            o + 1,\n            2,\n            o.b + 1,\n            NaN\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_object_nested: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o = { a: { b: 1 } };\n        console.log(\n            o + 1,\n            o.a + 1,\n            o.b + 1,\n            o.a.b + 1\n        );\n    }\n    expect: {\n        var o = { a: { b: 1 } };\n        console.log(\n            o + 1,\n            o.a + 1,\n            o.b + 1,\n            2\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_object_complex: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o = { a: { b: 1 }, b: 1 };\n        console.log(\n            o + 1,\n            o.a + 1,\n            o.b + 1,\n            o.a.b + 1\n        );\n    }\n    expect: {\n        var o = { a: { b: 1 }, b: 1 };\n        console.log(\n            o + 1,\n            o.a + 1,\n            2,\n            2\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_object_repeated: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o = { a: { b: 1 }, a: 1 };\n        console.log(\n            o + 1,\n            o.a + 1,\n            o.b + 1,\n            o.a.b + 1\n        );\n    }\n    expect: {\n        var o = { a: { b: 1 }, a: 1 };\n        console.log(\n            o + 1,\n            2,\n            o.b + 1,\n            NaN\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_object_accessor: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f() {\n            var a = {\n                get b() {},\n                set b(v) {},\n            };\n            return { a: a };\n        }\n    }\n    expect: {\n        function f() {\n            var a = {\n                get b() {},\n                set b(v) {},\n            };\n            return { a: a };\n        }\n    }\n}\n\nprop_function: {\n    options = {\n        evaluate: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\n            ({a:{b:1},b:function(){}}) + 1,\n            ({a:{b:1},b:function(){}}).a + 1,\n            ({a:{b:1},b:function(){}}).b + 1,\n            ({a:{b:1},b:function(){}}).a.b + 1\n        );\n    }\n    expect: {\n        console.log(\n            ({a:{b:1},b:function(){}}) + 1,\n            ({b:1}) + 1,\n            function(){} + 1,\n            2\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_integer_key: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            ({0:1}) + 1,\n            ({0:1})[0] + 1,\n            ({0:1})[\"0\"] + 1,\n            ({0:1})[1] + 1,\n            ({0:1})[0][1] + 1,\n            ({0:1})[0][\"1\"] + 1\n        );\n    }\n    expect: {\n        console.log(\n            ({0:1}) + 1,\n            2,\n            2,\n            ({0:1})[1] + 1,\n            NaN,\n            NaN\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_integer_key_complex: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            ({0:{1:1},1:1}) + 1,\n            ({0:{1:1},1:1})[0] + 1,\n            ({0:{1:1},1:1})[\"0\"] + 1,\n            ({0:{1:1},1:1})[1] + 1,\n            ({0:{1:1},1:1})[0][1] + 1,\n            ({0:{1:1},1:1})[0][\"1\"] + 1\n        );\n    }\n    expect: {\n        console.log(\n            ({0:{1:1},1:1}) + 1,\n            \"[object Object]1\",\n            \"[object Object]1\",\n            2,\n            2,\n            2\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_float_key: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            ({2.72:1}) + 1,\n            ({2.72:1})[2.72] + 1,\n            ({2.72:1})[\"2.72\"] + 1,\n            ({2.72:1})[3.14] + 1,\n            ({2.72:1})[2.72][3.14] + 1,\n            ({2.72:1})[2.72][\"3.14\"] + 1\n        );\n    }\n    expect: {\n        console.log(\n            ({2.72:1}) + 1,\n            2,\n            2,\n            ({2.72:1})[3.14] + 1,\n            NaN,\n            NaN\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_float_key_complex: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            ({2.72:{3.14:1},3.14:1}) + 1,\n            ({2.72:{3.14:1},3.14:1})[2.72] + 1,\n            ({2.72:{3.14:1},3.14:1})[\"2.72\"] + 1,\n            ({2.72:{3.14:1},3.14:1})[3.14] + 1,\n            ({2.72:{3.14:1},3.14:1})[2.72][3.14] + 1,\n            ({2.72:{3.14:1},3.14:1})[2.72][\"3.14\"] + 1\n        );\n    }\n    expect: {\n        console.log(\n            \"[object Object]1\",\n            \"[object Object]1\",\n            \"[object Object]1\",\n            2,\n            2,\n            2\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_array: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        var a = \"PASS\";\n        Array.prototype[1] = a;\n        console.log([, ].length);\n        console.log(\"\" + [, , ]);\n        console.log([1, , 3][1]);\n        console.log([1, 2, 3, a] + 1);\n        console.log([1, 2, 3, 4] + 1);\n        console.log([1, 2, 3, a][0] + 1);\n        console.log([1, 2, 3, 4][0] + 1);\n        console.log([1, 2, 3, 4][6 - 5] + 1);\n        console.log([1, , 3, 4][6 - 5] + 1);\n        console.log([[1, 2], [3, 4]][0] + 1);\n        console.log([[1, 2], [3, 4]][6 - 5][1] + 1);\n        console.log([[1, 2], , [3, 4]][6 - 5][1] + 1);\n    }\n    expect: {\n        var a = \"PASS\";\n        Array.prototype[1] = a;\n        console.log([, ].length);\n        console.log(\"\" + [, , ]);\n        console.log([1, , 3][1]);\n        console.log([1, 2, 3, a] + 1);\n        console.log(\"1,2,3,41\");\n        console.log([1, 2, 3, a][0] + 1);\n        console.log(2);\n        console.log(3);\n        console.log([1, , 3, 4][1] + 1);\n        console.log(\"1,21\");\n        console.log(5);\n        console.log([[1, 2], , [3, 4]][1][1] + 1);\n    }\n    expect_stdout: [\n        \"1\",\n        \",PASS\",\n        \"PASS\",\n        \"1,2,3,PASS1\",\n        \"1,2,3,41\",\n        \"2\",\n        \"2\",\n        \"3\",\n        \"PASS1\",\n        \"1,21\",\n        \"5\",\n        \"A1\",\n    ]\n}\n\nunsafe_string: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            \"1234\" + 1,\n            \"1234\"[0] + 1,\n            \"1234\"[6 - 5] + 1,\n            (\"12\" + \"34\")[0] + 1,\n            (\"12\" + \"34\")[6 - 5] + 1,\n            [1, 2, 3, 4].join(\"\")[0] + 1\n        );\n    }\n    expect: {\n        console.log(\n            \"12341\",\n            \"11\",\n            \"21\",\n            \"11\",\n            \"21\",\n            \"11\"\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_array_bad_index: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            [1, 2, 3, 4].a + 1,\n            [1, 2, 3, 4][\"a\"] + 1,\n            [1, 2, 3, 4][3.14] + 1\n        );\n    }\n    expect: {\n        console.log(\n            [1, 2, 3, 4].a + 1,\n            [1, 2, 3, 4][\"a\"] + 1,\n            [1, 2, 3, 4][3.14] + 1\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_string_bad_index: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            \"1234\".a + 1,\n            \"1234\"[\"a\"] + 1,\n            \"1234\"[3.14] + 1\n        );\n    }\n    expect: {\n        console.log(\n            NaN,\n            NaN,\n            NaN\n        );\n    }\n    expect_stdout: \"NaN NaN NaN\"\n}\n\nprototype_function: {\n    options = {\n        evaluate: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        function v() {\n            return this.valueOf === v ? \"PASS\" : \"FAIL\";\n        }\n        console.log(({ valueOf: v }) < 1);\n        console.log(({ valueOf: v }) + \"\");\n        console.log((( {valueOf: v }) + \"\")[2]);\n        console.log(({ valueOf: v }).valueOf());\n        function t() {\n            return this.toString === t ? \"PASS\" : \"FAIL\";\n        }\n        console.log(({ toString: t }) < 1);\n        console.log(({ toString: t }) + \"\");\n        console.log((( {toString: t }) + \"\")[2]);\n        console.log(({ toString: t }).toString());\n    }\n    expect: {\n        function v() {\n            return this.valueOf === v ? \"PASS\" : \"FAIL\";\n        }\n        console.log(({ valueOf: v }) < 1);\n        console.log(({ valueOf: v }) + \"\");\n        console.log((( {valueOf: v }) + \"\")[2]);\n        console.log(({ valueOf: v }).valueOf());\n        function t() {\n            return this.toString === t ? \"PASS\" : \"FAIL\";\n        }\n        console.log(({ toString: t }) < 1);\n        console.log(({ toString: t }) + \"\");\n        console.log((( {toString: t }) + \"\")[2]);\n        console.log(({ toString: t }).toString());\n    }\n    expect_stdout: [\n        \"false\",\n        \"PASS\",\n        \"S\",\n        \"PASS\",\n        \"false\",\n        \"PASS\",\n        \"S\",\n        \"PASS\",\n    ]\n}\n\ncall_args: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        console.log(a);\n        +function(a) {\n            return a;\n        }(a);\n    }\n    expect: {\n        var a = 1;\n        console.log(1);\n        1, 1;\n    }\n    expect_stdout: true\n}\n\ncall_args_drop_param: {\n    options = {\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        console.log(a);\n        +function(a) {\n            return a;\n        }(a, b);\n    }\n    expect: {\n        console.log(1);\n        b, 1;\n    }\n    expect_stdout: true\n}\n\nin_boolean_context: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(\n            !42,\n            !\"foo\",\n            ![1, 2],\n            !/foo/,\n            !b(42),\n            !b(\"foo\"),\n            !b([1, 2]),\n            !b(/foo/),\n            ![1, foo()],\n            ![1, foo(), 2]\n        );\n    }\n    expect: {\n        console.log(\n            !1,\n            !1,\n            !1,\n            !1,\n            !b(42),\n            !b(\"foo\"),\n            !b([1, 2]),\n            !b(/foo/),\n            (foo(), !1),\n            (foo(), !1)\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_charAt: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            \"1234\" + 1,\n            \"1234\".charAt(0) + 1,\n            \"1234\".charAt(6 - 5) + 1,\n            (\"12\" + \"34\").charAt(0) + 1,\n            (\"12\" + \"34\").charAt(6 - 5) + 1,\n            [1, 2, 3, 4].join(\"\").charAt(0) + 1\n        );\n    }\n    expect: {\n        console.log(\n            \"12341\",\n            \"11\",\n            \"21\",\n            \"11\",\n            \"21\",\n            \"11\"\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_charAt_bad_index: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\n            \"1234\".charAt() + 1,\n            \"1234\".charAt(\"a\") + 1,\n            \"1234\".charAt(3.14) + 1\n        );\n    }\n    expect: {\n        console.log(\n            \"11\",\n            \"11\",\n            \"41\"\n        );\n    }\n    expect_stdout: true\n}\n\nunsafe_charAt_noop: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        s = \"foo\";\n        x = 42;\n        console.log(\n            s.charAt(0),\n            \"string\".charAt(x),\n            (typeof x).charAt()\n        );\n    }\n    expect: {\n        s = \"foo\";\n        x = 42;\n        console.log(\n            s[0] || \"\",\n            \"string\"[0 | x] || \"\",\n            (typeof x)[0] || \"\"\n        );\n    }\n    expect_stdout: \"f  n\"\n}\n\nchained_side_effects: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\"foo\") || (console.log(\"bar\"), \"baz\") || console.log(\"moo\");\n    }\n    expect: {\n        console.log(\"foo\") || (console.log(\"bar\"), \"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    expect_warnings: [\n        \"WARN: Condition left of || always true [test/compress/evaluate.js:1,8]\",\n    ]\n}\n\ninstanceof_lambda: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(42 instanceof function() {});\n    }\n    expect: {\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n}\n\nissue_1649: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(-1 + -1);\n    }\n    expect: {\n        console.log(-2);\n    }\n    expect_stdout: \"-2\";\n}\n\nissue_1760_1: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        !function(a) {\n            try {\n                throw 0;\n            } catch (NaN) {\n                a = +\"foo\";\n            }\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function(a) {\n            try {\n                throw 0;\n            } catch (NaN) {\n                a = 0 / 0;\n            }\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_1760_2: {\n    options = {\n        evaluate: true,\n        keep_infinity: true,\n    }\n    input: {\n        !function(a) {\n            try {\n                throw 0;\n            } catch (Infinity) {\n                a = 123456789 / 0;\n            }\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function(a) {\n            try {\n                throw 0;\n            } catch (Infinity) {\n                a = 1 / 0;\n            }\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"Infinity\"\n}\n\ndelete_expr_1: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        console.log(delete undefined);\n        console.log(delete void 0);\n        console.log(delete Infinity);\n        console.log(delete (1 / 0));\n        console.log(delete NaN);\n        console.log(delete (0 / 0));\n    }\n    expect: {\n        console.log(delete undefined);\n        console.log((void 0, !0));\n        console.log(delete Infinity);\n        console.log((1 / 0, !0));\n        console.log(delete NaN);\n        console.log((0 / 0, !0));\n    }\n    expect_stdout: true\n}\n\ndelete_expr_2: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        keep_infinity: true,\n    }\n    input: {\n        console.log(delete undefined);\n        console.log(delete void 0);\n        console.log(delete Infinity);\n        console.log(delete (1 / 0));\n        console.log(delete NaN);\n        console.log(delete (0 / 0));\n    }\n    expect: {\n        console.log(delete undefined);\n        console.log((void 0, !0));\n        console.log(delete Infinity);\n        console.log((1 / 0, !0));\n        console.log(delete NaN);\n        console.log((0 / 0, !0));\n    }\n    expect_stdout: true\n}\n\ndelete_binary_1: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (true && undefined));\n        console.log(delete (true && void 0));\n        console.log(delete (true && Infinity));\n        console.log(delete (true && (1 / 0)));\n        console.log(delete (true && NaN));\n        console.log(delete (true && (0 / 0)));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\ndelete_binary_2: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        keep_infinity: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (false || undefined));\n        console.log(delete (false || void 0));\n        console.log(delete (false || Infinity));\n        console.log(delete (false || (1 / 0)));\n        console.log(delete (false || NaN));\n        console.log(delete (false || (0 / 0)));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\nInfinity_NaN_undefined_LHS: {\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        function f() {\n            Infinity = Infinity;\n            ++Infinity;\n            Infinity--;\n            NaN *= NaN;\n            ++NaN;\n            NaN--;\n            undefined |= undefined;\n            ++undefined;\n            undefined--;\n        }\n    }\n    expect_exact: [\n        \"function f() {\",\n        \"    Infinity = 1 / 0;\",\n        \"    ++Infinity;\",\n        \"    Infinity--;\",\n        \"    NaN *= NaN;\",\n        \"    ++NaN;\",\n        \"    NaN--;\",\n        \"    undefined |= void 0;\",\n        \"    ++undefined;\",\n        \"    undefined--;\",\n        \"}\",\n    ]\n}\n\nissue_1964_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe_regexp: false,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var long_variable_name = /\\s/;\n            console.log(long_variable_name.source);\n            return \"a b c\".split(long_variable_name)[1];\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            var long_variable_name = /\\s/;\n            console.log(long_variable_name.source);\n            return \"a b c\".split(long_variable_name)[1];\n        }\n        console.log(f());\n    }\n    expect_stdout: [\n        \"\\\\s\",\n        \"b\",\n    ]\n}\n\nissue_1964_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe_regexp: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var long_variable_name = /\\s/;\n            console.log(long_variable_name.source);\n            return \"a b c\".split(long_variable_name)[1];\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            console.log(/\\s/.source);\n            return \"a b c\".split(/\\s/)[1];\n        }\n        console.log(f());\n    }\n    expect_stdout: [\n        \"\\\\s\",\n        \"b\",\n    ]\n}\n\narray_slice_index: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log([1,2,3].slice(1)[1]);\n    }\n    expect: {\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n}\n\nstring_charCodeAt: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\"foo\".charCodeAt(\"bar\".length));\n    }\n    expect: {\n        console.log(NaN);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_2207_1: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(String.fromCharCode(65));\n        console.log(Math.max(3, 6, 2, 7, 3, 4));\n        console.log(Math.cos(1.2345));\n        console.log(Math.cos(1.2345) - Math.sin(4.321));\n        console.log(Math.pow(Math.PI, Math.E - Math.LN10).toFixed(15));\n    }\n    expect: {\n        console.log(\"A\");\n        console.log(7);\n        console.log(Math.cos(1.2345));\n        console.log(1.2543732512566947);\n        console.log(\"1.609398451447204\");\n    }\n    expect_stdout: true\n}\n\nissue_2207_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(Math.E);\n        console.log(Math.LN10);\n        console.log(Math.LN2);\n        console.log(Math.LOG2E);\n        console.log(Math.LOG10E);\n        console.log(Math.PI);\n        console.log(Math.SQRT1_2);\n        console.log(Math.SQRT2);\n    }\n    expect: {\n        console.log(Math.E);\n        console.log(Math.LN10);\n        console.log(Math.LN2);\n        console.log(Math.LOG2E);\n        console.log(Math.LOG10E);\n        console.log(Math.PI);\n        console.log(Math.SQRT1_2);\n        console.log(Math.SQRT2);\n    }\n    expect_stdout: true\n}\n\nissue_2207_3: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(Number.MAX_VALUE);\n        console.log(Number.MIN_VALUE);\n        console.log(Number.NaN);\n        console.log(Number.NEGATIVE_INFINITY);\n        console.log(Number.POSITIVE_INFINITY);\n    }\n    expect: {\n        console.log(Number.MAX_VALUE);\n        console.log(5e-324);\n        console.log(NaN);\n        console.log(-1/0);\n        console.log(1/0);\n    }\n    expect_stdout: true\n}\n\nissue_2231_1: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(Object.keys(void 0));\n    }\n    expect: {\n        console.log(Object.keys(void 0));\n    }\n    expect_stdout: true\n    expect_warnings: [\n        \"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1,20]\",\n    ]\n}\n\nissue_2231_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(Object.getOwnPropertyNames(null));\n    }\n    expect: {\n        console.log(Object.getOwnPropertyNames(null));\n    }\n    expect_stdout: true\n    expect_warnings: [\n        \"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1,20]\",\n    ]\n}\n\nissue_2231_3: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(Object.keys({ foo: \"bar\" })[0]);\n    }\n    expect: {\n        console.log(\"foo\");\n    }\n    expect_stdout: \"foo\"\n}\n\nself_comparison_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var o = { n: NaN };\n        console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);\n    }\n    expect: {\n        console.log(\"number\", false, false, true, true);\n    }\n    expect_stdout: \"number false false true true\"\n}\n\nself_comparison_2: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = { n: NaN };\n        console.log(typeof o.n, o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n);\n    }\n    expect: {\n        console.log(\"number\", false, false, true, true);\n    }\n    expect_stdout: \"number false false true true\"\n}\n\nissue_2535_1: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        if ((x() || true) || y()) z();\n        if ((x() || true) && y()) z();\n        if ((x() && true) || y()) z();\n        if ((x() && true) && y()) z();\n        if ((x() || false) || y()) z();\n        if ((x() || false) && y()) z();\n        if ((x() && false) || y()) z();\n        if ((x() && false) && y()) z();\n    }\n    expect: {\n        if (x(), 1) z();\n        if (x(), y()) z();\n        if (x() || y()) z();\n        if (x() && y()) z();\n        if (x() || y()) z();\n        if (x() && y()) z();\n        if (x(), y()) z();\n        if (x(), 0) z();\n    }\n}\n\nissue_2535_2: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        (x() || true) || y();\n        (x() || true) && y();\n        (x() && true) || y();\n        (x() && true) && y();\n        (x() || false) || y();\n        (x() || false) && y();\n        (x() && false) || y();\n        (x() && false) && y();\n    }\n    expect: {\n        x(),\n        x(), y(),\n        x() || y(),\n        x() && y(),\n        x() || y(),\n        x() && y(),\n        x(), y(),\n        x();\n    }\n}\n\nissue_2535_3: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        console.log(Object(1) && 1 && 2);\n        console.log(Object(1) && true && 1 && 2 && Object(2));\n        console.log(Object(1) && true && 1 && null && 2 && Object(2));\n        console.log(2 == Object(1) || 0 || void 0 || null);\n        console.log(2 == Object(1) || 0 || void 0 || null || Object(2));\n        console.log(2 == Object(1) || 0 || void 0 || \"ok\" || null || Object(2));\n    }\n    expect: {\n        console.log(Object(1) && 2);\n        console.log(Object(1) && Object(2));\n        console.log(Object(1) && null);\n        console.log(2 == Object(1) || null);\n        console.log(2 == Object(1) || Object(2));\n        console.log(2 == Object(1) || \"ok\");\n    }\n    expect_stdout: true\n    expect_warnings: [\n        \"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1,20]\",\n        \"WARN: Dropping side-effect-free && [test/compress/evaluate.js:2,20]\",\n        \"WARN: Dropping side-effect-free && [test/compress/evaluate.js:3,20]\",\n        \"WARN: Condition left of && always false [test/compress/evaluate.js:3,20]\",\n        \"WARN: Dropping side-effect-free || [test/compress/evaluate.js:4,20]\",\n        \"WARN: Dropping side-effect-free || [test/compress/evaluate.js:5,20]\",\n        \"WARN: Dropping side-effect-free || [test/compress/evaluate.js:6,20]\",\n        \"WARN: Condition left of || always true [test/compress/evaluate.js:6,20]\",\n    ]\n}\n\nissue_2822: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log([ function() {}, \"PASS\", \"FAIL\" ][1]);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nstring_case: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\"İ\".toLowerCase().charCodeAt(0));\n        console.log(\"I\".toLowerCase().charCodeAt(0));\n        console.log(\"Ş\".toLowerCase().charCodeAt(0));\n        console.log(\"Ğ\".toLowerCase().charCodeAt(0));\n        console.log(\"Ü\".toLowerCase().charCodeAt(0));\n        console.log(\"Ö\".toLowerCase().charCodeAt(0));\n        console.log(\"Ç\".toLowerCase().charCodeAt(0));\n        console.log(\"i\".toUpperCase().charCodeAt(0));\n        console.log(\"ı\".toUpperCase().charCodeAt(0));\n        console.log(\"ş\".toUpperCase().charCodeAt(0));\n        console.log(\"ğ\".toUpperCase().charCodeAt(0));\n        console.log(\"ü\".toUpperCase().charCodeAt(0));\n        console.log(\"ö\".toUpperCase().charCodeAt(0));\n        console.log(\"ç\".toUpperCase().charCodeAt(0));\n    }\n    expect: {\n        console.log(105);\n        console.log(105);\n        console.log(351);\n        console.log(287);\n        console.log(252);\n        console.log(246);\n        console.log(231);\n        console.log(73);\n        console.log(73);\n        console.log(350);\n        console.log(286);\n        console.log(220);\n        console.log(214);\n        console.log(199);\n    }\n    expect_stdout: [\n        \"105\",\n        \"105\",\n        \"351\",\n        \"287\",\n        \"252\",\n        \"246\",\n        \"231\",\n        \"73\",\n        \"73\",\n        \"350\",\n        \"286\",\n        \"220\",\n        \"214\",\n        \"199\",\n    ]\n}\n\nissue_2916_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        var c = \"PASS\";\n        (function(a, b) {\n            (function(d) {\n                d[0] = 1;\n            })(b);\n            a == b && (c = \"FAIL\");\n        })(\"\", []);\n        console.log(c);\n    }\n    expect: {\n        var c = \"PASS\";\n        (function(a, b) {\n            (function(d) {\n                d[0] = 1;\n            })(b);\n            a == b && (c = \"FAIL\");\n        })(\"\", []);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2916_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(b) {\n            (function(d) {\n                d[0] = 1;\n            })(b);\n            +b && (c = \"PASS\");\n        })([]);\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(b) {\n            b[0] = 1;\n            +b && (c = \"PASS\");\n        })([]);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2919: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log([ function() {} ].toString());\n    }\n    expect: {\n        console.log(\"function(){}\");\n    }\n}\n\nissue_2926_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function f(a) {\n            console.log(f.name.length, f.length);\n        })();\n    }\n    expect: {\n        (function f(a) {\n            console.log(1, 1);\n        })();\n    }\n    expect_stdout: \"1 1\"\n}\n\nissue_2926_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(typeof function() {}.valueOf());\n    }\n    expect: {\n        console.log(\"function\");\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2968_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            (function(a, b) {\n                a <<= 0;\n                a && (a[(c = \"PASS\", 0 >>> (b += 1))] = 0);\n            })(42, -42);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function() {\n            a = 42,\n            void ((a <<= 0) && (a[(c = \"PASS\", 0)] = 0));\n            var a;\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2968_2: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            (function(a, b) {\n                a <<= 0;\n                a && (a[(c = \"PASS\", 0 >>> (b += 1))] = 0);\n            })(42, -42);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function() {\n            a = 42,\n            ((a <<= 0) && (a[(c = \"PASS\", 0)] = 0));\n            var a;\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\ntruthy_conditionals: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        if (a = {}) x();\n        (b = /foo/) && y();\n        (c = function() {}) || z();\n    }\n    expect: {\n        a = {}, x();\n        b = /foo/, y();\n        c = function() {};\n    }\n}\n\ntruthy_loops: {\n    options = {\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        while ([]) x();\n        do {\n            y();\n        } while(a = {});\n    }\n    expect: {\n        for (;;) {\n            [];\n            x();\n        }\n        for (;;) {\n            y();\n            a = {};\n        }\n    }\n}\n\nif_increment: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            if (console)\n                return ++a;\n        }(0));\n    }\n    expect: {\n        console.log(function(a) {\n            if (console)\n                return 1;\n        }());\n    }\n    expect_stdout: \"1\"\n}\n\ntry_increment: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                return ++a;\n            } catch (e) {}\n        }(0));\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                return 1;\n            } catch (e) {}\n        }());\n    }\n    expect_stdout: \"1\"\n}\n\nunsafe_escaped: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            console.log(function(index) {\n                return a[index];\n            }(function(term) {\n                return a.indexOf(term);\n            }(\"PASS\")));\n        })([ \"PASS\" ]);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nunsafe_string_replace: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        \"foo\".replace(\"f\", function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect: {\n        \"foo\".replace(\"f\", function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3387_1: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(1 + (2 + \"3\"[4]));\n    }\n    expect: {\n        console.log(1 + (2 + \"3\"[4]));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_3387_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(1 + (2 + \"3\"[4]));\n    }\n    expect: {\n        console.log(NaN);\n    }\n    expect_stdout: \"NaN\"\n}\n\nsimple_function_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function sum(a, b) {\n            return a + b;\n        }\n        console.log(sum(1, 2) * sum(3, 4));\n    }\n    expect: {\n        console.log(21);\n    }\n    expect_stdout: \"21\"\n}\n\nsimple_function_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var sum = function(a, b) {\n            return a + b;\n        }\n        console.log(sum(1, 2) * sum(3, 4));\n    }\n    expect: {\n        console.log(21);\n    }\n    expect_stdout: \"21\"\n}\n\nrecursive_function_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function factorial(a) {\n            return a > 0 ? a * factorial(a - 1) : 1;\n        }\n        console.log(factorial(5));\n    }\n    expect: {\n        console.log(function factorial(a) {\n            return a > 0 ? a * factorial(a - 1) : 1;\n        }(5));\n    }\n    expect_stdout: \"120\"\n}\n\nrecursive_function_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var factorial = function(a) {\n            return a > 0 ? a * factorial(a - 1) : 1;\n        }\n        console.log(factorial(5));\n    }\n    expect: {\n        var factorial = function(a) {\n            return a > 0 ? a * factorial(a - 1) : 1;\n        }\n        console.log(factorial(5));\n    }\n    expect_stdout: \"120\"\n}\n\nissue_3558: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a) {\n            return 1 + --a;\n        }\n        console.log(f(true), f(false));\n    }\n    expect: {\n        function f(a) {\n            return 1 + --a;\n        }\n        console.log(1, 0);\n    }\n    expect_stdout: \"1 0\"\n}\n\nissue_3568: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var a = 0;\n        function f(b) {\n            return b && b.p;\n        }\n        console.log(f(++a + f()));\n    }\n    expect: {\n        var a = 0;\n        function f(b) {\n            return b && b.p;\n        }\n        console.log(NaN);\n    }\n    expect_stdout: \"NaN\"\n}\n\nconditional_function: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a) {\n            return a && \"undefined\" != typeof A ? A : 42;\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            return a && \"undefined\" != typeof A ? A : 42;\n        }\n        console.log(42, f(1));\n    }\n    expect_stdout: \"42 42\"\n}\n\nbest_of_evaluate: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function d(x, y) {\n            return x / y;\n        }\n        console.log(0 / 3, 1 / 64, 4 / 7, 7 / 7);\n        console.log(d(0, 3), d(1, 64), d(4, 7), d(7, 7));\n    }\n    expect: {\n        function d(x, y) {\n            return x / y;\n        }\n        console.log(0, 1 / 64, 4 / 7, 1);\n        console.log(0, .015625, d(4, 7), 1);\n    }\n    expect_stdout: [\n        \"0 0.015625 0.5714285714285714 1\",\n        \"0 0.015625 0.5714285714285714 1\",\n    ]\n}\n\neager_evaluate: {\n    options = {\n        evaluate: \"eager\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function d(x, y) {\n            return x / y;\n        }\n        console.log(0 / 3, 1 / 64, 4 / 7, 7 / 7);\n        console.log(d(0, 3), d(1, 64), d(4, 7), d(7, 7));\n    }\n    expect: {\n        console.log(0, .015625, .5714285714285714, 1);\n        console.log(0, .015625, .5714285714285714, 1);\n    }\n    expect_stdout: [\n        \"0 0.015625 0.5714285714285714 1\",\n        \"0 0.015625 0.5714285714285714 1\",\n    ]\n}\n\nthreshold_evaluate_default: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(b(\"1\"), b(2), b(b(b(\"ABCDEFGHIJK\"))));\n    }\n    expect: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(\"111\", 6, b(b(b(\"ABCDEFGHIJK\"))));\n    }\n    expect_stdout: \"111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\"\n}\n\nthreshold_evaluate_30: {\n    options = {\n        evaluate: 30,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(b(\"1\"), b(2), b(b(b(\"ABCDEFGHIJK\"))));\n    }\n    expect: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(\"111\", 6, b(b(\"ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\")));\n    }\n    expect_stdout: \"111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\"\n}\n\nthreshold_evaluate_100: {\n    options = {\n        evaluate: 100,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(b(\"1\"), b(2), b(b(b(\"ABCDEFGHIJK\"))));\n    }\n    expect: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(\"111\", 6, b(\"ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\"));\n    }\n    expect_stdout: \"111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\"\n}\n\nthreshold_evaluate_999: {\n    options = {\n        evaluate: 999,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function b(x) {\n            return x + x + x;\n        }\n        console.log(b(\"1\"), b(2), b(b(b(\"ABCDEFGHIJK\"))));\n    }\n    expect: {\n        console.log(\"111\", 6, \"ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\");\n    }\n    expect_stdout: \"111 6 ABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJKABCDEFGHIJK\"\n}\n\ncollapse_vars_regexp: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe_regexp: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var k = 9;\n            var rx = /[A-Z]+/;\n            return [rx, k];\n        }\n        function f2() {\n            var rx = /ab*/g;\n            return function(s) {\n                return rx.exec(s);\n            };\n        }\n        function f3() {\n            var rx = /ab*/g;\n            return function() {\n                return rx;\n            };\n        }\n        (function() {\n            var result;\n            var s = \"acdabcdeabbb\";\n            var rx = /ab*/g;\n            while (result = rx.exec(s))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result;\n            var s = \"acdabcdeabbb\";\n            var rx = f2();\n            while (result = rx(s))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result;\n            var s = \"acdabcdeabbb\";\n            var rx = f3();\n            while (result = rx().exec(s))\n                console.log(result[0]);\n        })();\n    }\n    expect: {\n        function f1() {\n            return [/[A-Z]+/, 9];\n        }\n        function f2() {\n            var rx = /ab*/g;\n            return function(s) {\n                return rx.exec(s);\n            };\n        }\n        function f3() {\n            var rx = /ab*/g;\n            return function() {\n                return rx;\n            };\n        }\n        (function() {\n            var result, rx = /ab*/g;\n            while (result = rx.exec(\"acdabcdeabbb\"))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result, rx = f2();\n            while (result = rx(\"acdabcdeabbb\"))\n                console.log(result[0]);\n        })();\n        (function() {\n            var result, rx = f3();\n            while (result = rx().exec(\"acdabcdeabbb\"))\n                console.log(result[0]);\n        })();\n    }\n    expect_stdout: [\n        \"a\",\n        \"ab\",\n        \"abbb\",\n        \"a\",\n        \"ab\",\n        \"abbb\",\n        \"a\",\n        \"ab\",\n        \"abbb\",\n    ]\n}\n\nissue_3738: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(1 / (0 + ([] - 1) % 1));\n    }\n    expect: {\n        console.log(1 / (0 + ([] - 1) % 1));\n    }\n    expect_stdout: \"Infinity\"\n}\n\nissue_3755: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        unsafe: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log((/4/.exec(1 + (!0 - 5 / \"23\")) || 0).p);\n    }\n    expect: {\n        console.log((/4/.exec(!0 - 5 / \"23\" + 1), 0).p);\n    }\n    expect_stdout: \"undefined\"\n}\n\nvoid_side_effects: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = void console.log(\"PASS\");\n        console.log(a);\n    }\n    expect: {\n        console.log(\"PASS\");\n        console.log(void 0);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\nno_returns: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function() {\n            console.log(\"PASS\");\n        }();\n        console.log(a);\n    }\n    expect: {\n        (function() {\n            console.log(\"PASS\");\n        })();\n        console.log(void 0);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\nvoid_returns: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            function g(b) {\n                if (b) console.log(\"FAIL\");\n            }\n            while (1) {\n                console.log(\"PASS\");\n                try {\n                    if (console) return;\n                } catch (e) {\n                    return g(e);\n                }\n            }\n        }();\n        console.log(a);\n    }\n    expect: {\n        (function() {\n            function g(b) {\n                if (b) console.log(\"FAIL\");\n            }\n            while (1) {\n                console.log(\"PASS\");\n                try {\n                    if (console) return;\n                } catch (e) {\n                    return g(e);\n                }\n            }\n        })();\n        console.log(void 0);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\nvoid_returns_recursive: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            function g(b) {\n                return f();\n            }\n            while (1) {\n                console.log(\"PASS\");\n                try {\n                    if (console) return;\n                } catch (e) {\n                    return g(e);\n                }\n            }\n        }();\n        console.log(a);\n    }\n    expect: {\n        var a = function f() {\n            function g(b) {\n                return f();\n            }\n            while (1) {\n                console.log(\"PASS\");\n                try {\n                    if (console) return;\n                } catch (e) {\n                    return g();\n                }\n            }\n        }();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\nissue_3878_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = function(a) {\n            return (a = 0) == (a && this > (a += 0));\n        }();\n        console.log(b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(true ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3878_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"foo\";\n        a++ + a;\n        a && a;\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        a++ + a;\n        a;\n        console.log(a);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_3882: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            return console.log(a++), a && this;\n        }\n        var b = f();\n        console.log(b);\n    }\n    expect: {\n        var b = function(a) {\n            return console.log(a++), a && this;\n        }();\n        console.log(b);\n    }\n    expect_stdout: [\n        \"NaN\",\n        \"NaN\",\n    ]\n}\n\nissue_3887: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(b) {\n            try {\n                b-- && console.log(\"PASS\");\n            } catch (a_2) {}\n        })(1);\n    }\n    expect: {\n        (function(b) {\n            try {\n                1, console.log(\"PASS\");\n            } catch (a_2) {}\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3903: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(b, c) {\n            return console, c;\n        }\n        var d = f(f(), a = a);\n        console.log(d);\n    }\n    expect: {\n        function f(b, c) {\n            return console, c;\n        }\n        f(f(), \"PASS\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3905: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        unused: true,\n    }\n    input: {\n        (function(a, a) {\n            return console.log(a = 0), a && console.log(\"FAIL\");\n        })(\"foo\", 42);\n    }\n    expect: {\n        (function(a, a) {\n            return console.log(a = 0), a && console.log(\"FAIL\");\n        })(\"foo\", 42);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_3920: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function(b) {\n            return (b[b = 0] = 0) >= (b ? 0 : 1);\n        }(\"foo\");\n        console.log(a);\n    }\n    expect: {\n        (function(b) {\n            \"foo\"[0] = 0;\n        })();\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n}\n\ninlined_increment_prefix: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            ++a;\n        })();\n        console.log(a += 0);\n    }\n    expect: {\n        var a = 0;\n        void ++a;\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\ninlined_increment_postfix: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            a++;\n        })();\n        console.log(a += 0);\n    }\n    expect: {\n        var a = 0;\n        void a++;\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\ncompound_assignment_to_property: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        1 + (0..p >>= 0) && console.log(\"PASS\");\n    }\n    expect: {\n        1 + (0..p >>= 0),\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2208_assign: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        a = 42;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect: {\n        a = 42;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_postfix: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        a = 41;\n        a++;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect: {\n        a = 41;\n        a++;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_prefix: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        a = 43;\n        --a;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect: {\n        a = 43;\n        --a;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3933: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            a && (b ^= 1) && console.log(\"PASS\");\n        })(1);\n    }\n    expect: {\n        (function(a, b) {\n            1, 1, console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3935: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(function f(a) {\n            return a++;\n        }());\n    }\n    expect: {\n        console.log(NaN);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_3937: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var a = 123;\n        (a++ + (b = a))[b] ? 0 ? a : b : 0 ? a : b;\n        console.log(a, b);\n    }\n    expect: {\n        var a = 123;\n        (a++ + (b = a))[b], 0, b;\n        console.log(a, b);\n    }\n    expect_stdout: \"124 124\"\n}\n\nissue_3944: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                while (function() {\n                    var a = 0 == (b && b.p), b = console.log(a);\n                }());\n                f;\n            }\n            f();\n        })();\n    }\n    expect: {\n        void function f() {\n            while (0 == void 0, console.log(false), void 0);\n            f;\n        }();\n    }\n    expect_stdout: \"false\"\n}\n\nissue_3953: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            (a += 0 * (a = 0)) && console.log(\"PASS\");\n        }\n        f(1);\n    }\n    expect: {\n        function f(a) {\n            (a += 0 * (a = 0)) && console.log(\"PASS\");\n        }\n        f(1);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3988: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f(b) {\n            return (\"\" + (b &= 0))[b && this];\n        }\n        var a = f();\n        console.log(a);\n    }\n    expect: {\n        var a = function(b) {\n            return (\"\" + (b &= 0))[b && this];\n        }();\n        console.log(a);\n    }\n    expect_stdout: \"0\"\n}\n\noperator_in: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        Object.prototype.PASS = 0;\n        console.log(0 in [ 1 ]);\n        console.log(0 in [ , ]);\n        console.log(0 / 0 in { NaN: 2 });\n        console.log(\"PASS\" in { });\n        console.log(\"FAIL\" in { });\n        console.log(\"toString\" in { });\n        console.log(\"toString\" in { toString: 3 });\n    }\n    expect: {\n        Object.prototype.PASS = 0;\n        console.log(true);\n        console.log(0 in [ , ]);\n        console.log(true);\n        console.log(\"PASS\" in { });\n        console.log(\"FAIL\" in { });\n        console.log(\"toString\" in { });\n        console.log(\"toString\" in { toString: 3 });\n    }\n    expect_stdout: [\n        \"true\",\n        \"false\",\n        \"true\",\n        \"true\",\n        \"false\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nissue_3997: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = function f(b) {\n            return b[b += this] = b;\n        }(0);\n        console.log(typeof a);\n    }\n    expect: {\n        var a = function f(b) {\n            return b[b += this] = b;\n        }(0);\n        console.log(typeof a);\n    }\n    expect_stdout: \"string\"\n}\n\nissue_4035: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            var b = --a;\n            console.log(delete (0 + b));\n            console.log(delete (1 * b));\n            console.log(delete (b + 0));\n            console.log(delete (b - 0));\n            console.log(delete (b / 1));\n        })();\n    }\n    expect: {\n        var a = 0;\n        (function() {\n            var b = --a;\n            console.log((0 + b, true));\n            console.log((1 * b, true));\n            console.log((0 + b, true));\n            console.log((b - 0, true));\n            console.log((b / 1, true));\n        })();\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nissue_4067: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function(a) {\n            (function(b) {\n                b[0] += 0;\n                console.log(+a);\n            })(a);\n        })([]);\n    }\n    expect: {\n        (function(a) {\n            (function(b) {\n                b[0] += 0;\n                console.log(+a);\n            })(a);\n        })([]);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4077: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log((a = []) - (a[0]++, 1) || \"PASS\");\n    }\n    expect: {\n        console.log((a = []) - (a[0]++, 1) || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4119_1: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var a, b;\n        b = a = [];\n        a[0] += 0;\n        if (+b + 1) {\n            console.log(\"FAIL\");\n        } else {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a, b;\n        b = a = [];\n        a[0] += 0;\n        +b + 1 ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4119_2: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        var a;\n        (function(b) {\n            a[0] += 0;\n            console.log(+b + 1 ? \"FAIL\" : \"PASS\");\n        })(a = []);\n    }\n    expect: {\n        var a;\n        (function(b) {\n            a[0] += 0;\n            console.log(+b + 1 ? \"FAIL\" : \"PASS\");\n        })(a = []);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4119_3: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var a, b;\n        b = a = {\n            p: 42,\n        };\n        delete a.p;\n        console.log(b.p ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        var a, b;\n        b = a = {\n            p: 42,\n        };\n        delete a.p;\n        console.log(b.p ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4119_4: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b;\n        b = a = {\n            p: 42,\n        };\n        delete a.p;\n        console.log(!b ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        var a, b;\n        b = a = {\n            p: 42,\n        };\n        delete a.p;\n        console.log((b, 0, \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4214: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            return function() {\n                try {\n                    return a;\n                } finally {\n                    var b = 0;\n                }\n            }(a++ && this());\n        }\n        var c = f();\n        console.log(c);\n    }\n    expect: {\n        var c = function(a) {\n            return function() {\n                try {\n                    return a;\n                } finally {}\n            }(a++ && this());\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4271: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        ({\n            p: null,\n            q: (console.log(\"foo\"), 42),\n            p: function() {}\n        })[console.log(\"bar\"), \"p\"] && console.log(\"PASS\");\n    }\n    expect: {\n        ({\n            p: null,\n            q: (console.log(\"foo\"), 42),\n            p: function() {}\n        })[console.log(\"bar\"), \"p\"],\n        console.log(\"PASS\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"PASS\",\n    ]\n}\n\nissue_4393: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function f(a) {\n            a = \"PASS\";\n            console.log(arguments[0]);\n        })(\"FAIL\");\n    }\n    expect: {\n        (function f(a) {\n            a = \"PASS\";\n            console.log(arguments[0]);\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4422: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            a = \"FAIL 1\";\n            arguments[0] = \"PASS\";\n            return a;\n        }(\"FAIL 2\"));\n    }\n    expect: {\n        console.log(function(a) {\n            a = \"FAIL 1\";\n            arguments[0] = \"PASS\";\n            return a;\n        }(\"FAIL 2\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4480: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = function f(b) {\n            b = \"FAIL\";\n            arguments[0] = \"PASS\";\n            var arguments = 0;\n            console.log(b);\n        }(a);\n    }\n    expect: {\n        var a = function(b) {\n            b = \"FAIL\";\n            arguments[0] = \"PASS\";\n            var arguments = 0;\n            console.log(b);\n        }(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4552: {\n    options = {\n        evaluate: true,\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f(b) {\n            return function() {\n                b++;\n                try {\n                    return b;\n                } catch (e) {}\n            }();\n        }();\n        console.log(a);\n    }\n    expect: {\n        var a = function f(b) {\n            return function() {\n                b++;\n                try {\n                    return b;\n                } catch (e) {}\n            }();\n        }();\n        console.log(a);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4886_1: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\"length\" in {\n            __proto__: function() {},\n            length: void 0,\n        });\n    }\n    expect: {\n        console.log(\"length\" in {\n            __proto__: function() {},\n            length: void 0,\n        });\n    }\n    expect_stdout: \"true\"\n}\n\nissue_4886_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(\"foo\" in {\n            \"foo\": null,\n            __proto__: 42,\n        });\n    }\n    expect: {\n        console.log(\"foo\" in {\n            \"foo\": null,\n            __proto__: 42,\n        });\n    }\n    expect_stdout: \"true\"\n}\n\nissue_5354: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        function f(a) {\n            return +a.toExponential(1);\n        }\n        function g(b) {\n            return 0 + b.toFixed(2);\n        }\n        function h(c) {\n            return 1 * c.toPrecision(3);\n        }\n        console.log(typeof f(45), typeof g(67), typeof h(89));\n    }\n    expect: {\n        function f(a) {\n            return +a.toExponential(1);\n        }\n        function g(b) {\n            return 0 + b.toFixed(2);\n        }\n        function h(c) {\n            return +c.toPrecision(3);\n        }\n        console.log(typeof f(45), typeof g(67), typeof h(89));\n    }\n    expect_stdout: \"number string number\"\n}\n\nissue_5356: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return a++;\n            var a = a;\n        }());\n    }\n    expect: {\n        console.log(+a);\n        var a;\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5362_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = -console;\n        console.log(delete +a);\n    }\n    expect: {\n        var a = -console;\n        console.log((+a, true));\n    }\n    expect_stdout: \"true\"\n}\n\nissue_5362_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = -console;\n        console.log(delete +a);\n    }\n    expect: {\n        console.log(true);\n    }\n    expect_stdout: \"true\"\n}\n\nissue_5380: {\n    options = {\n        evaluate: true,\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f(b) {\n            return function g() {\n                for (b in { PASS: 42 });\n            }(), b;\n        }(\"FAIL\");\n        console.log(a);\n    }\n    expect: {\n        var a = function f(b) {\n            return function g() {\n                for (b in { PASS: 42 });\n            }(), b;\n        }(\"FAIL\");\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5558: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 99, b = 0;\n        a++;\n        b++;\n        b += a;\n        b *= a;\n        b += a;\n        console.log(a);\n    }\n    expect: {\n        var a = 99, b = 0;\n        b++,\n        b = (b += ++a) * a + a,\n        console.log(a);\n    }\n    expect_stdout: \"100\"\n}\n\nissue_5940: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            f && (console, 42) && (f && (a = [])) && console.log(\"PASS\");\n            f = 42;\n        })();\n    }\n    expect: {\n        (function f(a) {\n            f && (console, 42) && (f && []) && console.log(\"PASS\"),\n            f = 42;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/exponentiation.js",
    "content": "precedence_1: {\n    input: {\n        console.log(-4 ** 3 ** 2);\n    }\n    expect_exact: \"console.log((-4)**3**2);\"\n    expect_stdout: \"-262144\"\n    node_version: \">=8\"\n}\n\nprecedence_2: {\n    input: {\n        console.log(-4 ** (3 ** 2));\n    }\n    expect_exact: \"console.log((-4)**3**2);\"\n    expect_stdout: \"-262144\"\n    node_version: \">=8\"\n}\n\nprecedence_3: {\n    input: {\n        console.log(-(4 ** 3) ** 2);\n    }\n    expect_exact: \"console.log((-(4**3))**2);\"\n    expect_stdout: \"4096\"\n    node_version: \">=8\"\n}\n\nprecedence_4: {\n    input: {\n        console.log((-4 ** 3) ** 2);\n    }\n    expect_exact: \"console.log(((-4)**3)**2);\"\n    expect_stdout: \"4096\"\n    node_version: \">=8\"\n}\n\nawait: {\n    input: {\n        (async a => a * await a ** ++a % a)(2).then(console.log);\n    }\n    expect_exact: \"(async a=>a*(await a)**++a%a)(2).then(console.log);\"\n    expect_stdout: \"1\"\n    node_version: \">=8\"\n}\n\nassignment_1: {\n    input: {\n        var a = 2;\n        a **= 5;\n        console.log(a);\n    }\n    expect_exact: \"var a=2;a**=5;console.log(a);\"\n    expect_stdout: \"32\"\n    node_version: \">=8\"\n}\n\nassignment_2: {\n    input: {\n        var a = 8n;\n        a **= a;\n        console.log(a);\n    }\n    expect_exact: \"var a=8n;a**=a;console.log(a);\"\n    expect_stdout: \"16777216n\"\n    node_version: \">=10.4.0\"\n}\n\nevaluate: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(1 + 2 ** 3 - 4);\n    }\n    expect: {\n        console.log(5);\n    }\n    expect_stdout: \"5\"\n    node_version: \">=8\"\n}\n\nissue_4664: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            new function(a) {\n                console.log(typeof f, a, typeof this);\n            }((A = 0, (NaN ^ 1) * 2 ** 30), 0);\n        }\n        f();\n    }\n    expect: {\n        (function f() {\n            new function(a) {\n                console.log(typeof f, 2 ** 30, typeof this);\n            }(A = 0);\n        })();\n    }\n    expect_stdout: \"function 1073741824 object\"\n    node_version: \">=8\"\n}\n\nissue_4715: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        A = 1;\n        console.log((-0) ** A + 0);\n        console.log((-0) ** A - 0);\n        console.log((-0) ** A * 1);\n        console.log((-0) ** A / 1);\n        console.log(Math.pow(-0, A) + 0);\n        console.log(Math.pow(-0, A) - 0);\n        console.log(Math.pow(-0, A) * 1);\n        console.log(Math.pow(-0, A) / 1);\n    }\n    expect: {\n        A = 1;\n        console.log((-0) ** A + 0);\n        console.log((-0) ** A);\n        console.log((-0) ** A * 1);\n        console.log((-0) ** A);\n        console.log(Math.pow(-0, A) + 0);\n        console.log(+Math.pow(-0, A));\n        console.log(+Math.pow(-0, A));\n        console.log(+Math.pow(-0, A));\n    }\n    expect_stdout: [\n        \"0\",\n        \"-0\",\n        \"-0\",\n        \"-0\",\n        \"0\",\n        \"-0\",\n        \"-0\",\n        \"-0\",\n    ]\n    node_version: \">=8\"\n}\n"
  },
  {
    "path": "test/compress/exports.js",
    "content": "refs: {\n    input: {\n        export {};\n        export { a, b as B, c as case, d as default };\n    }\n    expect_exact: \"export{};export{a,b as B,c as case,d as default};\"\n}\n\nvar_defs: {\n    input: {\n        export const a = 1;\n        export let b = 2, c = 3;\n        export var { d, e: [] } = f;\n    }\n    expect_exact: \"export const a=1;export let b=2,c=3;export var{d,e:[]}=f;\"\n}\n\ndefuns: {\n    input: {\n        export class A {}\n        export function e() {}\n        export function* f(a) {}\n        export async function g(b, c) {}\n        export async function* h({}, ...[]) {}\n    }\n    expect_exact: \"export class A{}export function e(){}export function*f(a){}export async function g(b,c){}export async function*h({},...[]){}\"\n}\n\ndefaults: {\n    input: {\n        export default 42;\n        export default async;\n        export default (x, y) => x * x;\n        export default class {};\n        export default function*(a, b) {};\n        export default async function f({ c }, ...[ d ]) {};\n    }\n    expect_exact: \"export default 42;export default async;export default(x,y)=>x*x;export default class{}export default function*(a,b){}export default async function f({c},...[d]){}\"\n}\n\ndefaults_parentheses_1: {\n    input: {\n        export default function() {\n            console.log(\"FAIL\");\n        }(console.log(\"PASS\"));\n    }\n    expect_exact: 'export default function(){console.log(\"FAIL\")}console.log(\"PASS\");'\n}\n\ndefaults_parentheses_2: {\n    input: {\n        export default (async function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_exact: 'export default(async function(){console.log(\"PASS\")})();'\n}\n\ndefaults_parentheses_3: {\n    input: {\n        export default (42, \"PASS\");\n    }\n    expect_exact: 'export default(42,\"PASS\");'\n}\n\ndefaults_parentheses_4: {\n    input: {\n        export default (function f() {});\n    }\n    expect_exact: \"export default(function f(){});\"\n}\n\ndefaults_parentheses_5: {\n    input: {\n        export default (function(a) {\n            console.log(a[0]);\n        }`PASS`);\n    }\n    expect_exact: \"export default(function(a){console.log(a[0])})`PASS`;\"\n}\n\ndefaults_parentheses_6: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        export default !function() {\n            while (!console);\n        }() ? \"PASS\" : \"FAIL\";\n    }\n    expect_exact: 'export default(function(){while(!console);})()?\"FAIL\":\"PASS\";'\n}\n\ndefaults_regexp: {\n    input: {\n        export default /foo/;\n    }\n    expect_exact: \"export default/foo/;\"\n}\n\nforeign: {\n    input: {\n        export * from \"foo\";\n        export {} from \"bar\";\n        export * as a from \"baz\";\n        export { default } from \"moo\";\n        export { b, c as case, default as delete, d } from \"moz\";\n    }\n    expect_exact: 'export*from\"foo\";export{}from\"bar\";export*as a from\"baz\";export{default}from\"moo\";export{b,c as case,default as delete,d}from\"moz\";'\n}\n\nnon_identifiers: {\n    beautify = {\n        quote_style: 3,\n    }\n    input: {\n        export * as \"42\" from 'foo';\n        export { '42', \"delete\" as 'foo' } from \"bar\";\n    }\n    expect_exact: \"export*as\\\"42\\\"from'foo';export{'42',delete as foo}from\\\"bar\\\";\"\n}\n\nsame_quotes: {\n    beautify = {\n        beautify: true,\n        quote_style: 3,\n    }\n    input: {\n        export * from 'foo';\n        export {} from \"bar\";\n    }\n    expect_exact: [\n        \"export * from 'foo';\",\n        \"\",\n        'export {} from \"bar\";',\n    ]\n}\n\ndrop_unused: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export default 42;\n        export default (x, y) => x * x;\n        export default class A extends B { get p() { h() } }\n        export default function*(a, b) {}\n        export default async function f({ c }, ...[ d ]) {}\n        export var e;\n        export function g(x, [ y ], ...z) {}\n        function h() {}\n    }\n    expect: {\n        export default 42;\n        export default (x, y) => x * x;\n        export default class extends B { get p() { h() } }\n        export default function*(a, b) {}\n        export default async function({}) {}\n        export var e;\n        export function g(x, []) {}\n        function h() {}\n    }\n}\n\nmangle: {\n    rename = false\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        const a = 42;\n        export let b, { foo: c } = a;\n        export function f(d, { [b]: e }) {\n            d(e, f);\n        }\n        export default a;\n        export default async function g(x, ...{ [c]: y }) {\n            (await x)(g, y);\n        }\n    }\n    expect: {\n        const t = 42;\n        export let b, { foo: c } = t;\n        export function f(t, { [b]: o }) {\n            t(o, f);\n        }\n        export default t;\n        export default async function e(t, ...{ [c]: o}) {\n            (await t)(e, o);\n        }\n    }\n}\n\nmangle_rename: {\n    rename = true\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        const a = 42;\n        export let b, { foo: c } = a;\n        export function f(d, { [b]: e }) {\n            d(e, f);\n        }\n        export default a;\n        export default async function g(x, ...{ [c]: y }) {\n            (await x)(g, y);\n        }\n    }\n    expect: {\n        const t = 42;\n        export let b, { foo: c } = t;\n        export function f(t, { [b]: o }) {\n            t(o, f);\n        }\n        export default t;\n        export default async function e(t, ...{ [c]: o}) {\n            (await t)(e, o);\n        }\n    }\n}\n\nhoist_exports_1: {\n    options = {\n        hoist_exports: true,\n    }\n    input: {\n        export { a };\n        export var b;\n        export function f() {}\n    }\n    expect: {\n        var b;\n        function f() {}\n        export { a, b, f };\n    }\n}\n\nhoist_exports_2: {\n    options = {\n        evaluate: true,\n        hoist_exports: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        const a = 42;\n        export let bbb, { foo: ccc } = a;\n        export function fff(d, { [bbb]: e }) {\n            d(e, fff);\n        }\n        export default a;\n        export default async function g(x, ...{ [ccc]: y }) {\n            (await x)(g, y);\n        }\n    }\n    expect: {\n        let e, a = 42..foo;\n        function f(t, { [e]: o }) {\n            t(o, f);\n        }\n        export default 42;\n        export default async function n(t, ...{ [a]: o }) {\n            (await t)(n, o);\n        };\n        export { e as bbb, a as ccc, f as fff };\n    }\n}\n\nhoist_vars: {\n    options = {\n        hoist_vars: true,\n    }\n    input: {\n        var a;\n        export var b = 42;\n    }\n    expect: {\n        var a;\n        export var b = 42;\n    }\n}\n\nkeep_return_values: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        export default function() {\n            return [];\n        }\n        export default function f() {\n            return null;\n        }\n    }\n    expect: {\n        export default function() {\n            return [];\n        }\n        export default function f() {\n            return null;\n        }\n    }\n}\n\nin_use: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export function f() {}\n        f.prototype.p = 42;\n    }\n    expect: {\n        export function f() {}\n        f.prototype.p = 42;\n    }\n}\n\nin_use_default: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export default function f() {}\n        f.prototype.p = 42;\n    }\n    expect: {\n        export default function f() {}\n        f.prototype.p = 42;\n    }\n}\n\nsingle_use: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export function f() {\n            console.log(\"PASS\");\n        }\n        f();\n    }\n    expect: {\n        export function f() {\n            console.log(\"PASS\");\n        }\n        f();\n    }\n}\n\nsingle_use_default: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export default function f() {\n            console.log(\"PASS\");\n        }\n        f();\n    }\n    expect: {\n        export default function f() {\n            console.log(\"PASS\");\n        }\n        f();\n    }\n}\n\nsingle_use_class: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export class A {}\n        A.prototype.p = \"PASS\";\n    }\n    expect: {\n        export class A {}\n        A.prototype.p = \"PASS\";\n    }\n}\n\nsingle_use_class_default: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export default class A {}\n        A.prototype.p = \"PASS\";\n    }\n    expect: {\n        export default class A {}\n        A.prototype.p = \"PASS\";\n    }\n}\n\nhoist_funs: {\n    options = {\n        hoist_funs: true,\n    }\n    input: {\n        export function f() {}\n        export default async function* g() {}\n    }\n    expect_exact: \"export function f(){}export default async function*g(){}\"\n}\n\ninstanceof_default_class: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export default class A {\n            f(a) {\n                return a instanceof A;\n            }\n        }\n    }\n    expect: {\n        export default class A {\n            f(a) {\n                return a instanceof A;\n            }\n        }\n    }\n}\n\ninstanceof_default_function: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export default function f() {\n            if (!(this instanceof f))\n                throw new Error(\"must instantiate\");\n        }\n    }\n    expect: {\n        export default function f() {\n            if (!(this instanceof f))\n                throw new Error(\"must instantiate\");\n        }\n    }\n}\n\nissue_4742_join_vars_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a = 42;\n        export var a;\n    }\n    expect: {\n        var a = 42;\n        export var a;\n    }\n}\n\nissue_4742_join_vars_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        export var a = \"foo\";\n        var b;\n        b = \"bar\";\n    }\n    expect: {\n        export var a = \"foo\";\n        var b, b = \"bar\";\n    }\n}\n\nissue_4742_unused_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        export var a;\n    }\n    expect: {\n        var a = 42;\n        export var a;\n    }\n}\n\nissue_4742_unused_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        export var a = \"foo\";\n        var a = \"bar\";\n    }\n    expect: {\n        export var a = \"foo\";\n        a = \"bar\";\n    }\n}\n\nissue_4761: {\n    input: {\n        export default \"function\" == 42;\n    }\n    expect_exact: 'export default\"function\"==42;'\n}\n\nissue_4766: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a = \"foo\";\n        export var a = \"bar\";\n    }\n    expect: {\n        var a = \"foo\";\n        export var a = \"bar\";\n    }\n}\n\nissue_5444: {\n    options = {\n        unused: true,\n    }\n    input: {\n        export var a = (console, console);\n    }\n    expect: {\n        console;\n        export var a = console;\n    }\n}\n\nissue_5628: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var a;\n        export default function f() {\n            for (a in 42);\n        }\n        console.log(a);\n    }\n    expect: {\n        var a;\n        export default function f() {\n            for (a in 42);\n        }\n        console.log(a);\n    }\n}\n"
  },
  {
    "path": "test/compress/functions.js",
    "content": "non_ascii_function_identifier_name: {\n    input: {\n        function fooλ(δλ) {}\n        function λ(δλ) {}\n        (function λ(δλ) {})()\n    }\n    expect_exact: \"function fooλ(δλ){}function λ(δλ){}(function λ(δλ){})();\"\n}\n\niifes_returning_constants_keep_fargs_true: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(){ return -1.23; }());\n        console.log( function foo(){ return \"okay\"; }() );\n        console.log( function foo(x, y, z){ return 123; }() );\n        console.log( function(x, y, z){ return z; }() );\n        console.log( function(x, y, z){ if (x) return y; return z; }(1, 2, 3) );\n        console.log( function(x, y){ return x * y; }(2, 3) );\n        console.log( function(x, y){ return x * y; }(2, 3, a(), b()) );\n    }\n    expect: {\n        console.log(\"okay\");\n        console.log(123);\n        console.log(void 0);\n        console.log(2);\n        console.log(6);\n        console.log((a(), b(), 6));\n    }\n    expect_stdout: true\n}\n\niifes_returning_constants_keep_fargs_false: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(){ return -1.23; }());\n        console.log( function foo(){ return \"okay\"; }() );\n        console.log( function foo(x, y, z){ return 123; }() );\n        console.log( function(x, y, z){ return z; }() );\n        console.log( function(x, y, z){ if (x) return y; return z; }(1, 2, 3) );\n        console.log( function(x, y){ return x * y; }(2, 3) );\n        console.log( function(x, y){ return x * y; }(2, 3, a(), b()) );\n    }\n    expect: {\n        console.log(\"okay\");\n        console.log(123);\n        console.log(void 0);\n        console.log(2);\n        console.log(6);\n        console.log((a(), b(), 6));\n    }\n    expect_stdout: true\n}\n\nissue_485_crashing_1530: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        (function(a) {\n            if (true) return;\n            var b = 42;\n        })(this);\n    }\n    expect: {}\n}\n\nissue_1841_1: {\n    options = {\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var b = 10;\n        !function(arg) {\n            for (var key in \"hi\")\n                var n = arg.baz, n = [ b = 42 ];\n        }(--b);\n        console.log(b);\n    }\n    expect: {\n        var b = 10;\n        !function() {\n            for (var key in \"hi\")\n                b = 42;\n        }(--b);\n        console.log(b);\n    }\n    expect_exact: \"42\"\n}\n\nissue_1841_2: {\n    options = {\n        keep_fargs: false,\n        pure_getters: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var b = 10;\n        !function(arg) {\n            for (var key in \"hi\")\n                var n = arg.baz, n = [ b = 42 ];\n        }(--b);\n        console.log(b);\n    }\n    expect: {\n        var b = 10;\n        !function(arg) {\n            for (var key in \"hi\")\n                arg.baz, b = 42;\n        }(--b);\n        console.log(b);\n    }\n    expect_exact: \"42\"\n}\n\nfunction_returning_constant_literal: {\n    options = {\n        inline: true,\n        passes: 2,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function greeter() {\n            return { message: 'Hello there' };\n        }\n        var greeting = greeter();\n        console.log(greeting.message);\n    }\n    expect: {\n        console.log(\"Hello there\");\n    }\n    expect_stdout: \"Hello there\"\n}\n\nhoist_funs: {\n    options = {\n        hoist_funs: true,\n    }\n    input: {\n        console.log(1, typeof f, typeof g);\n        if (console.log(2, typeof f, typeof g))\n            console.log(3, typeof f, typeof g);\n        else {\n            console.log(4, typeof f, typeof g);\n            function f() {}\n            console.log(5, typeof f, typeof g);\n        }\n        function g() {}\n        console.log(6, typeof f, typeof g);\n    }\n    expect: {\n        function f() {}\n        function g() {}\n        console.log(1, typeof f, typeof g);\n        if (console.log(2, typeof f, typeof g))\n            console.log(3, typeof f, typeof g);\n        else {\n            console.log(4, typeof f, typeof g);\n            console.log(5, typeof f, typeof g);\n        }\n        console.log(6, typeof f, typeof g);\n    }\n    expect_stdout: [\n        \"1 'function' 'function'\",\n        \"2 'function' 'function'\",\n        \"4 'function' 'function'\",\n        \"5 'function' 'function'\",\n        \"6 'function' 'function'\",\n    ]\n    node_version: \"<=4\"\n}\n\nissue_203: {\n    options = {\n        keep_fargs: false,\n        side_effects: true,\n        unsafe_Function: true,\n        unused: true,\n    }\n    input: {\n        var m = {};\n        var fn = Function(\"require\", \"module\", \"exports\", \"module.exports = 42;\");\n        fn(null, m, m.exports);\n        console.log(m.exports);\n    }\n    expect: {\n        var m = {};\n        var fn = Function(\"n,o,t\", \"o.exports=42\");\n        fn(null, m, m.exports);\n        console.log(m.exports);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2084: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        !function() {\n            !function(c) {\n                c = 1 + c;\n                var c = 0;\n                function f14(a_1) {\n                    if (c = 1 + c, 0 !== 23..toString())\n                        c = 1 + c, a_1 && (a_1[0] = 0);\n                }\n                f14();\n            }(-1);\n        }();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        23..toString(),\n        console.log(c);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_2097: {\n    options = {\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw 0;\n            } catch (e) {\n                console.log(arguments[0]);\n            }\n        }\n        f(1);\n    }\n    expect: {\n        !function() {\n            try {\n                throw 0;\n            } catch (e) {\n                console.log(arguments[0]);\n            }\n        }(1);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2101: {\n    options = {\n        inline: true,\n    }\n    input: {\n        a = {};\n        console.log(function() {\n            return function() {\n                return this.a;\n            }();\n        }() === function() {\n            return a;\n        }());\n    }\n    expect: {\n        a = {};\n        console.log(function() {\n            return this.a;\n        }() === a);\n    }\n    expect_stdout: \"true\"\n}\n\ninner_ref: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            return function() {\n                return a;\n            }();\n        }(1), function(a) {\n            return function(a) {\n                return a;\n            }();\n        }(2));\n    }\n    expect: {\n        console.log(1, void 0);\n    }\n    expect_stdout: \"1 undefined\"\n}\n\nissue_2107: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        inline: true,\n        passes: 3,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        !function() {\n            c++;\n        }(c++ + new function() {\n            this.a = 0;\n            var a = (c = c + 1) + (c = 1 + c);\n            return c++ + a;\n        }());\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        c++, new function() {\n            this.a = 0, c = 1 + (c += 1), c++;\n        }(), c++, console.log(c);\n    }\n    expect_stdout: \"5\"\n}\n\nissue_2114_1: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        if_return: true,\n        inline: true,\n        keep_fargs: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        !function(a) {\n            a = 0;\n        }([ {\n            0: c = c + 1,\n            length: c = 1 + c\n        }, typeof void function a() {\n            var b = function f1(a) {\n            }(b && (b.b += (c = c + 1, 0)));\n        }() ]);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        c = 1 + (c += 1), function() {\n            var b = void (b && (b.b += (c += 1, 0)));\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2114_2: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        if_return: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        !function(a) {\n            a = 0;\n        }([ {\n            0: c = c + 1,\n            length: c = 1 + c\n        }, typeof void function a() {\n            var b = function f1(a) {\n            }(b && (b.b += (c = c + 1, 0)));\n        }() ]);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        c = 1 + (c += 1), function() {\n            var b = void (b && (b.b += (c += 1, 0)));\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2428: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function bar(k) {\n            console.log(k);\n        }\n        function foo(x) {\n            return bar(x);\n        }\n        function baz(a) {\n            foo(a);\n        }\n        baz(42);\n        baz(\"PASS\");\n    }\n    expect: {\n        function baz(a) {\n            console.log(a);\n        }\n        baz(42);\n        baz(\"PASS\");\n    }\n    expect_stdout: [\n        \"42\",\n        \"PASS\",\n    ]\n}\n\nissue_2531_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function outer() {\n            function inner(value) {\n                function closure() {\n                    return value;\n                }\n                return function() {\n                    return closure();\n                };\n            }\n            return inner(\"Hello\");\n        }\n        console.log(\"Greeting:\", outer()());\n    }\n    expect: {\n        function outer() {\n            return value = \"Hello\", function() {\n                return value;\n            };\n            var value;\n        }\n        console.log(\"Greeting:\", outer()());\n    }\n    expect_stdout: \"Greeting: Hello\"\n}\n\nissue_2531_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function outer() {\n            function inner(value) {\n                function closure() {\n                    return value;\n                }\n                return function() {\n                    return closure();\n                };\n            }\n            return inner(\"Hello\");\n        }\n        console.log(\"Greeting:\", outer()());\n    }\n    expect: {\n        function outer() {\n            return function() {\n                return \"Hello\";\n            };\n        }\n        console.log(\"Greeting:\", outer()());\n    }\n    expect_stdout: \"Greeting: Hello\"\n}\n\nissue_2531_3: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function outer() {\n            function inner(value) {\n                function closure() {\n                    return value;\n                }\n                return function() {\n                    return closure();\n                };\n            }\n            return inner(\"Hello\");\n        }\n        console.log(\"Greeting:\", outer()());\n    }\n    expect: {\n        console.log(\"Greeting:\", \"Hello\");\n    }\n    expect_stdout: \"Greeting: Hello\"\n}\n\nempty_body: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            function noop() {}\n            noop();\n            return noop;\n        }\n    }\n    expect: {\n        function f() {\n            function noop() {}\n            return noop;\n        }\n    }\n}\n\ninline_binary_and: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            (function() {\n                while (console.log(\"foo\"));\n                return \"bar\";\n            })() && (function() {\n                while (console.log(\"baz\"));\n                return \"moo\";\n            })();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (function() {\n                while (console.log(\"foo\"));\n                return \"bar\";\n            }()) {\n                while (console.log(\"baz\"));\n                return void \"moo\";\n                return;\n            } else\n                return void 0;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"undefined\",\n    ]\n}\n\ninline_binary_or: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function() {\n            while (console.log(\"foo\"));\n        })() || (function() {\n            while (console.log(\"bar\"));\n        })();\n    }\n    expect: {\n        if (!function() {\n            while (console.log(\"foo\"));\n        }())\n            while (console.log(\"bar\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ninline_conditional: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function() {\n            while (console.log(\"foo\"));\n        })() ? (function() {\n            while (console.log(\"bar\"));\n        })() : (function() {\n            while (console.log(\"baz\"));\n        })();\n    }\n    expect: {\n        if (function() {\n            while (console.log(\"foo\"));\n        }())\n            while (console.log(\"bar\"));\n        else\n            while (console.log(\"baz\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n    ]\n}\n\ninline_do: {\n    options = {\n        inline: true,\n    }\n    input: {\n        do (function() {\n            while (console.log(\"foo\"));\n        })();\n        while (function() {\n            while (console.log(\"bar\"));\n        }());\n    }\n    expect: {\n        do {\n            while (console.log(\"foo\"));\n        } while (function() {\n            while (console.log(\"bar\"));\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ninline_finally_return: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            try {\n                throw \"FAIL\";\n            } finally {\n                return function() {\n                    while (console.log(\"PASS\"));\n                }(), 42;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            try {\n                throw \"FAIL\";\n            } finally {\n                while (console.log(\"PASS\"));\n                return 42;\n            }\n        }());\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n}\n\ninline_for_init: {\n    options = {\n        inline: true,\n    }\n    input: {\n        for (function() {\n            while (console.log(\"foo\"));\n        }(); function() {\n            while (console.log(\"bar\"));\n        }(); function() {\n            while (console.log(\"baz\"));\n        }()) (function() {\n            while (console.log(\"moo\"));\n        })();\n    }\n    expect: {\n        while (console.log(\"foo\"));\n        for (; function() {\n            while (console.log(\"bar\"));\n        }(); function() {\n            while (console.log(\"baz\"));\n        }()) {\n            while (console.log(\"moo\"));\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ninline_for_object: {\n    options = {\n        inline: true,\n    }\n    input: {\n        for (var a in function() {\n            while (console.log(\"foo\"));\n        }(), function() {\n            while (console.log(\"bar\"));\n        }()) (function() {\n            while (console.log(\"baz\"));\n        })();\n    }\n    expect: {\n        while (console.log(\"foo\"));\n        for (var a in function() {\n            while (console.log(\"bar\"));\n        }()) {\n            while (console.log(\"baz\"));\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ninline_if_else: {\n    options = {\n        inline: true,\n    }\n    input: {\n        if (function() {\n            while (console.log(\"foo\"));\n        }(), function() {\n            while (console.log(\"bar\"));\n        }()) (function() {\n            while (console.log(\"baz\"));\n        })();\n        else (function() {\n            while (console.log(\"moo\"));\n        })();\n    }\n    expect: {\n        while (console.log(\"foo\"));\n        if (function() {\n            while (console.log(\"bar\"));\n        }()) {\n            while (console.log(\"baz\"));\n        } else {\n            while (console.log(\"moo\"));\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n    ]\n}\n\ninline_label: {\n    options = {\n        inline: true,\n    }\n    input: {\n        L: (function() {\n            while (console.log(\"PASS\"));\n        })()\n    }\n    expect: {\n        L: {\n            while (console.log(\"PASS\"));\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\ninline_loop_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return x();\n        }\n        for (;;) f();\n    }\n    expect: {\n        for (;;) x();\n    }\n}\n\ninline_loop_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (;;) f();\n        function f() {\n            return x();\n        }\n    }\n    expect: {\n        for (;;) x();\n    }\n}\n\ninline_loop_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function() {\n            return x();\n        };\n        for (;;) f();\n    }\n    expect: {\n        for (;;) x();\n    }\n}\n\ninline_loop_4: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (;;) f();\n        var f = function() {\n            return x();\n        };\n    }\n    expect: {\n        for (;;) f();\n        var f = function() {\n            return x();\n        };\n    }\n}\n\ninline_loop_5: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a in \"foo\") {\n            (function() {\n                function f() {}\n                var f;\n                console.log(typeof f, a - f);\n            })();\n        }\n    }\n    expect: {\n        for (var a in \"foo\")\n            f = void 0,\n            f = function() {},\n            void console.log(typeof f, a - f);\n        var f;\n    }\n    expect_stdout: [\n        \"function NaN\",\n        \"function NaN\",\n        \"function NaN\",\n    ]\n}\n\ninline_loop_6: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a in \"foo\") {\n            (function() {\n                var f;\n                function f() {}\n                console.log(typeof f, a - f);\n            })();\n        }\n    }\n    expect: {\n        for (var a in \"foo\")\n            f = void 0,\n            f = function() {},\n            void console.log(typeof f, a - f);\n        var f;\n    }\n    expect_stdout: [\n        \"function NaN\",\n        \"function NaN\",\n        \"function NaN\",\n    ]\n}\n\ninline_loop_7: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a in \"foo\") {\n            (function() {\n                function f() {}\n                var f;\n                while (console.log(typeof f, a - f));\n            })();\n        }\n    }\n    expect: {\n        for (var a in \"foo\") {\n            f = void 0;\n            var f = function() {};\n            var f;\n            while (console.log(typeof f, a - f));\n        }\n    }\n    expect_stdout: [\n        \"function NaN\",\n        \"function NaN\",\n        \"function NaN\",\n    ]\n}\n\ninline_loop_8: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a in \"foo\") {\n            (function() {\n                var f;\n                function f() {}\n                while (console.log(typeof f, a - f));\n            })();\n        }\n    }\n    expect: {\n        for (var a in \"foo\") {\n            f = void 0;\n            var f = function() {};\n            var f;\n            while (console.log(typeof f, a - f));\n        }\n    }\n    expect_stdout: [\n        \"function NaN\",\n        \"function NaN\",\n        \"function NaN\",\n    ]\n}\n\ninline_loop_9: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a = 0; a < 2; a++) {\n            (function() {\n                var b = b && b[console.log(\"FAIL\")] || \"PASS\";\n                while (console.log(b));\n            })();\n        }\n    }\n    expect: {\n        for (var a = 0; a < 2; a++) {\n            b = void 0;\n            var b = b && b[console.log(\"FAIL\")] || \"PASS\";\n            while (console.log(b));\n        }\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\ninline_negate_iife: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            return !function() {\n                while (!console);\n            }();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            while (!console);\n            return !void 0;\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\ninline_return_binary: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            return function() {\n                while (console.log(\"foo\"));\n                return \"bar\";\n            }() || function() {\n                while (console.log(\"baz\"));\n                return \"moo\";\n            }();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            while (console.log(\"foo\"));\n            return \"bar\";\n        }() || function() {\n            while (console.log(\"baz\"));\n            return \"moo\";\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ninline_return_conditional: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            return console ? \"foo\" : function() {\n                while (console.log(\"bar\"));\n                return \"baz\";\n            }();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (console)\n                return \"foo\";\n            else {\n                while (console.log(\"bar\"));\n                return \"baz\";\n                return;\n            }\n        }());\n    }\n    expect_stdout: \"foo\"\n}\n\ninline_while: {\n    options = {\n        inline: true,\n    }\n    input: {\n        while (function() {\n            while (console.log(\"foo\"));\n        }()) (function() {\n            while (console.log(\"bar\"));\n        })();\n    }\n    expect: {\n        while (function() {\n            while (console.log(\"foo\"));\n        }()) {\n            while (console.log(\"bar\"));\n        }\n    }\n    expect_stdout: \"foo\"\n}\n\ninline_with: {\n    options = {\n        inline: true,\n    }\n    input: {\n        with (+function() {\n            while (console.log(\"foo\"));\n        }(), -function() {\n            while (console.log(\"bar\"));\n        }()) ~function() {\n            while (console.log(\"baz\"));\n        }();\n    }\n    expect: {\n        while (console.log(\"foo\"));\n        with (-function() {\n            while (console.log(\"bar\"));\n        }()) {\n            while (console.log(\"baz\"));\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_2476: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        }\n        for (var sum = 0, i = 0; i < 10; i++)\n            sum += foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect: {\n        for (var sum = 0, i = 0; i < 10; i++)\n            sum += (x = i, y = i + 1, z = 3 * i, x < y ? x * y + z : x * z - y);\n        var x, y, z;\n        console.log(sum);\n    }\n    expect_stdout: \"465\"\n}\n\nissue_2601_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function() {\n            function f(b) {\n                function g(b) {\n                    b && b();\n                }\n                g();\n                (function() {\n                    b && (a = \"PASS\");\n                })();\n            }\n            f(\"foo\");\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function() {\n            var b;\n            b = \"foo\",\n            function(b) {\n                b && b();\n            }(),\n            b && (a = \"PASS\");\n        })(),\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2601_2: {\n    rename = true\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var a = \"FAIL\";\n        (function() {\n            function f(b) {\n                function g(b) {\n                    b && b();\n                }\n                g();\n                (function() {\n                    b && (a = \"PASS\");\n                })();\n            }\n            f(\"foo\");\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        a = \"PASS\",\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2604_1: {\n    options = {\n        inline: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function() {\n            try {\n                throw 1;\n            } catch (b) {\n                (function f(b) {\n                    b && b();\n                })();\n                b && (a = \"PASS\");\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (b) {\n            (function(b) {\n                b && b();\n            })();\n            b && (a = \"PASS\");\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2604_2: {\n    rename = true\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var a = \"FAIL\";\n        (function() {\n            try {\n                throw 1;\n            } catch (b) {\n                (function f(b) {\n                    b && b();\n                })();\n                b && (a = \"PASS\");\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (o) {\n            o && (a = \"PASS\");\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nunsafe_apply_1: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            console.log(a, b);\n        }).apply(\"foo\", [ \"bar\" ]);\n        (function(a, b) {\n            console.log(this, a, b);\n        }).apply(\"foo\", [ \"bar\" ]);\n        (function(a, b) {\n            console.log(a, b);\n        }).apply(\"foo\", [ \"bar\" ], \"baz\");\n    }\n    expect: {\n        console.log(\"bar\", void 0);\n        (function(a, b) {\n            console.log(this, a, b);\n        }).call(\"foo\", \"bar\");\n        (function(a, b) {\n            console.log(a, b);\n        }).apply(\"foo\", [ \"bar\" ], \"baz\");\n    }\n    expect_stdout: true\n}\n\nunsafe_apply_2: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        function foo() {\n            console.log(a, b);\n        }\n        var bar = function(a, b) {\n            console.log(this, a, b);\n        }\n        (function() {\n            foo.apply(\"foo\", [ \"bar\" ]);\n            bar.apply(\"foo\", [ \"bar\" ]);\n        })();\n    }\n    expect: {\n        function foo() {\n            console.log(a, b);\n        }\n        var bar = function(a, b) {\n            console.log(this, a, b);\n        }\n        (function() {\n            foo(\"bar\");\n            bar.call(\"foo\", \"bar\");\n        })();\n    }\n    expect_stdout: true\n}\n\nunsafe_call_1: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            console.log(a, b);\n        }).call(\"foo\", \"bar\");\n        (function(a, b) {\n            console.log(this, a, b);\n        }).call(\"foo\", \"bar\");\n    }\n    expect: {\n        console.log(\"bar\", void 0);\n        (function(a, b) {\n            console.log(this, a, b);\n        }).call(\"foo\", \"bar\");\n    }\n    expect_stdout: true\n}\n\nunsafe_call_2: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        function foo() {\n            console.log(a, b);\n        }\n        var bar = function(a, b) {\n            console.log(this, a, b);\n        }\n        (function() {\n            foo.call(\"foo\", \"bar\");\n            bar.call(\"foo\", \"bar\");\n        })();\n    }\n    expect: {\n        function foo() {\n            console.log(a, b);\n        }\n        var bar = function(a, b) {\n            console.log(this, a, b);\n        }\n        (function() {\n            foo(\"bar\");\n            bar.call(\"foo\", \"bar\");\n        })();\n    }\n    expect_stdout: true\n}\n\nunsafe_call_3: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function() {\n            return arguments[0] + eval(\"arguments\")[1];\n        }.call(0, 1, 2));\n    }\n    expect: {\n        console.log(function() {\n            return arguments[0] + eval(\"arguments\")[1];\n        }(1, 2));\n    }\n    expect_stdout: \"3\"\n}\n\ninline_eval_inner: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function() {\n            console.log(typeof eval(\"arguments\"));\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(typeof eval(\"arguments\"));\n        })();\n    }\n    expect_stdout: \"object\"\n}\n\ninline_eval_outer: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        A = 42;\n        (function(a) {\n            console.log(a);\n        })(A);\n        console.log(eval(\"typeof a\"));\n    }\n    expect: {\n        A = 42;\n        (function(a) {\n            console.log(a);\n        })(A);\n        console.log(eval(\"typeof a\"));\n    }\n    expect_stdout: [\n        \"42\",\n        \"undefined\",\n    ]\n}\n\nissue_2616: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f() {\n                function g(NaN) {\n                    (true << NaN) - 0/0 || (c = \"PASS\");\n                }\n                g([]);\n            }\n            f();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (true << []) - NaN || (c = \"PASS\");\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2620_1: {\n    options = {\n        inline: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f(a) {\n                var b = function g(a) {\n                    a && a();\n                }();\n                if (a) {\n                    var d = c = \"PASS\";\n                }\n            }\n            f(1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        !function(a) {\n            if (function(a) {\n                a && a();\n            }(), a) c = \"PASS\";\n        }(1),\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2620_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f(a) {\n                var b = function g(a) {\n                    a && a();\n                }();\n                if (a) {\n                    var d = c = \"PASS\";\n                }\n            }\n            f(1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function() {\n            var a = 1;\n            if (function(a) {\n                a && a();\n            }(), a) c = \"PASS\";\n        })(),\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2620_3: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f(a) {\n                var b = function g(a) {\n                    a && a();\n                }();\n                if (a) {\n                    var d = c = \"PASS\";\n                }\n            }\n            f(1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        c = \"PASS\",\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2620_4: {\n    options = {\n        evaluate: true,\n        inline: 3,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f(a, NaN) {\n                function g() {\n                    switch (a) {\n                      case a:\n                        break;\n                      case c = \"PASS\", NaN:\n                        break;\n                    }\n                }\n                g();\n            }\n            f(0/0);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        !function(a, NaN) {\n            (function() {\n                switch (a) {\n                    case a:\n                    break;\n                    case c = \"PASS\", NaN:\n                    break;\n                }\n            })();\n        }(NaN);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2620_5: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f(a, NaN) {\n                function g() {\n                    switch (a) {\n                      case a:\n                        break;\n                      case c = \"PASS\", NaN:\n                        break;\n                    }\n                }\n                g();\n            }\n            f(0/0);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        !function(a, NaN) {\n            switch (a) {\n              case a:\n                break;\n              case c = \"PASS\", NaN:\n                break;\n            }\n        }(NaN);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2620_6: {\n    rename = true\n    options = {\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        switches: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            function f(a, NaN) {\n                function g() {\n                    switch (a) {\n                      case a:\n                        break;\n                      case c = \"PASS\", NaN:\n                        break;\n                    }\n                }\n                g();\n            }\n            f(0/0);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function() {\n            switch (NaN) {\n              case void (c = \"PASS\"):\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2630_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            while (f());\n            function f() {\n                var a = function() {\n                    var b = c++, d = c = 1 + c;\n                }();\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        while (void (c = 1 + ++c));\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2630_2: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        !function() {\n            while (f()) {}\n            function f() {\n                var not_used = function() {\n                    c = 1 + c;\n                }(c = c + 1);\n            }\n        }();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        while (void (c = 1 + (c += 1)));\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2630_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var x = 2, a = 1;\n        (function() {\n            function f1(a) {\n                f2();\n                --x >= 0 && f1({});\n            }\n            f1(a++);\n            function f2() {\n                a++;\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var x = 2, a = 1;\n        (function() {\n            (function f1(a) {\n                f2();\n                --x >= 0 && f1();\n            })(a++);\n            function f2() {\n                a++;\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"5\"\n}\n\nissue_2630_4: {\n    options = {\n        collapse_vars: true,\n        inline: 3,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var x = 3, a = 1, b = 2;\n        (function() {\n            (function f1() {\n                while (--x >= 0 && f2());\n            }());\n            function f2() {\n                a++ + (b += a);\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var x = 3, a = 1, b = 2;\n        !function() {\n            while (--x >= 0 && void (b += ++a));\n        }();\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2630_5: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var x = 3, a = 1, b = 2;\n        (function() {\n            (function f1() {\n                while (--x >= 0 && f2());\n            }());\n            function f2() {\n                a++ + (b += a);\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var x = 3, a = 1, b = 2;\n        while (--x >= 0 && void (b += ++a));\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2630_6: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var c = 1;\n        !function() {\n            do {\n                c *= 10;\n            } while (f());\n            function f() {\n                return function() {\n                    return (c = 2 + c) < 100;\n                }(c = c + 3);\n            }\n        }();\n        console.log(c);\n    }\n    expect: {\n        var c = 1;\n        !function() {\n            do {\n                c *= 10;\n            } while ((c = 2 + (c += 3)) < 100);\n        }();\n        console.log(c);\n    }\n    expect_stdout: \"155\"\n}\n\nrecursive_inline_1: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            h();\n        }\n        function g(a) {\n            a();\n        }\n        function h(b) {\n            g();\n            if (b) x();\n        }\n    }\n    expect: {}\n}\n\nrecursive_inline_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(n) {\n            return n ? n * f(n - 1) : 1;\n        }\n        console.log(f(5));\n    }\n    expect: {\n        console.log(function f(n) {\n            return n ? n * f(n - 1) : 1;\n        }(5));\n    }\n    expect_stdout: \"120\"\n}\n\nissue_2657: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function f() {\n            return h;\n            function g(b) {\n                return b || b();\n            }\n            function h(a) {\n                g(a);\n                return a;\n            }\n        }()(42));\n    }\n    expect: {\n        \"use strict\";\n        console.log(function(a) {\n            return b = a, b || b(), a;\n            var b;\n        }(42));\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2663_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var i, o = {};\n            function createFn(j) {\n                return function() {\n                    console.log(j);\n                };\n            }\n            for (i in { a: 1, b: 2, c: 3 })\n                o[i] = createFn(i);\n            for (i in o)\n                o[i]();\n        })();\n    }\n    expect: {\n        (function() {\n            var i, o = {};\n            function createFn(j) {\n                return function() {\n                    console.log(j);\n                };\n            }\n            for (i in { a: 1, b: 2, c: 3 })\n                o[i] = createFn(i);\n            for (i in o)\n                o[i]();\n        })();\n    }\n    expect_stdout: [\n        \"a\",\n        \"b\",\n        \"c\",\n    ]\n}\n\nissue_2663_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var i;\n            function fn(j) {\n                return function() {\n                    console.log(j);\n                }();\n            }\n            for (i in { a: 1, b: 2, c: 3 })\n                fn(i);\n        })();\n    }\n    expect: {\n        (function() {\n            for (var i in { a: 1, b: 2, c: 3 })\n                j = i, console.log(j);\n            var j;\n        })();\n    }\n    expect_stdout: [\n        \"a\",\n        \"b\",\n        \"c\",\n    ]\n}\n\nissue_2663_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var outputs = [\n                { type: 0, target: null, eventName: \"ngSubmit\", propName: null },\n                { type: 0, target: null, eventName: \"submit\", propName: null },\n                { type: 0, target: null, eventName: \"reset\", propName: null },\n            ];\n            function listenToElementOutputs(outputs) {\n                var handlers = [];\n                for (var i = 0; i < outputs.length; i++) {\n                    var output = outputs[i];\n                    var handleEventClosure = renderEventHandlerClosure(output.eventName);\n                    handlers.push(handleEventClosure)\n                }\n                var target, name;\n                return handlers;\n            }\n            function renderEventHandlerClosure(eventName) {\n                return function() {\n                    return console.log(eventName);\n                };\n            }\n            listenToElementOutputs(outputs).forEach(function(handler) {\n                return handler()\n            });\n        })();\n    }\n    expect: {\n        (function() {\n            function renderEventHandlerClosure(eventName) {\n                return function() {\n                    return console.log(eventName);\n                };\n            }\n            (function(outputs) {\n                var handlers = [];\n                for (var i = 0; i < outputs.length; i++) {\n                    var output = outputs[i];\n                    var handleEventClosure = renderEventHandlerClosure(output.eventName);\n                    handlers.push(handleEventClosure);\n                }\n                return handlers;\n            })([ {\n                type: 0,\n                target: null,\n                eventName: \"ngSubmit\",\n                propName: null\n            }, {\n                type: 0,\n                target: null,\n                eventName: \"submit\",\n                propName: null\n            }, {\n                type: 0,\n                target: null,\n                eventName: \"reset\",\n                propName: null\n            } ]).forEach(function(handler) {\n                return handler();\n            });\n        })();\n    }\n    expect_stdout: [\n        \"ngSubmit\",\n        \"submit\",\n        \"reset\",\n    ]\n}\n\nduplicate_argnames_1: {\n    options = {\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a, a, a) {\n            return a;\n        }(\"FAIL\", 42, \"PASS\"));\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_argnames_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(b, b, b) {\n            b && (a = \"FAIL\");\n        }\n        f(0, console);\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        console, void 0 && (a = \"FAIL\");\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_argnames_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        function f(b, b, b) {\n            b && (a = \"PASS\");\n        }\n        f(null, 0, console, \"42\".toString());\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        b = console, \"42\".toString(), b && (a = \"PASS\");\n        var b;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_argnames_4: {\n    options = {\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        (function() {\n            (function(a, a) {\n                while (console.log(a || \"PASS\"));\n            })(\"FAIL\");\n        })();\n    }\n    expect: {\n        (function() {\n            var a = \"FAIL\";\n            var a = void 0;\n            while (console.log(a || \"PASS\"));\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nloop_init_arg: {\n    options = {\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        for (var k in \"12\") (function(b) {\n            (b >>= 1) && (a = \"FAIL\"), b = 2;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        for (var k in \"12\")\n            b = void 0, (b >>= 1) && (a = \"FAIL\"), b = 2;\n        var b;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ninline_false: {\n    options = {\n        inline: false,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"3\",\n    ]\n}\n\ninline_0: {\n    options = {\n        inline: 0,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"3\",\n    ]\n}\n\ninline_1: {\n    options = {\n        inline: 1,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect: {\n        console.log(1);\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"3\",\n    ]\n}\n\ninline_2: {\n    options = {\n        inline: 2,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect: {\n        console.log(1);\n        console.log(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"3\",\n    ]\n}\n\ninline_3: {\n    options = {\n        inline: 3,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect: {\n        console.log(1);\n        console.log(2);\n        b = 3, c = b, console.log(c);\n        var b, c;\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"3\",\n    ]\n}\n\ninline_true: {\n    options = {\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            console.log(1);\n        })();\n        (function(a) {\n            console.log(a);\n        })(2);\n        (function(b) {\n            var c = b;\n            console.log(c);\n        })(3);\n    }\n    expect: {\n        console.log(1);\n        console.log(2);\n        b = 3, c = b, console.log(c);\n        var b, c;\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"3\",\n    ]\n}\n\nuse_before_init_in_loop: {\n    options = {\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        for (var b = 2; --b >= 0;) (function() {\n            var c = function() {\n                return 1;\n            }(c && (a = \"FAIL\"));\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        for (var b = 2; --b >= 0;)\n            c = void 0, c = (c && (a = \"FAIL\"), 1);\n        var c;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_arg_var_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function(b) {\n            return b;\n            var b;\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_arg_var_2: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(function(b) {\n            return b + \"SS\";\n            var b;\n        }(\"PA\"));\n    }\n    expect: {\n        console.log(\"PA\" + \"SS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nduplicate_arg_var_3: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(function(b) {\n            return b + \"SS\";\n            var b;\n        }(\"PA\", \"42\".toString()));\n    }\n    expect: {\n        console.log((b = \"PA\", \"42\".toString(), b + \"SS\"));\n        var b;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2737_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            while (a());\n        })(function f() {\n            console.log(typeof f);\n        });\n    }\n    expect: {\n        (function(a) {\n            while (a());\n        })(function f() {\n            console.log(typeof f);\n        });\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2737_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(bar) {\n            for (;bar();) break;\n        })(function qux() {\n            return console.log(\"PASS\"), qux;\n        });\n    }\n    expect: {\n        (function(bar) {\n            for (;bar();) break;\n        })(function qux() {\n            return console.log(\"PASS\"), qux;\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2783: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            return g;\n            function f(a) {\n                var b = a.b;\n                if (b) return b;\n                return a;\n            }\n            function g(o, i) {\n                while (i--) {\n                    console.log(f(o));\n                }\n            }\n        })()({ b: \"PASS\" }, 1);\n    }\n    expect: {\n        (function() {\n            return function(o,i) {\n                while (i--) console.log(f(o));\n            };\n            function f(a) {\n                var b = a.b;\n                return b || a;\n            }\n        })()({ b: \"PASS\" },1);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2898: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            while (f());\n            function f() {\n                var b = (c = 1 + c, void (c = 1 + c));\n                b && b[0];\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function() {\n            while (b = void 0, void ((b = void (c = 1 + (c = 1 + c))) && b[0]));\n            var b;\n        })(),\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\ndeduplicate_parentheses: {\n    input: {\n        ({}).a = b;\n        (({}).a = b)();\n        (function() {}).a = b;\n        ((function() {}).a = b)();\n    }\n    expect_exact: \"({}).a=b;({}.a=b)();(function(){}).a=b;(function(){}.a=b)();\"\n}\n\nissue_3016_1: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1;\n        do {\n            (function(a) {\n                return a[b];\n                var a;\n            })(3);\n        } while (0);\n        console.log(b);\n    }\n    expect: {\n        var b = 1;\n        do {\n            3[b];\n        } while (0);\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3016_2: {\n    options = {\n        dead_code: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1;\n        do {\n            (function(a) {\n                return a[b];\n                try {\n                    a = 2;\n                } catch (a) {\n                    var a;\n                }\n            })(3);\n        } while (0);\n        console.log(b);\n    }\n    expect: {\n        var b = 1;\n        do {\n            a = 3,\n            a[b];\n        } while (0);\n        var a;\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3016_2_ie8: {\n    options = {\n        dead_code: true,\n        ie: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1;\n        do {\n            (function(a) {\n                return a[b];\n                try {\n                    a = 2;\n                } catch (a) {\n                    var a;\n                }\n            })(3);\n        } while (0);\n        console.log(b);\n    }\n    expect: {\n        var b = 1;\n        do {\n            a = 3,\n            a[b];\n        } while (0);\n        var a;\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3016_3: {\n    options = {\n        dead_code: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1;\n        do {\n            console.log(function() {\n                return a ? \"FAIL\" : a = \"PASS\";\n                try {\n                    a = 2;\n                } catch (a) {\n                    var a;\n                }\n            }());\n        } while (b--);\n    }\n    expect: {\n        var b = 1;\n        do {\n            console.log((a = void 0, a ? \"FAIL\" : \"PASS\"));\n        } while (b--);\n        var a;\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_3016_3_ie8: {\n    options = {\n        dead_code: true,\n        ie: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1;\n        do {\n            console.log(function() {\n                return a ? \"FAIL\" : a = \"PASS\";\n                try {\n                    a = 2;\n                } catch (a) {\n                    var a;\n                }\n            }());\n        } while (b--);\n    }\n    expect: {\n        var b = 1;\n        do {\n            console.log((a = void 0, a ? \"FAIL\" : \"PASS\"));\n        } while (b--);\n        var a;\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_3018: {\n    options = {\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 1, c = \"PASS\";\n        do {\n            (function() {\n                (function(a) {\n                    a = 0 != (a && (c = \"FAIL\"));\n                })();\n            })();\n        } while (b--);\n        console.log(c);\n    }\n    expect: {\n        var b = 1, c = \"PASS\";\n        do {\n            a = void 0,\n            a = 0 != (a && (c = \"FAIL\"));\n        } while (b--);\n        var a;\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3054: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        inline: 1,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            return { a: true };\n        }\n        console.log(function(b) {\n            b = false;\n            return f();\n        }().a, f.call().a);\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            return { a: !0 };\n        }\n        console.log(function(b) {\n            b = !1;\n            return f();\n        }().a, f.call().a);\n    }\n    expect_stdout: \"true true\"\n}\n\nissue_3076: {\n    options = {\n        dead_code: true,\n        inline: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        var c = \"PASS\";\n        (function(b) {\n            var n = 2;\n            while (--b + function() {\n                e && (c = \"FAIL\");\n                e = 5;\n                return 1;\n                try {\n                    var a = 5;\n                } catch (e) {\n                    var e;\n                }\n            }().toString() && --n > 0);\n        })(2);\n        console.log(c);\n    }\n    expect: {\n        var c = \"PASS\";\n        (function(b) {\n            var n = 2;\n            while (--b + (e = void 0, e && (c = \"FAIL\"), e = 5, 1..toString()) && --n > 0);\n            var e;\n        })(2),\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3125: {\n    options = {\n        inline: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function() {\n            return \"PASS\";\n        }.call());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3274: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        join_vars: true,\n        loops: true,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var g = function(a) {\n                var c = a.p, b = c;\n                return b != c;\n            };\n            while (g(1))\n                console.log(\"FAIL\");\n            console.log(\"PASS\");\n        })();\n    }\n    expect: {\n        (function() {\n            for (var c; (c = 1..p) != c;)\n                console.log(\"FAIL\");\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3297_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        function function1() {\n            var r = {\n                function2: function2\n            };\n            function function2() {\n                alert(1234);\n                function function3() {\n                    function2();\n                };\n                function3();\n            }\n            return r;\n        }\n    }\n    expect: {\n        function function1() {\n            return {\n                function2: function n() {\n                    alert(1234);\n                    function t() {\n                        n();\n                    }\n                    t();\n                }\n            };\n        }\n    }\n}\n\nissue_3297_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        function function1(session) {\n            var public = {\n                processBulk: processBulk\n            };\n            return public;\n            function processBulk(bulk) {\n                var subparam1 = session();\n                function processOne(param1) {\n                    var param2 = {\n                        subparam1: subparam1\n                    };\n                    doProcessOne({\n                        param1: param1,\n                        param2: param2,\n                    }, function() {\n                        processBulk(bulk);\n                    });\n                };\n                if (bulk && bulk.length > 0)\n                    processOne(bulk.shift());\n            }\n            function doProcessOne(config, callback) {\n                console.log(JSON.stringify(config));\n                callback();\n            }\n        }\n        function1(function session() {\n            return 42;\n        }).processBulk([1, 2, 3]);\n    }\n    expect: {\n        function function1(o) {\n            return {\n                processBulk: function t(u) {\n                    var r = o();\n                    function n(n) {\n                        var o = {\n                            subparam1: r\n                        };\n                        c({\n                            param1: n,\n                            param2: o\n                        }, function() {\n                            t(u);\n                        });\n                    }\n                    u && u.length > 0 && n(u.shift());\n                }\n            };\n            function c(n, o) {\n                console.log(JSON.stringify(n));\n                o();\n            }\n        }\n        function1(function() {\n            return 42;\n        }).processBulk([ 1, 2, 3 ]);\n    }\n    expect_stdout: [\n        '{\"param1\":1,\"param2\":{\"subparam1\":42}}',\n        '{\"param1\":2,\"param2\":{\"subparam1\":42}}',\n        '{\"param1\":3,\"param2\":{\"subparam1\":42}}',\n    ]\n}\n\nissue_3297_3: {\n    options = {\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        inline: true,\n        join_vars: true,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        function function1(session) {\n            var public = {\n                processBulk: processBulk,\n            };\n            return public;\n            function processBulk(bulk) {\n                var subparam1 = session();\n                function processOne(param1) {\n                    var param2 = {\n                        subparam1: subparam1,\n                    };\n                    doProcessOne({\n                        param1: param1,\n                        param2: param2,\n                    }, function() {\n                        processBulk(bulk);\n                    });\n                };\n                if (bulk && bulk.length > 0)\n                    processOne(bulk.shift());\n            }\n            function doProcessOne(config, callback) {\n                console.log(JSON.stringify(config));\n                callback();\n            }\n        }\n        function1(function session() {\n            return 42;\n        }).processBulk([1, 2, 3]);\n    }\n    expect: {\n        function function1(c) {\n            return {\n                processBulk: function n(o) {\n                    var r, t, u = c();\n                    o && 0 < o.length && (r = o.shift(),\n                    t = function() {\n                        n(o);\n                    },\n                    console.log(JSON.stringify({\n                        param1: r,\n                        param2: {\n                            subparam1: u,\n                        },\n                    })),\n                    t());\n                },\n            };\n        }\n        function1(function() {\n            return 42;\n        }).processBulk([ 1, 2, 3 ]);\n    }\n    expect_stdout: [\n        '{\"param1\":1,\"param2\":{\"subparam1\":42}}',\n        '{\"param1\":2,\"param2\":{\"subparam1\":42}}',\n        '{\"param1\":3,\"param2\":{\"subparam1\":42}}',\n    ]\n}\n\ncross_references_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var Math = {\n            square: function(n) {\n                return n * n;\n            }\n        };\n        console.log((function(factory) {\n            return factory();\n        })(function() {\n            return function(Math) {\n                return function(n) {\n                    return Math.square(n);\n                };\n            }(Math);\n        })(3));\n    }\n    expect: {\n        var Math = {\n            square: function(n) {\n                return n * n;\n            }\n        };\n        console.log(function(Math) {\n            return function(n) {\n                return Math.square(n);\n            };\n        }(Math)(3));\n    }\n    expect_stdout: \"9\"\n}\n\ncross_references_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 6,\n        properties: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var Math = {\n            square: function(n) {\n                return n * n;\n            }\n        };\n        console.log((function(factory) {\n            return factory();\n        })(function() {\n            return function(Math) {\n                return function(n) {\n                    return Math.square(n);\n                };\n            }(Math);\n        })(3));\n    }\n    expect: {\n        console.log(9);\n    }\n    expect_stdout: \"9\"\n}\n\ncross_references_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var Math = {\n            square: function(n) {\n                return n * n;\n            },\n            cube: function(n) {\n                return n * n * n;\n            }\n        };\n        console.log(function(factory) {\n            return factory();\n        }(function() {\n            return function(Math) {\n                return function(n) {\n                    Math = {\n                        square: function(x) {\n                            return \"(SQUARE\" + x + \")\";\n                        },\n                        cube: function(x) {\n                            return \"(CUBE\" + x + \")\";\n                        }\n                    };\n                    return Math.square(n) + Math.cube(n);\n                };\n            }(Math);\n        })(2));\n        console.log(Math.square(3), Math.cube(3));\n    }\n    expect: {\n        var Math = {\n            square: function(n) {\n                return n * n;\n            },\n            cube: function(n) {\n                return n * n * n;\n            }\n        };\n        console.log(function(Math) {\n            return function(n) {\n                Math = {\n                    square: function(x) {\n                        return \"(SQUARE\" + x + \")\";\n                    },\n                    cube: function(x) {\n                        return \"(CUBE\" + x + \")\";\n                    }\n                };\n                return Math.square(n) + Math.cube(n);\n            };\n        }()(2));\n        console.log(Math.square(3), Math.cube(3));\n    }\n    expect_stdout: [\n        \"(SQUARE2)(CUBE2)\",\n        \"9 27\",\n    ]\n}\n\nloop_inline: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(o) {\n            function g(p) {\n                return o[p];\n            }\n            function h(q) {\n                while (g(q));\n            }\n            return h;\n        }([ 1, \"foo\", 0 ])(2));\n    }\n    expect: {\n        console.log(function(o) {\n            return function(q) {\n                while (p = q, o[p]);\n                var p;\n            };\n        }([ 1, \"foo\", 0 ])(2));\n    }\n    expect_stdout: \"undefined\"\n}\n\nfunctions: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a = function a() {\n                return a && \"a\";\n            };\n            var b = function x() {\n                return !!x;\n            };\n            var c = function(c) {\n                return c;\n            };\n            if (c(b(a()))) {\n                var d = function() {};\n                var e = function y() {\n                    return typeof y;\n                };\n                var f = function(f) {\n                    return f;\n                };\n                console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);\n            }\n        }();\n    }\n    expect: {\n        !function() {\n            function a() {\n                return a && \"a\";\n            }\n            function b() {\n                return !!b;\n            }\n            function c(c) {\n                return c;\n            }\n            if (c(b(a()))) {\n                function d() {}\n                function e() {\n                    return typeof e;\n                }\n                function f(f) {\n                    return f;\n                }\n                console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);\n            }\n        }();\n    }\n    expect_stdout: \"a true 42 function function function\"\n}\n\nfunctions_use_strict: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        !function() {\n            var a = function a() {\n                return a && \"a\";\n            };\n            var b = function x() {\n                return !!x;\n            };\n            var c = function(c) {\n                return c;\n            };\n            if (c(b(a()))) {\n                var d = function() {};\n                var e = function y() {\n                    return typeof y;\n                };\n                var f = function(f) {\n                    return f;\n                };\n                console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);\n            }\n        }();\n    }\n    expect: {\n        \"use strict\";\n        !function() {\n            function a() {\n                return a && \"a\";\n            }\n            function b() {\n                return !!b;\n            }\n            function c(c) {\n                return c;\n            }\n            if (c(b(a()))) {\n                var d = function() {};\n                var e = function y() {\n                    return typeof y;\n                };\n                var f = function(f) {\n                    return f;\n                };\n                console.log(a(d()), b(e()), c(f(42)), typeof d, e(), typeof f);\n            }\n        }();\n    }\n    expect_stdout: \"a true 42 function function function\"\n}\n\nfunctions_cross_scope_reference: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        log = function(fn) {\n            console.log(typeof fn());\n        };\n        var a = function() {};\n        function f() {\n            return a;\n        }\n        while (log(f));\n    }\n    expect: {\n        log = function(fn) {\n            console.log(typeof fn());\n        };\n        function a() {}\n        function f() {\n            return a;\n        }\n        while (log(f));\n    }\n    expect_stdout: \"function\"\n}\n\nfunctions_inner_var: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function() {\n            var a;\n            console.log(a, a);\n        };\n        a(a);\n    }\n    expect: {\n        function a() {\n            var a;\n            console.log(a, a);\n        }\n        a();\n    }\n    expect_stdout: \"undefined undefined\"\n}\n\nfunctions_keep_fnames: {\n    options = {\n        functions: true,\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var FAIL = function PASS() {};\n        FAIL.p = 42;\n        console.log(FAIL.name, FAIL.p);\n    }\n    expect: {\n        var FAIL = function PASS() {};\n        FAIL.p = 42;\n        console.log(FAIL.name, FAIL.p);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nissue_2437: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        functions: true,\n        if_return: true,\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            return bar();\n        }\n        function bar() {\n            if (xhrDesc) {\n                var req = new XMLHttpRequest();\n                var result = !!req.onreadystatechange;\n                Object.defineProperty(XMLHttpRequest.prototype, 'onreadystatechange', xhrDesc || {});\n                return result;\n            } else {\n                var req = new XMLHttpRequest();\n                var detectFunc = function(){};\n                req.onreadystatechange = detectFunc;\n                var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;\n                req.onreadystatechange = null;\n                return result;\n            }\n        }\n        console.log(foo());\n    }\n    expect: {\n        var req, detectFunc, result;\n        console.log((\n            xhrDesc ? (\n                result = !!(req = new XMLHttpRequest).onreadystatechange,\n                Object.defineProperty(XMLHttpRequest.prototype, \"onreadystatechange\", xhrDesc || {})\n            ) : (\n                (req = new XMLHttpRequest).onreadystatechange = detectFunc = function(){},\n                result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc,req.onreadystatechange = null\n            ),\n            result\n        ));\n    }\n}\n\nissue_2485_1: {\n    options = {\n        functions: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var foo = function(bar) {\n            var n = function(a, b) {\n                return a + b;\n            };\n            var sumAll = function(arg) {\n                return arg.reduce(n, 0);\n            };\n            var runSumAll = function(arg) {\n                return sumAll(arg);\n            };\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect: {\n        var foo = function(bar) {\n            function n(a, b) {\n                return a + b;\n            }\n            function runSumAll(arg) {\n                return function(arg) {\n                    return arg.reduce(n, 0);\n                }(arg);\n            }\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect_stdout: \"6\"\n}\n\nissue_2485_2: {\n    options = {\n        functions: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var foo = function(bar) {\n            var n = function(a, b) {\n                return a + b;\n            };\n            var sumAll = function(arg) {\n                return arg.reduce(n, 0);\n            };\n            var runSumAll = function(arg) {\n                return sumAll(arg);\n            };\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect: {\n        var foo = function(bar) {\n            function n(a, b) {\n                return a + b;\n            }\n            function runSumAll(arg) {\n                return arg.reduce(n, 0);\n            }\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect_stdout: \"6\"\n}\n\nissue_3364: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var s = 2, a = 100, b = 10, c = 0;\n        function f(p, e, r) {\n            try {\n                for (var i = 1; i-- > 0;)\n                    var a = function(x) {\n                        function g(y) {\n                            y && y[a++];\n                        }\n                        var x = g(--s >= 0 && f(c++));\n                        for (var j = 1; --j > 0;);\n                    }();\n            } catch (e) {\n                try {\n                    return;\n                } catch (z) {\n                    for (var k = 1; --k > 0;) {\n                        for (var l = 1; l > 0; --l) {\n                            var n = function() {};\n                            for (var k in n)\n                                var o = (n, k);\n                        }\n                    }\n                }\n            }\n        }\n        var r = f();\n        console.log(c);\n    }\n    expect: {\n        var s = 2, c = 0;\n        (function n(r, o, a) {\n            try {\n                for (var f = 1; f-- >0;)\n                    var t = function(r) {\n                        (function(r) {\n                            r && r[t++];\n                        })(--s >= 0 && n(c++));\n                        for (var o = 1; --o > 0;);\n                    }();\n            } catch (o) {\n                try {\n                    return;\n                } catch (r) {\n                    for (var v = 1; --v > 0;)\n                        for (var i = 1; i > 0;--i) {\n                            function u() {}\n                            for (var v in u);\n                        }\n                }\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_3366: {\n    options = {\n        functions: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                return function() {};\n            }\n            var a = g();\n            (function() {\n                this && a && console.log(\"PASS\");\n            })();\n        }\n        f();\n    }\n    expect: {\n        void function() {\n            this && a && console.log(\"PASS\");\n        }();\n        function a() {}\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3371: {\n    options = {\n        functions: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = function f() {\n                (function() {\n                    console.log(typeof f);\n                })();\n            };\n            while (a());\n        })();\n    }\n    expect: {\n        (function() {\n            function a() {\n                console.log(typeof a);\n            }\n            while (a());\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nclass_iife: {\n    options = {\n        inline: true,\n        sequences: true,\n        toplevel: true,\n    }\n    input: {\n        var A = function() {\n            function B() {}\n            B.prototype.m = function() {\n                console.log(\"PASS\");\n            };\n            return B;\n        }();\n        new A().m();\n    }\n    expect: {\n        var A = (B.prototype.m = function() {\n            console.log(\"PASS\");\n        }, B);\n        function B() {}\n        new A().m();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3400_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(f) {\n            console.log(f()()[0].p);\n        })(function() {\n            function g() {\n                function h(u) {\n                    var o = {\n                        p: u\n                    };\n                    return console.log(o[g]), o;\n                }\n                function e() {\n                    return [ 42 ].map(function(v) {\n                        return h(v);\n                    });\n                }\n                return e();\n            }\n            return g;\n        });\n    }\n    expect: {\n        void console.log(function g() {\n            function h(u) {\n                var o = {\n                    p: u\n                };\n                return console.log(o[g]), o;\n            }\n            function e() {\n                return [ 42 ].map(h);\n            }\n            return e();\n        }()[0].p);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"42\",\n    ]\n}\n\nissue_3400_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(f) {\n            console.log(f()()[0].p);\n        })(function() {\n            function g() {\n                function h(u) {\n                    var o = {\n                        p: u\n                    };\n                    return console.log(o[g]), o;\n                }\n                function e() {\n                    return [ 42 ].map(function(v) {\n                        return h(v);\n                    });\n                }\n                return e();\n            }\n            return g;\n        });\n    }\n    expect: {\n        void console.log(function g() {\n            return [ 42 ].map(function(u) {\n                var o = {\n                    p: u\n                };\n                return console.log(o[g]), o;\n            });\n        }()[0].p);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"42\",\n    ]\n}\n\nissue_3402: {\n    options = {\n        evaluate: true,\n        functions: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        var f = function f() {\n            f = 42;\n            console.log(typeof f);\n        };\n        \"function\" == typeof f && f();\n        \"function\" == typeof f && f();\n        console.log(typeof f);\n    }\n    expect: {\n        var f = function f() {\n            f = 42;\n            console.log(typeof f);\n        };\n        f();\n        f();\n        console.log(typeof f);\n    }\n    expect_stdout: [\n        \"function\",\n        \"function\",\n        \"function\",\n    ]\n}\n\nissue_3439_1: {\n    options = {\n        inline: 3,\n    }\n    input: {\n        console.log(typeof function() {\n            return function(a) {\n                function a() {}\n                return a;\n            }(42);\n        }());\n    }\n    expect: {\n        console.log(typeof function(a) {\n            function a() {}\n            return a;\n        }(42));\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3439_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(typeof function() {\n            return function(a) {\n                function a() {}\n                return a;\n            }(42);\n        }());\n    }\n    expect: {\n        console.log(typeof function(a) {\n            function a() {}\n            return a;\n        }(42));\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3444: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(h) {\n            return f;\n            function f() {\n                g();\n            }\n            function g() {\n                h(\"PASS\");\n            }\n        })(console.log)();\n    }\n    expect: {\n        (function(h) {\n            return function() {\n                void h(\"PASS\");\n            };\n        })(console.log)();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3506_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b) {\n            (function(b) {\n                b && (a = \"PASS\");\n            })(b);\n        })(a);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        !function(b) {\n            b && (a = \"PASS\");\n        }(a);\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3506_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: 3,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b) {\n            (function(c) {\n                var d = 1;\n                for (;c && (a = \"PASS\") && 0 < --d;);\n            })(b);\n        })(a);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        !function(c) {\n            var d = 1;\n            for (;c && (a = \"PASS\") && 0 < --d;);\n        }(a);\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3506_3: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b) {\n            (function(c) {\n                var d = 1;\n                for (;c && (a = \"PASS\") && 0 < --d;);\n            })(b);\n        })(a);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function(b) {\n            var c = a;\n            var d = 1;\n            for (;c && (a = \"PASS\") && 0 < --d;);\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3506_4: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        evaluate: true,\n        inline: 3,\n        loops: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b) {\n            (function(c) {\n                var d = 1;\n                for (;c && (a = \"PASS\") && 0 < --d;);\n            })(b);\n        })(a);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        !function(c) {\n            var d = 1;\n            for (;c && (a = \"PASS\") && 0 < --d;);\n        }(a);\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3506_5: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        loops: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function(b) {\n            (function(c) {\n                var d = 1;\n                for (;c && (a = \"PASS\") && 0 < --d;);\n            })(b);\n        })(a);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function(b) {\n            var c = a;\n            var d = 1;\n            for (;c && (a = \"PASS\") && 0 < --d;);\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3512: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(b) {\n            (function() {\n                b <<= this || 1;\n                b.a = \"FAIL\";\n            })();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(b) {\n            (function() {\n                (b <<= this || 1).a = \"FAIL\";\n            })();\n        })(),\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3562: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(b) {\n            f = function() {\n                console.log(b);\n            };\n            return \"FAIL\";\n        }\n        a = f(a);\n        f(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        function f(b) {\n            f = function() {\n                console.log(b);\n            };\n            return \"FAIL\";\n        }\n        a = f(a);\n        f(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nhoisted_inline: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(\"PASS\");\n        }\n        function g() {\n            for (var console in [ 0 ])\n                h();\n        }\n        function h() {\n            f();\n        }\n        g();\n    }\n    expect: {\n        function f() {\n            console.log(\"PASS\");\n        }\n        (function() {\n            for (var console in [ 0 ])\n                void f();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nhoisted_single_use: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            for (var r in a) g(r);\n        }\n        function g(a) {\n            console.log(a);\n        }\n        function h(a) {\n            var g = a.bar;\n            g();\n            g();\n            i(a);\n        }\n        function i(b) {\n            f(b);\n        }\n        h({\n            bar: function() {\n                console.log(\"foo\");\n            }\n        });\n    }\n    expect: {\n        function f(a) {\n            for (var r in a) (function(a) {\n                console.log(a);\n            })(r);\n        }\n        (function(a) {\n            var g = a.bar;\n            g();\n            g();\n            (function(b) {\n                f(b);\n            })(a);\n        })({\n            bar: function() {\n                console.log(\"foo\");\n            }\n        });\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ninlined_single_use: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(f) {\n            f();\n        }(function() {\n            var a = function() {\n                A;\n            };\n            var b = function() {\n                a(B);\n            };\n            (function() {\n                b;\n            });\n            var c = 42;\n        }));\n    }\n    expect: {\n        console.log(function(f) {\n            a = function() {\n                A;\n            },\n            b = function() {\n                a(B);\n            },\n            void 0;\n            var a, b;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\npr_3592_1: {\n    options = {\n        inline: true,\n        reduce_funcs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function problem(w) {\n            return g.indexOf(w);\n        }\n        function unused(x) {\n            return problem(x);\n        }\n        function B(problem) {\n            return g[problem];\n        }\n        function A(y) {\n            return problem(y);\n        }\n        function main(z) {\n            return B(A(z));\n        }\n        var g = [ \"PASS\" ];\n        console.log(main(\"PASS\"));\n    }\n    expect: {\n        function problem(w) {\n            return g.indexOf(w);\n        }\n        function B(problem) {\n            return g[problem];\n        }\n        var g = [ \"PASS\" ];\n        console.log((z = \"PASS\", B((y = z, problem(y)))));\n        var z, y;\n    }\n    expect_stdout: \"PASS\"\n}\n\npr_3592_2: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function problem(w) {\n            return g.indexOf(w);\n        }\n        function unused(x) {\n            return problem(x);\n        }\n        function B(problem) {\n            return g[problem];\n        }\n        function A(y) {\n            return problem(y);\n        }\n        function main(z) {\n            return B(A(z));\n        }\n        var g = [ \"PASS\" ];\n        console.log(main(\"PASS\"));\n    }\n    expect: {\n        function problem(w) {\n            return g.indexOf(w);\n        }\n        var g = [ \"PASS\" ];\n        console.log((z = \"PASS\", function(problem) {\n            return g[problem];\n        }(problem(z))));\n        var z;\n    }\n    expect_stdout: \"PASS\"\n}\n\ninline_use_strict: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            \"use strict\";\n            return function() {\n                \"use strict\";\n                var a = \"foo\";\n                a += \"bar\";\n                return a;\n            };\n        }()());\n    }\n    expect: {\n        console.log(\"foobar\");\n    }\n    expect_stdout: \"foobar\"\n}\n\npr_3595_1: {\n    options = {\n        collapse_vars: false,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var g = [ \"PASS\" ];\n        function problem(arg) {\n            return g.indexOf(arg);\n        }\n        function unused(arg) {\n            return problem(arg);\n        }\n        function a(arg) {\n            return problem(arg);\n        }\n        function b(problem) {\n            return g[problem];\n        }\n        function c(arg) {\n            return b(a(arg));\n        }\n        console.log(c(\"PASS\"));\n    }\n    expect: {\n        var g = [ \"PASS\" ];\n        function problem(arg) {\n            return g.indexOf(arg);\n        }\n        console.log((arg = \"PASS\", function(problem) {\n            return g[problem];\n        }(problem(arg))));\n        var arg;\n    }\n    expect_stdout: \"PASS\"\n}\n\npr_3595_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var g = [ \"PASS\" ];\n        function problem(arg) {\n            return g.indexOf(arg);\n        }\n        function unused(arg) {\n            return problem(arg);\n        }\n        function a(arg) {\n            return problem(arg);\n        }\n        function b(problem) {\n            return g[problem];\n        }\n        function c(arg) {\n            return b(a(arg));\n        }\n        console.log(c(\"PASS\"));\n    }\n    expect: {\n        var g = [ \"PASS\" ];\n        function problem(arg) {\n            return g.indexOf(arg);\n        }\n        console.log(function(problem) {\n            return g[problem];\n        }(problem(\"PASS\")));\n    }\n    expect_stdout: \"PASS\"\n}\n\npr_3595_3: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var g = [ \"PASS\" ];\n        function problem(arg) {\n            return g.indexOf(arg);\n        }\n        function unused(arg) {\n            return problem(arg);\n        }\n        function a(arg) {\n            return problem(arg);\n        }\n        function b(problem) {\n            return g[problem];\n        }\n        function c(arg) {\n            return b(a(arg));\n        }\n        console.log(c(\"PASS\"));\n    }\n    expect: {\n        var g = [ \"PASS\" ];\n        console.log(function(problem) {\n            return g[problem];\n        }(g.indexOf(\"PASS\")));\n    }\n    expect_stdout: \"PASS\"\n}\n\npr_3595_4: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var g = [ \"PASS\" ];\n        function problem(arg) {\n            return g.indexOf(arg);\n        }\n        function unused(arg) {\n            return problem(arg);\n        }\n        function a(arg) {\n            return problem(arg);\n        }\n        function b(problem) {\n            return g[problem];\n        }\n        function c(arg) {\n            return b(a(arg));\n        }\n        console.log(c(\"PASS\"));\n    }\n    expect: {\n        var g = [ \"PASS\" ];\n        console.log((problem = g.indexOf(\"PASS\"), g[problem]));\n        var problem;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3679_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var f = function() {};\n            f.g = function() {\n                console.log(\"PASS\");\n            };\n            f.g();\n        })();\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3679_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            \"use strict\";\n            var f = function() {};\n            f.g = function() {\n                console.log(\"PASS\");\n            };\n            f.g();\n        })();\n    }\n    expect: {\n        (function() {\n            \"use strict\";\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3679_3: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        functions: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var f = function() {};\n            f.p = \"PASS\";\n            f.g = function() {\n                console.log(f.p);\n            };\n            f.g();\n        })();\n    }\n    expect: {\n        (function() {\n            function f() {};\n            f.p = \"PASS\";\n            (f.g = function() {\n                console.log(f.p);\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\npreceding_side_effects: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function(a, b, c) {\n            return b;\n        }(console, \"PASS\", 42));\n    }\n    expect: {\n        console.log((console, 42, \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\ntrailing_side_effects: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function(a, b, c) {\n            return b;\n        }(42, \"PASS\", console));\n    }\n    expect: {\n        console.log(function(a, b, c) {\n            return b;\n        }(42, \"PASS\", console));\n    }\n    expect_stdout: \"PASS\"\n}\n\npreserve_binding_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var o = {\n            f: function() {\n                return this === o ? \"FAIL\" : \"PASS\";\n            },\n        };\n        console.log(function(a) {\n            return a;\n        }(o.f)());\n    }\n    expect: {\n        var o = {\n            f: function() {\n                return this === o ? \"FAIL\" : \"PASS\";\n            },\n        };\n        console.log((0, o.f)());\n    }\n    expect_stdout: \"PASS\"\n}\n\npreserve_binding_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            f: function() {\n                return this === o ? \"FAIL\" : \"PASS\";\n            },\n        };\n        console.log(function(a) {\n            return a;\n        }(o.f)());\n    }\n    expect: {\n        var o = {\n            f: function() {\n                return this === o ? \"FAIL\" : \"PASS\";\n            },\n        };\n        console.log((0, o.f)());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3770: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f(a, a) {\n                var b = function() {\n                    return a || \"PASS\";\n                }();\n                console.log(b);\n            }\n            f(\"FAIL\");\n        })();\n    }\n    expect: {\n        (function() {\n            b = a || \"PASS\",\n            console.log(b);\n            var a, b;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3771: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            function f(a) {\n                var a = f(1234);\n            }\n            f();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function f(a) {\n                f();\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3772: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return a;\n        }\n        var b = f();\n        function g() {\n            console.log(f());\n        }\n        g();\n    }\n    expect: {\n        var a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3777_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            ff && ff(NaN);\n            function ff(a) {\n                var a = console.log(\"PASS\");\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            ff && ff(NaN);\n            function ff(a) {\n                var a = console.log(\"PASS\");\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3777_2: {\n    options = {\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        ff(ff.p);\n        function ff(a) {\n            var a = console.log(\"PASS\");\n        }\n    }\n    expect: {\n        ff(ff.p);\n        function ff(a) {\n            var a = console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3821_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var a = 0;\n        console.log(function(b) {\n            return +a + b;\n        }(--a));\n    }\n    expect: {\n        var a = 0;\n        console.log(function(b) {\n            return +a + b;\n        }(--a));\n    }\n    expect_stdout: \"-2\"\n}\n\nissue_3821_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(g, b) {\n            return g(), b;\n        }\n        console.log(f(function() {\n            a = \"FAIL\";\n        }, a));\n    }\n    expect: {\n        var a = \"PASS\";\n        function f(g, b) {\n            return g(), b;\n        }\n        console.log(f(function() {\n            a = \"FAIL\";\n        }, a));\n    }\n    expect_stdout: \"PASS\"\n}\n\nsubstitute: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {};\n        function f(a) {\n            return a === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect: {\n        var o = {};\n        function f(a) {\n            return a === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return f;\n            },\n            function() {\n                \"use strict\";\n                return f;\n            },\n            function() {\n                return f;\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect_stdout: [\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 2\",\n    ]\n}\n\nsubstitute_add_farg_1: {\n    options = {\n        inline: 3,\n        keep_fargs: false,\n    }\n    input: {\n        function f(g) {\n            console.log(g.length);\n            g(null, \"FAIL\");\n        }\n        f(function() {\n            return function(a, b) {\n                return function(c) {\n                    do {\n                        console.log(\"PASS\");\n                    } while (c);\n                }(a, b);\n            };\n        }());\n    }\n    expect: {\n        function f(g) {\n            console.log(g.length);\n            g(null, \"FAIL\");\n        }\n        f(function(c, argument_1) {\n            do {\n                console.log(\"PASS\");\n            } while (c);\n        });\n    }\n    expect_stdout: [\n        \"2\",\n        \"PASS\",\n    ]\n}\n\nsubstitute_add_farg_2: {\n    options = {\n        if_return: true,\n        inline: true,\n        keep_fargs: false,\n        side_effects: true,\n    }\n    input: {\n        function f(g) {\n            console.log(g.length);\n            g(null, \"FAIL\");\n        }\n        f(function() {\n            return function(a, b) {\n                return function(c) {\n                    do {\n                        console.log(\"PASS\");\n                    } while (c);\n                }(a, b);\n            };\n        }());\n    }\n    expect: {\n        function f(g) {\n            console.log(g.length);\n            g(null, \"FAIL\");\n        }\n        f(function(a, b) {\n            var c = a;\n            do {\n                console.log(\"PASS\");\n            } while (c);\n        });\n    }\n    expect_stdout: [\n        \"2\",\n        \"PASS\",\n    ]\n}\n\nsubstitute_arguments: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {};\n        function f(a) {\n            return arguments[0] === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect: {\n        var o = {};\n        function f(a) {\n            return arguments[0] === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect_stdout: [\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 2\",\n    ]\n}\n\nsubstitute_drop_farg: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {};\n        function f(a) {\n            return a === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o));\n        });\n    }\n    expect: {\n        var o = {};\n        function f(a) {\n            return a === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return f;\n            },\n            function() {\n                \"use strict\";\n                return f;\n            },\n            function() {\n                return f;\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o));\n        });\n    }\n    expect_stdout: [\n        \"PASS PASS\",\n        \"PASS PASS\",\n        \"PASS PASS\",\n        \"PASS PASS\",\n        \"PASS PASS\",\n    ]\n}\n\nsubstitute_this: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {};\n        function f(a) {\n            return a === o ? this === o : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect: {\n        var o = {};\n        function f(a) {\n            return a === o ? this === o : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect_stdout: [\n        \"false true 1\",\n        \"false false 1\",\n        \"false false 1\",\n        \"false false 1\",\n        \"false false 2\",\n    ]\n}\n\nsubstitute_use_strict: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {};\n        function f(a) {\n            \"use strict\";\n            return a === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return function(b) {\n                    return f(b);\n                };\n            },\n            function() {\n                \"use strict\";\n                return function(c) {\n                    return f(c);\n                };\n            },\n            function() {\n                return function(c) {\n                    \"use strict\";\n                    return f(c);\n                };\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect: {\n        var o = {};\n        function f(a) {\n            \"use strict\";\n            return a === o ? \"PASS\" : \"FAIL\";\n        }\n        [\n            function() {\n                return f;\n            },\n            function() {\n                return f;\n            },\n            function() {\n                \"use strict\";\n                return f;\n            },\n            function() {\n                return f;\n            },\n            function() {\n                return function(d, e) {\n                    return f(d, e);\n                };\n            },\n        ].forEach(function(g) {\n            console.log(g()(o), g().call(o, o), g().length);\n        });\n    }\n    expect_stdout: [\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 1\",\n        \"PASS PASS 2\",\n    ]\n}\n\nsubstitute_assignment: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        properties: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b, c) {\n            a[b] = c;\n        }\n        var o = {};\n        f(o, 42, null);\n        f(o, \"foo\", \"bar\");\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {};\n        o[42] = null;\n        o.foo = \"bar\";\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"42 null\",\n        \"foo bar\",\n    ]\n}\n\nissue_3833_1: {\n    options = {\n        inline: 3,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            return function() {\n                while (a);\n                console.log(\"PASS\");\n            }();\n        }\n        f();\n    }\n    expect: {\n        (function() {\n            while (a);\n            console.log(\"PASS\");\n        })();\n        var a;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3833_2: {\n    options = {\n        if_return: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            return function() {\n                while (a);\n                console.log(\"PASS\");\n            }();\n        }\n        f();\n    }\n    expect: {\n        var a = void 0;\n        while (a);\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3835: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function f() {\n            return function() {\n                return f();\n            }();\n        })();\n    }\n    expect: {\n        (function f() {\n            return f();\n        })();\n    }\n    expect_stdout: RangeError(\"Maximum call stack size exceeded\")\n}\n\nissue_3836_1: {\n    options = {\n        inline: 3,\n    }\n    input: {\n        (function() {\n            return function() {\n                for (var a in 0)\n                    console.log(k);\n            }(console.log(\"PASS\"));\n        })();\n    }\n    expect: {\n        (function() {\n            for (var a in 0)\n                console.log(k);\n        })(console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3836_2: {\n    options = {\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                for (var a in 0)\n                    console.log(k);\n            }(console.log(\"PASS\"));\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(\"PASS\");\n            for (var a in 0)\n                console.log(k);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3852: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            return function(b) {\n                return b && (b[0] = 0), \"PASS\";\n            }(a);\n        }(42));\n    }\n    expect: {\n        console.log(function(a) {\n            return a && (a[0] = 0), \"PASS\";\n        }(42));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3911: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return function() {\n                if (a) (a++, b += a);\n                f();\n            };\n        }\n        var a = f, b;\n        console.log(\"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3929: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var abc = function f() {\n                (function() {\n                    switch (f) {\n                      default:\n                        var abc = 0;\n                      case 0:\n                        abc.p;\n                    }\n                    console.log(typeof f);\n                })();\n            };\n            typeof abc && abc();\n        })();\n    }\n    expect: {\n        (function() {\n            var abc = function f() {\n                (function() {\n                    switch (f) {\n                      default:\n                        var abc = 0;\n                      case 0:\n                        abc.p;\n                    }\n                    console.log(typeof f);\n                })();\n            };\n            typeof abc && abc();\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4006: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            (function(b, c) {\n                for (var k in console.log(c), 0)\n                    return b += 0;\n            })(0, --a);\n            return a ? 0 : --a;\n        })();\n    }\n    expect: {\n        var a = 0;\n        (function(c) {\n            for (var k in console.log(c), 0)\n                return;\n        })(--a), a || --a;\n    }\n    expect_stdout: \"-1\"\n}\n\nissue_4155: {\n    options = {\n        functions: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            (function() {\n                console.log(a);\n            })(a);\n            var b = function() {};\n            b && console.log(typeof b);\n        })();\n    }\n    expect: {\n        (function() {\n            var a;\n            void console.log(a);\n            function b() {}\n            b && console.log(typeof b);\n        })();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"function\",\n    ]\n}\n\nissue_4159: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42, c = function(b) {\n            (b = a) && console.log(a++, b);\n        }(c = a);\n    }\n    expect: {\n        var a = 42;\n        (b = a) && console.log(a++, b);\n        var b;\n    }\n    expect_stdout: \"42 42\"\n}\n\ndirect_inline: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            function g(c) {\n                return c >> 1;\n            }\n            return g(a) + g(b);\n        }\n        console.log(f(13, 31));\n    }\n    expect: {\n        function f(a, b) {\n            return (a >> 1) + (b >> 1);\n        }\n        console.log(f(13, 31));\n    }\n    expect_stdout: \"21\"\n}\n\ndirect_inline_catch_redefined: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        function f() {\n            return a;\n        }\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n            console.log(a, f(), g());\n        }\n        console.log(a, f(), g());\n    }\n    expect: {\n        var a = 1;\n        function f() {\n            return a;\n        }\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n            console.log(a, f(), g());\n        }\n        console.log(a, a, g());\n    }\n    expect_stdout: true\n}\n\nstatement_var_inline: {\n    options = {\n        inline: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            (function() {\n                var a = {};\n                function g() {\n                    a.p;\n                }\n                g(console.log(\"PASS\"));\n                var b = function h(c) {\n                    c && c.q;\n                }();\n            })();\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            var c, a = {};\n            function g() {\n                a.p;\n            }\n            g(console.log(\"PASS\"));\n            c && c.q;\n            return;\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4171_1: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                while (a)\n                    var e = function() {};\n            } catch (e) {\n                return function() {\n                    return e;\n                };\n            }\n        }(!console));\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                while (a)\n                    var e = function() {};\n            } catch (e) {\n                return function() {\n                    return e;\n                };\n            }\n        }(!console));\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4171_2: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                while (a);\n            } catch (e) {\n                return function() {\n                    return e;\n                };\n            } finally {\n                var e = function() {};\n            }\n        }(!console));\n    }\n    expect: {\n        console.log(function(a) {\n            try {\n                while (a);\n            } catch (e) {\n                return function() {\n                    return e;\n                };\n            } finally {\n                function e() {}\n            }\n        }(!console));\n    }\n    expect_stdout: \"undefined\"\n}\n\ncatch_defun: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (a) {\n            function f() {\n                return typeof a;\n            }\n        }\n        console.log(f());\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (o) {\n            function t() {\n                return typeof o;\n            }\n        }\n        console.log(t());\n    }\n    expect_stdout: true\n}\n\ncatch_no_argname: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return a;\n        }\n        try {\n            throw a;\n        } catch {\n            function g() {\n                return a;\n            }\n            console.log(a, f(), g());\n        }\n        console.log(a, f(), g());\n    }\n    expect: {\n        var a = \"PASS\";\n        try {\n            throw a;\n        } catch {\n            function g() {\n                return a;\n            }\n            console.log(a, a, g());\n        }\n        console.log(a, a, g());\n    }\n    expect_stdout: [\n        \"PASS PASS PASS\",\n        \"PASS PASS PASS\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_4186: {\n    options = {\n        conditionals: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            return function() {\n                function f() {\n                    if (1)\n                        g();\n                    else\n                        (function() {\n                            return f;\n                        });\n                }\n                return f;\n                function g() {\n                    if (1) {\n                        if (0)\n                            h;\n                        else\n                            h();\n                        var key = 0;\n                    }\n                }\n                function h() {\n                    return factory;\n                }\n            };\n        }()());\n    }\n    expect: {\n        console.log(typeof function() {\n            return function f() {\n                1 ? void (1 && (0 ? h : h(), 0)) : function() {\n                    return f;\n                };\n            };\n            function h() {\n                return factory;\n            }\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4233: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            try {\n                var a = function() {};\n                try {\n                    throw 42;\n                } catch (a) {\n                    (function() {\n                        console.log(typeof a);\n                    })();\n                    var a;\n                }\n            } catch (e) {}\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                var a = function() {};\n                try {\n                    throw 42;\n                } catch (a) {\n                    (function() {\n                        console.log(typeof a);\n                    })();\n                    var a;\n                }\n            } catch (e) {}\n        })();\n    }\n    expect_stdout: \"number\"\n}\n\nissue_4259: {\n    options = {\n        collapse_vars: true,\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function b() {\n            var c = b;\n            for (b in c);\n        };\n        a();\n        console.log(typeof a);\n    }\n    expect: {\n        var a = function b() {\n            for (b in b);\n        }\n        a();\n        console.log(typeof a);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4261: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (e) {\n            (function() {\n                function f() {\n                    e.p;\n                }\n                function g() {\n                    while (f());\n                }\n                (function() {\n                    while (console.log(g()));\n                })();\n            })();\n        }\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (e) {\n            function g() {\n                // `ReferenceError: e is not defined` on Node.js v4-\n                while (void e.p);\n            }\n            while (console.log(g()));\n        }\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4265: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        inline: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            console;\n            if ([ function() {\n                return this + console.log(a);\n                a;\n                var a;\n            }() ]);\n            return 42;\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            var a;\n            return console, console.log(a), 42;\n        }\n        console.log(f());\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"42\",\n    ]\n}\n\ntrailing_comma: {\n    input: {\n        new function(a, b,) {\n            console.log(b, a,);\n        }(42, \"PASS\",);\n    }\n    expect_exact: 'new function(a,b){console.log(b,a)}(42,\"PASS\");'\n    expect_stdout: \"PASS 42\"\n}\n\nissue_4451: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            for (f in \"foo\")\n                return f;\n        };\n        while (console.log(typeof a()));\n    }\n    expect: {\n        var a = function f() {\n            for (f in \"foo\")\n                return f;\n        };\n        while (console.log(typeof a()));\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4471: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        f(f());\n        function f() {\n            return g();\n        }\n        function g() {\n            {\n                console.log(\"PASS\");\n            }\n        }\n    }\n    expect: {\n        f(g());\n        function f() {\n            return g();\n        }\n        function g() {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_4612_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function f() {\n                return g();\n            }\n            function g(a) {\n                return a || f();\n            }\n            return g(\"PASS\");\n        }());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4612_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function fn() {\n                return h();\n            }\n            function g() {\n                return fn();\n            }\n            function h(a) {\n                return a || fn();\n            }\n            return h(\"PASS\");\n        }());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4612_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(typeof function() {\n            return g();\n            function f() {\n                return g;\n            }\n            function g() {\n                {\n                    return f;\n                }\n            }\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            return g();\n            function f() {\n                return g;\n            }\n            function g() {\n                return f;\n            }\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4612_4: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            function f() {\n                return h();\n            }\n            function g() {\n                {\n                    return h();\n                }\n            }\n            function h() {\n                {\n                    return g();\n                }\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            function f() {\n                h();\n            }\n            function g() {\n                return h();\n            }\n            function h() {\n                return g();\n            }\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4655: {\n    options = {\n        functions: true,\n        loops: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function f() {\n            while (console.log(\"PASS\")) {\n                var g = function() {};\n                for (var a in g)\n                    g();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            for (; console.log(\"PASS\");) {\n                function g() {};\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4659_1: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            function f() {\n                return a++;\n            }\n            (function() {\n                f && f();\n                (function() {\n                    var a = console && a;\n                })();\n            })();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function() {\n            function f() {\n                return a++;\n            }\n            f && a++;\n            (function() {\n                var a = console && a;\n            })();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4659_2: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            function f() {\n                return a++;\n            }\n            (function() {\n                (function() {\n                    f && f();\n                })();\n                (function() {\n                    var a = console && a;\n                })();\n            })();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function() {\n            function f() {\n                return a++;\n            }\n            void (f && a++);\n            (function() {\n                var a = console && a;\n            })();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4659_3: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function() {\n            function f() {\n                return a++;\n            }\n            (function() {\n                function g() {\n                    while (!console);\n                }\n                g(f && f());\n                (function() {\n                    var a = console && a;\n                })();\n            })();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function() {\n            function f() {\n                return a++;\n            }\n            f && a++;\n            while (!console);\n            (function() {\n                var a = console && a;\n            })();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nblock_scope_1: {\n    input: {\n        console.log(typeof f);\n        function f() {}\n    }\n    expect: {\n        console.log(typeof f);\n        function f() {}\n    }\n    expect_stdout: \"function\"\n}\n\nblock_scope_1_compress: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof f);\n        function f() {}\n    }\n    expect: {\n        console.log(\"function\");\n    }\n    expect_stdout: \"function\"\n}\n\nblock_scope_2: {\n    input: {\n        {\n            console.log(typeof f);\n        }\n        function f() {}\n    }\n    expect: {\n        console.log(typeof f);\n        function f() {}\n    }\n    expect_stdout: \"function\"\n}\n\nblock_scope_2_compress: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        {\n            console.log(typeof f);\n        }\n        function f() {}\n    }\n    expect: {\n        console.log(\"function\");\n    }\n    expect_stdout: \"function\"\n}\n\nblock_scope_3: {\n    input: {\n        console.log(typeof f);\n        {\n            function f() {}\n        }\n    }\n    expect: {\n        console.log(typeof f);\n        {\n            function f() {}\n        }\n    }\n    expect_stdout: true\n}\n\nblock_scope_3_compress: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof f);\n        {\n            function f() {}\n        }\n    }\n    expect: {\n        console.log(typeof f);\n        {\n            function f() {}\n        }\n    }\n    expect_stdout: true\n}\n\nblock_scope_4: {\n    input: {\n        {\n            console.log(typeof f);\n            function f() {}\n        }\n    }\n    expect: {\n        console.log(typeof f);\n        function f() {}\n    }\n    expect_stdout: \"function\"\n}\n\nblock_scope_4_compress: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        {\n            console.log(typeof f);\n            function f() {}\n        }\n    }\n    expect: {\n        console.log(\"function\");\n    }\n    expect_stdout: \"function\"\n}\n\nissue_4725_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var o = {\n            f() {\n                return function g() {\n                    return g;\n                }();\n            }\n        };\n        console.log(typeof o.f());\n    }\n    expect: {\n        var o = {\n            f() {\n                return function g() {\n                    return g;\n                }();\n            }\n        };\n        console.log(typeof o.f());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_4725_2: {\n    options = {\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        var o = {\n            f() {\n                return function() {\n                    while (console.log(\"PASS\"));\n                }();\n            }\n        };\n        o.f();\n    }\n    expect: {\n        var o = {\n            f() {\n                while (console.log(\"PASS\"));\n            }\n        };\n        o.f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nnew_target_1: {\n    input: {\n        new function f() {\n            console.log(new.target === f);\n        }();\n        console.log(function() {\n            return new.target;\n        }());\n    }\n    expect: {\n        new function f() {\n            console.log(new.target === f);\n        }();\n        console.log(function() {\n            return new.target;\n        }());\n    }\n    expect_stdout: [\n        \"true\",\n        \"undefined\",\n    ]\n    node_version: \">=6\"\n}\n\nnew_target_2: {\n    input: {\n        new function(a) {\n            if (!new.target)\n                console.log(\"FAIL\");\n            else if (a)\n                console.log(\"PASS\");\n            else\n                new new.target(new.target.length);\n        }();\n    }\n    expect: {\n        new function(a) {\n            if (!new.target)\n                console.log(\"FAIL\");\n            else if (a)\n                console.log(\"PASS\");\n            else\n                new new.target(new.target.length);\n        }();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nnew_target_collapse_vars: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        new function(a) {\n            if (a)\n                console.log(\"PASS\");\n            else\n                new new.target(new.target.length);\n        }(0);\n    }\n    expect: {\n        new function(a) {\n            if (a)\n                console.log(\"PASS\");\n            else\n                new new.target(new.target.length);\n        }(0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nnew_target_delete: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        new function() {\n            console.log(delete new.target);\n        }();\n    }\n    expect: {\n        new function() {\n            console.log(delete new.target);\n        }();\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nnew_target_reduce_vars: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        new function(a) {\n            if (a)\n                console.log(\"PASS\");\n            else\n                new new.target(new.target.length);\n        }(0);\n    }\n    expect: {\n        new function(a) {\n            if (a)\n                console.log(\"PASS\");\n            else\n                new new.target(new.target.length);\n        }(0);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4753_1: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var i in [ 1, 2 ])\n            (function() {\n                function f() {}\n                f && console.log(f.p ^= 42);\n            })();\n    }\n    expect: {\n        for (var i in [ 1, 2 ])\n            f = function() {},\n            void (f && console.log(f.p ^= 42));\n        var f;\n    }\n    expect_stdout: [\n        \"42\",\n        \"42\",\n    ]\n}\n\nissue_4753_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        do {\n            (function() {\n                var a = f();\n                function f() {\n                    return \"PASS\";\n                }\n                f;\n                function g() {\n                    console.log(a);\n                }\n                g();\n            })();\n        } while (0);\n    }\n    expect: {\n        do {\n            a = void 0,\n            f = function() {\n                return \"PASS\";\n            },\n            a = f(),\n            console.log(a);\n        } while (0);\n        var f, a;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4788: {\n    options = {\n        evaluate: true,\n        functions: true,\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = function g() {\n                if (0) {\n                    var g = 42;\n                    f();\n                }\n                g || console.log(\"PASS\");\n            };\n            a(a);\n        }\n        f();\n    }\n    expect: {\n        (function f() {\n            function a() {\n                if (0) {\n                    var g = 42;\n                    f();\n                }\n                g || console.log(\"PASS\");\n            }\n            a();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4823: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            {\n                function f() {}\n                var arguments = f();\n                function g() {}\n                var arguments = g;\n            }\n            return f && arguments;\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            {\n                function f() {}\n                f();\n                var arguments = function() {};\n            }\n            return f && arguments;\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\ndrop_unused_self_reference: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        (f.p = f).q = console.log(\"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nreduce_cross_reference_1: {\n    options = {\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            a = b = function() {};\n            a.p = a;\n            b = a = function() {};\n            b.q = b;\n        })();\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_1_toplevel: {\n    options = {\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = b = function() {};\n        a.p = a;\n        var b = a = function() {};\n        b.q = b;\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_2: {\n    options = {\n        collapse_vars: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            a = b = function() {};\n            b.p = a;\n            b = a = function() {};\n            a.q = b;\n        })();\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_2_toplevel: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = b = function() {};\n        b.p = a;\n        var b = a = function() {};\n        a.q = b;\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_3: {\n    options = {\n        collapse_vars: true,\n        passes: 4,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            a = b = function() {};\n            a.p = b;\n            b = a = function() {};\n            b.q = a;\n        })();\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_3_toplevel: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = b = function() {};\n        a.p = b;\n        var b = a = function() {};\n        b.q = a;\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_4: {\n    options = {\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a, b) {\n            a = b = function() {};\n            b.p = b;\n            b = a = function() {};\n            a.q = a;\n        })();\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nreduce_cross_reference_4_toplevel: {\n    options = {\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = b = function() {};\n        b.p = b;\n        var b = a = function() {};\n        a.q = a;\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nrecursive_collapse: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function f(a) {\n            var b = a && f();\n            return b;\n        }(\"FAIL\") || \"PASS\");\n    }\n    expect: {\n        console.log(function f(a) {\n            var b;\n            return a && f();\n        }(\"FAIL\") || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5025: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            function g() {\n                b = 42;\n            }\n            g(b = a);\n            var b = this;\n            console.log(typeof b);\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            b = a,\n            void (b = 42);\n            var b = this;\n            console.log(typeof b);\n        }\n        f();\n    }\n    expect_stdout: \"object\"\n}\n\nissue_5036: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            var await = function f() {\n                return f;\n            };\n            return await() === await;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(typeof function() {\n            function await() {\n                return await;\n            }\n            return await() === await;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5046: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        keep_fnames: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        if (a)\n            0();\n        else\n            (function f() {\n                f;\n                return a = \"PASS\";\n            })();\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (a ? 0 : function f() {\n            return a = \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5061_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var f, a = 1;\n        (f = function() {\n            console.log(a ? \"foo\" : \"bar\");\n        })();\n        f(a = 0);\n    }\n    expect: {\n        var f, a = 1;\n        (f = function() {\n            console.log(a ? \"foo\" : \"bar\");\n        })();\n        f(a = 0);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_5061_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f, a = 1;\n        (f = function() {\n            console.log(a ? \"foo\" : \"bar\");\n        })();\n        f(a = 0);\n    }\n    expect: {\n        var f, a = 1;\n        (f = function() {\n            console.log(a ? \"foo\" : \"bar\");\n        })();\n        f(a = 0);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_5067: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function() {\n            f();\n        };\n    }\n    expect: {}\n}\n\nissue_5096_1: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect: {\n        var a, b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5096_2: {\n    options = {\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect: {\n        var a, b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5096_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            var a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect: {\n        var b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            var a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5096_4: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            var a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect: {\n        var b = \"FAIL\", c = 1;\n        do {\n            a && a();\n            var a = function() {\n                b = \"PASS\";\n            };\n        } while (c--);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5098: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(o) {\n            function f() {\n                f = console.log;\n                if (o.p++)\n                    throw \"FAIL\";\n                f(\"PASS\");\n            }\n            return f;\n        })({ p: 0 })();\n    }\n    expect: {\n        (function(o) {\n            function f() {\n                f = console.log;\n                if (o.p++)\n                    throw \"FAIL\";\n                f(\"PASS\");\n            }\n            return f;\n        })({ p: 0 })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nshorter_without_void: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            a = b;\n        }\n        f(\"foo\");\n        console.log(a) || f(\"bar\");\n        console.log(a, f(\"baz\"));\n        console.log(a);\n    }\n    expect: {\n        var a;\n        function f(b) {\n            a = b;\n        }\n        a = \"foo\";\n        console.log(a) || (a = \"bar\");\n        console.log(a, f(\"baz\"));\n        console.log(a);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar undefined\",\n        \"baz\",\n    ]\n}\n\nissue_5120: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            function g() {\n                f || g();\n            }\n            g();\n            return f.valueOf();\n        };\n        console.log(a() === a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        function a() {\n            (function g() {\n                a || g();\n            })();\n            return a.valueOf();\n        }\n        console.log(a() === a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5140: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = 42;\n        function f(b) {\n            return b >> 0;\n        }\n        var a = f(42 in []);\n        console.log(f(A));\n    }\n    expect: {\n        function f(b) {\n            return b >> 0;\n        }\n        A = 42;\n        console.log(A >> 0);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5173_1: {\n    options = {\n        conditionals: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a, b) {\n            console.log(b);\n        }\n        f([ A = 42, [] + \"\" || (A = f) ]);\n    }\n    expect: {\n        function f(a, b) {\n            console.log(b);\n        }\n        f([ A = 42, [] + \"\" || (A = f) ]);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5173_2: {\n    options = {\n        conditionals: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            console.log(b);\n        }\n        f([ A = 42, [] + \"\" || (A = f) ]);\n    }\n    expect: {\n        function f(a, b) {\n            console.log(b);\n        }\n        f(A = [] + \"\" ? 42 : f);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5230: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        while (function() {\n            function f(a) {\n                var b = 42, c = (console, [ a ]);\n                for (var k in c)\n                    c, console.log(b++);\n            }\n            f(f);\n        }());\n    }\n    expect: {\n        while (void (f = function(a) {\n            var b = 42;\n            console;\n            var a;\n            for (var k in a = [ a ])\n                console.log(b++);\n        })(f));\n        var f;\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5237: {\n    options = {\n        evaluate: true,\n        inline: true,\n    }\n    input: {\n        function f() {\n            (function() {\n                while (console.log(0/0));\n            })();\n            (function() {\n                var NaN = console && console.log(NaN);\n            })();\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            while (console.log(NaN));\n            (function() {\n                var NaN = console && console.log(NaN);\n            })();\n        }\n        f();\n    }\n    expect_stdout: [\n        \"NaN\",\n        \"undefined\",\n    ]\n}\n\nissue_5239: {\n    options = {\n        functions: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            (function(f) {\n                var a = 42, f = function() {};\n                while (console.log(f.p || a++));\n            })();\n        })();\n    }\n    expect: {\n        (function() {\n            var f = void 0;\n            var a = 42, f = function() {};\n            while (console.log(f.p || a++));\n            return;\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5240_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw \"FAIL 1\";\n            } catch (e) {\n                return function() {\n                    if (console) {\n                        console.log(e);\n                        var e = \"FAIL 2\";\n                    }\n                }();\n            }\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            try {\n                throw \"FAIL 1\";\n            } catch (e) {\n                return function() {\n                    if (console) {\n                        console.log(e);\n                        var e = \"FAIL 2\";\n                    }\n                }();\n            }\n        }\n        f();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5240_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw \"FAIL 1\";\n            } catch (e) {\n                {\n                    return function() {\n                        if (console) {\n                            console.log(e);\n                            var e = \"FAIL 2\";\n                        }\n                    }();\n                }\n            }\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            try {\n                throw \"FAIL 1\";\n            } catch (e) {\n                return function() {\n                    if (console) {\n                        console.log(e);\n                        var e = \"FAIL 2\";\n                    }\n                }();\n            }\n        }\n        f();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5249_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            if (!console)\n                var a = \"FAIL 1\";\n            else\n                return void (a && function() {\n                    while (console.log(\"FAIL 2\"));\n                }());\n            throw \"FAIL 3\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (!console)\n                var a = \"FAIL 1\";\n            else if (a) {\n                while (console.log(\"FAIL 2\"));\n                return;\n            } else\n                return void 0;\n            throw \"FAIL 3\";\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5249_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            if (!console)\n                var a = \"FAIL 1\";\n            else\n                return void (a && function() {\n                    while (console.log(\"FAIL 2\"));\n                }());\n            throw \"FAIL 3\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (!console)\n                throw \"FAIL 3\";\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5254_1: {\n    options = {\n        inline: 3,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            while (a--)\n                (function f() {\n                    var f = new function() {\n                        console.log(f);\n                    }();\n                })();\n        })(2);\n    }\n    expect: {\n        (function(a) {\n            while (a--)\n                f = void 0,\n                f = new function() {\n                    console.log(f);\n                }(),\n                void 0;\n            var f;\n        })(2);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\nissue_5254_2: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            while (a--)\n                (function f() {\n                    var f = new function() {\n                        console.log(f);\n                    }();\n                    while (!console);\n                })();\n        })(2);\n    }\n    expect: {\n        (function(a) {\n            while (a--) {\n                f = void 0;\n                var f = new function() {\n                    console.log(f);\n                }();\n                while (!console);\n            }\n        })(2);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\nissue_5263: {\n    options = {\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        for (var i = 0; i < 2; i++) (function() {\n            while (console.log(i));\n            (function(a) {\n                console.log(a) && a,\n                a++;\n            })();\n        })();\n    }\n    expect: {\n        for (var i = 0; i < 2; i++) {\n            a = void 0;\n            while (console.log(i));\n            console.log(a),\n            a++;\n            var a;\n        }\n    }\n    expect_stdout: [\n        \"0\",\n        \"undefined\",\n        \"1\",\n        \"undefined\",\n    ]\n}\n\nissue_5264_1: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function f(arguments) {\n                console.log(arguments);\n                (function() {\n                    while (console.log(\"foo\"));\n                })();\n            }\n            f(\"bar\");\n            return arguments;\n        }(\"baz\")[0]);\n    }\n    expect: {\n        console.log(function() {\n            (function(arguments) {\n                console.log(arguments);\n                while (console.log(\"foo\"));\n            })(\"bar\");\n            return arguments;\n        }(\"baz\")[0]);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"baz\",\n    ]\n}\n\nissue_5264_2: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function f(arguments) {\n                console.log(arguments);\n                (function() {\n                    while (console.log(\"foo\"));\n                })();\n            }\n            f(\"bar\");\n            return arguments;\n        }(\"baz\")[0]);\n    }\n    expect: {\n        console.log(function() {\n            (function(arguments) {\n                console.log(arguments);\n                while (console.log(\"foo\"));\n            })(\"bar\");\n            return arguments;\n        }(\"baz\")[0]);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"baz\",\n    ]\n}\n\nissue_5283: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        inline: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL 1\";\n        (function() {\n            (a = \"PASS\")[function() {\n                if (console)\n                    return null;\n                var b = function f(a) {\n                    console.log(\"FAIL 2\");\n                    var c = a.p;\n                }();\n            }()];\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL 1\";\n        (function() {\n            a = \"PASS\";\n            console || function(a) {\n                console.log(\"FAIL 2\");\n                a.p;\n            }();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5290: {\n    options = {\n        functions: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        while (a--) new function(b) {\n            switch (b) {\n              case b.p:\n              case console.log(\"PASS\"):\n            }\n        }(function() {});\n    }\n    expect: {\n        var a = 1;\n        while (a--) {\n            b = void 0;\n            var b = function() {};\n            switch (b) {\n              case b.p:\n              case console.log(\"PASS\"):\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5296: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            for (var i = 0; i < 2; i++)\n                try {\n                    return function() {\n                        while (!console);\n                        var b = b && (a = b) || \"FAIL\";\n                    }();\n                } finally {\n                    continue;\n                }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            for (var i = 0; i < 2; i++)\n                try {\n                    b = void 0;\n                    while (!console);\n                    var b = b && (a = b) || \"FAIL\";\n                    return;\n                } finally {\n                    continue;\n                }\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5316_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        do {\n            console.log(\"PASS\");\n        } while (function() {\n            var a, b = 42 && (console[a = b] = a++);\n        }());\n    }\n    expect: {\n        do {\n            console.log(\"PASS\");\n        } while (b = a = void 0, b = (42, console[a = a] = a++), void 0);\n        var a, b;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5316_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        do {\n            (function() {\n                var a, b = 42 && (console[a = b] = a++);\n                while (console.log(\"PASS\"));\n            })();\n        } while (!console);\n    }\n    expect: {\n        do {\n            a = void 0;\n            var a, b = (42, console[a = b = void 0] = a++);\n            while (console.log(\"PASS\"));\n        } while (!console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5328: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function(arguments) {\n            console.log(Object.keys(arguments).join());\n        })(this);\n    }\n    expect: {\n        void console.log(Object.keys(this).join());\n    }\n    expect_stdout: \"\"\n}\n\nissue_5332_1: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        do {\n            var a = {};\n            for (A in a)\n                a;\n        } while (function() {\n            console.log(b);\n            var b = b;\n        }());\n    }\n    expect: {\n        do {\n            var a = {};\n            for (A in a);\n        } while (a = void 0, void console.log(a));\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5332_2: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        do {\n            var a = 42 in [];\n            for (A in a)\n                a;\n        } while (function() {\n            console.log(++b);\n            var b = b;\n        }());\n    }\n    expect: {\n        do {\n            var a = 42 in [];\n            for (A in a);\n        } while (a = void 0, void console.log(++a));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5366: {\n    options = {\n        inline: true,\n    }\n    input: {\n        for (console.log(\"foo\") || function() {\n            while (console.log(\"bar\"));\n        }(); console.log(\"baz\") ;);\n    }\n    expect: {\n        if (!console.log(\"foo\"))\n            while (console.log(\"bar\"));\n        for (;console.log(\"baz\"););\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5376_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        for (;42;)\n            var b = function() {\n                var c;\n                throw new Error(c++);\n            }();\n    }\n    expect: {\n        \"use strict\";\n        for (;;) {\n            42;\n            throw new Error(NaN);\n        }\n    }\n    expect_stdout: Error(\"NaN\")\n}\n\nissue_5376_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        loops: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        for (;42;)\n            var b = function() {\n                var c;\n                c++;\n                throw new Error(\"PASS\");\n            }();\n    }\n    expect: {\n        \"use strict\";\n        for (;;) {\n            0;\n            throw new Error(\"PASS\");\n        }\n    }\n    expect_stdout: Error(\"PASS\")\n}\n\nissue_5401: {\n    options = {\n        inline: true,\n    }\n    input: {\n        L: for (var a in function() {\n            while (console.log(\"PASS\"));\n        }(), a) do {\n            continue L;\n        } while (console.log(\"FAIL\"));\n    }\n    expect: {\n        while (console.log(\"PASS\"));\n        L: for (var a in a) do {\n            continue L;\n        } while (console.log(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5409: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            (a = console) || FAIL(a);\n            (function(b) {\n                console.log(b && b);\n                while (!console);\n            })();\n        })();\n    }\n    expect: {\n        (function(a) {\n            (a = console) || FAIL(a);\n            a = void 0;\n            console.log(a && a);\n            while (!console);\n            return;\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nmixed_mode_inline_1: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return this;\n        }\n        console.log(function() {\n            return f();\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function() {\n            return this;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_1_strict: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            return this;\n        }\n        console.log(function() {\n            return f();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            return this;\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_2: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            \"use strict\";\n            return this;\n        }\n        console.log(function() {\n            return f();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        console.log(function() {\n            \"use strict\";\n            return this;\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_2_strict: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            \"use strict\";\n            return this;\n        }\n        console.log(function() {\n            return f();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            return this;\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_3: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return this;\n        }\n        console.log(function() {\n            \"use strict\";\n            return f();\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        function f() {\n            return this;\n        }\n        console.log(function() {\n            \"use strict\";\n            return f();\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_3_strict: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            return this;\n        }\n        console.log(function() {\n            \"use strict\";\n            return f();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            return this;\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_4: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            \"use strict\";\n            return this;\n        }\n        console.log(function() {\n            \"use strict\";\n            return f();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        console.log(function() {\n            \"use strict\";\n            return function() {\n                \"use strict\";\n                return this;\n            }();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmixed_mode_inline_4_strict: {\n    options = {\n        directives: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            \"use strict\";\n            return this;\n        }\n        console.log(function() {\n            \"use strict\";\n            return f();\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            return this;\n        }() ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nmodule_inline: {\n    options = {\n        inline: true,\n        module: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = f;\n        function f() {\n            return a;\n        }\n        console.log(f() === a);\n    }\n    expect: {\n        var a = f;\n        function f() {\n            return a;\n        }\n        console.log(a === a);\n    }\n    expect_stdout: \"true\"\n}\n\nsingle_use_inline_collision: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            var f = function() {\n                while (console.log(a));\n            };\n            (function() {\n                (function() {\n                    f();\n                })();\n                (function(a) {\n                    a || a(\"FAIL\");\n                })(console.log);\n            })();\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            void function() {\n                while (console.log(a));\n            }();\n            (function(a) {\n                a || a(\"FAIL\");\n            })(console.log);\n            return;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5692: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function() {\n            while (console.log(\"PASS\"))\n                if (console)\n                    return;\n        })();\n    }\n    expect: {\n        (function() {\n            while (console.log(\"PASS\"))\n                if (console)\n                    return;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5766_1: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        functions: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        log = function(a) {\n            console.log(typeof a);\n        };\n        do {\n            (function() {\n                try {\n                    var f = function() {};\n                    log(f && f);\n                } catch (e) {}\n            })();\n        } while (0);\n    }\n    expect: {\n        log = function(a) {\n            console.log(typeof a);\n        };\n        do {\n            try {\n                function f() {}\n                log(f);\n            } catch (e) {}\n        } while (0);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_5766_2: {\n    options = {\n        evaluate: true,\n        functions: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        log = function(a) {\n            console.log(typeof a);\n        };\n        do {\n            (function() {\n                try {\n                    var f = function() {};\n                    log(f && f);\n                } catch (e) {}\n            })();\n        } while (0);\n    }\n    expect: {\n        log = function(a) {\n            console.log(typeof a);\n        };\n        do {\n            try {\n                function f() {}\n                log(f);\n            } catch (e) {}\n        } while (0);\n    }\n    expect_stdout: \"function\"\n}\n\nissue_5841_1: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        (function() {\n            f();\n            var b = f();\n            function f() {\n                if (console && a)\n                    g && g();\n            }\n            function g() {\n                var c;\n                for (;console.log(\"foo\"););\n                (function h(d) {\n                    d && d.p;\n                })();\n            }\n        })();\n    }\n    expect: {\n        var a = 42;\n        (function() {\n            f();\n            f();\n            function f() {\n                {\n                    if (console && a) {\n                        for (;console.log(\"foo\"););\n                        return;\n                    }\n                    return;\n                }\n            }\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_5841_2: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        if_return: true,\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        (function() {\n            f();\n            var b = f();\n            function f() {\n                if (console && a)\n                    g && g();\n            }\n            function g() {\n                var c;\n                for (;console.log(\"foo\"););\n                (function h(d) {\n                    d && d.p;\n                })();\n            }\n        })();\n    }\n    expect: {\n        var a = 42;\n        (function() {\n            f();\n            f();\n            function f() {\n                if (console && a)\n                    for (;console.log(\"foo\"););\n            }\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_5851_1: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(\"PASS\") && f();\n        function f() {\n            return f();\n        }\n        f;\n    }\n    expect: {\n        console.log(\"PASS\") && f();\n        function f() {\n            return f();\n        }\n        f;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5851_2: {\n    options = {\n        conditionals: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = f();\n        f();\n        function f() {\n            if (console.log(\"foo\"))\n                console && f();\n        }\n    }\n    expect: {\n        f();\n        f();\n        function f() {\n            console.log(\"foo\") && console && f();\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_5885: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        f();\n        function f() {\n            return ++a + \"foo\";\n        }\n        console.log(a = f());\n    }\n    expect: {\n        var a;\n        f();\n        function f() {\n            return ++a + \"foo\";\n        }\n        console.log(a = f());\n    }\n    expect_stdout: \"NaNfoo\"\n}\n\nissue_5895_1: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            for (var a in [ 1, 2 ])\n                try {\n                    return function() {\n                        var b;\n                        b[b = 42];\n                        while (!console);\n                    }();\n                } catch (e) {\n                    console.log(\"foo\");\n                }\n        })();\n    }\n    expect: {\n        (function() {\n            for (var a in [ 1, 2 ])\n                try {\n                    b = void 0;\n                    var b;\n                    b[b = 42];\n                    while (!console);\n                    return;\n                } catch (e) {\n                    console.log(\"foo\");\n                }\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_5895_2: {\n    options = {\n        inline: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            for (var a in [ 1, 2 ])\n                try {\n                    return function() {\n                        (function f(b) {\n                            b[b = 42];\n                        })();\n                        while (!console);\n                    }();\n                } catch (e) {\n                    console.log(\"foo\");\n                }\n        })();\n    }\n    expect: {\n        (function() {\n            for (var a in [ 1, 2 ])\n                try {\n                    b = void 0;\n                    void b[b = 42];\n                    var b;\n                    while (!console);\n                    return;\n                } catch (e) {\n                    console.log(\"foo\");\n                }\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_5924: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 42;\n        function f() {\n            return a - 41;\n        }\n        function g() {\n            return f;\n        }\n        var b = f();\n        a--;\n        console.log(b ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = 42;\n        function f() {\n            return a - 41;\n        }\n        function g() {\n            return f;\n        }\n        var b = f();\n        a--;\n        console.log(b ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5925: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 42;\n        console.log(function() {\n            function f() {\n                return +a - 41;\n            }\n            var b = f(f);\n            a--;\n            return b;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = 42;\n        console.log(function() {\n            function f() {\n                return +a - 41;\n            }\n            var b = f(f);\n            a--;\n            return b;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/global_defs.js",
    "content": "must_replace: {\n    options = {\n        global_defs: {\n            D: \"foo bar\",\n        },\n    }\n    input: {\n        console.log(D);\n    }\n    expect: {\n        console.log(\"foo bar\");\n    }\n}\n\nrepeated_nodes: {\n    options = {\n        global_defs: {\n            \"@N\": \"rand()\",\n        },\n    }\n    input: {\n        console.log(N, N);\n    }\n    expect: {\n        console.log(rand(), rand());\n    }\n}\n\nkeyword: {\n    options = {\n        global_defs: {\n            undefined: 0,\n            NaN: 1,\n            Infinity: 2,\n        },\n    }\n    input: {\n        console.log(undefined, NaN, Infinity);\n    }\n    expect: {\n        console.log(0, 1, 2);\n    }\n}\n\nobject: {\n    options = {\n        evaluate: true,\n        global_defs: {\n            CONFIG: {\n                DEBUG: [ 0 ],\n                VALUE: 42,\n            },\n        },\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        function f(CONFIG) {\n            // CONFIG not global - do not replace\n            return CONFIG.VALUE;\n        }\n        function g() {\n            var CONFIG = { VALUE: 1 };\n            // CONFIG not global - do not replace\n            return CONFIG.VALUE;\n        }\n        function h() {\n            return CONFIG.VALUE;\n        }\n        if (CONFIG.DEBUG[0])\n            console.debug(\"foo\");\n    }\n    expect: {\n        function f(CONFIG) {\n            return CONFIG.VALUE;\n        }\n        function g() {\n            var CONFIG = { VALUE: 1 };\n            return CONFIG.VALUE;\n        }\n        function h() {\n            return 42;\n        }\n        if (0)\n            console.debug(\"foo\");\n    }\n}\n\nexpanded: {\n    options = {\n        global_defs: {\n            \"CONFIG.DEBUG\": [ 0 ],\n            \"CONFIG.VALUE\": 42,\n        },\n    }\n    input: {\n        function f(CONFIG) {\n            // CONFIG not global - do not replace\n            return CONFIG.VALUE;\n        }\n        function g() {\n            var CONFIG = { VALUE: 1 };\n            // CONFIG not global - do not replace\n            return CONFIG.VALUE;\n        }\n        function h() {\n            return CONFIG.VALUE;\n        }\n        if (CONFIG.DEBUG[0])\n            console.debug(\"foo\");\n    }\n    expect: {\n        function f(CONFIG) {\n            return CONFIG.VALUE;\n        }\n        function g() {\n            var CONFIG = { VALUE: 1 };\n            return CONFIG.VALUE;\n        }\n        function h() {\n            return 42;\n        }\n        if ([0][0])\n            console.debug(\"foo\");\n    }\n}\n\nmixed: {\n    options = {\n        evaluate: true,\n        global_defs: {\n            \"CONFIG.VALUE\": 42,\n            \"FOO.BAR\": \"moo\",\n        },\n        properties: true,\n    }\n    input: {\n        var FOO = { BAR: 0 };\n        console.log(FOO.BAR);\n        console.log(++CONFIG.DEBUG);\n        console.log(++CONFIG.VALUE);\n        console.log(++CONFIG[\"VAL\" + \"UE\"]);\n        console.log(++DEBUG[CONFIG.VALUE]);\n        CONFIG.VALUE.FOO = \"bar\";\n        console.log(CONFIG);\n    }\n    expect: {\n        var FOO = { BAR: 0 };\n        console.log(\"moo\");\n        console.log(++CONFIG.DEBUG);\n        console.log(++CONFIG.VALUE);\n        console.log(++CONFIG.VALUE);\n        console.log(++DEBUG[42]);\n        CONFIG.VALUE.FOO = \"bar\";\n        console.log(CONFIG);\n    }\n    expect_warnings: [\n        \"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:4,22]\",\n        \"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:7,8]\",\n    ]\n}\n\nissue_1801: {\n    options = {\n        booleans: true,\n        global_defs: {\n            \"CONFIG.FOO.BAR\": true,\n        },\n    }\n    input: {\n        console.log(CONFIG.FOO.BAR);\n    }\n    expect: {\n        console.log(!0);\n    }\n}\n\nissue_1986: {\n    options = {\n        global_defs: {\n            \"@alert\": \"console.log\",\n        },\n    }\n    input: {\n        alert(42);\n    }\n    expect: {\n        console.log(42);\n    }\n}\n\nissue_2167: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        global_defs: {\n            \"@isDevMode\": \"function(){}\",\n        },\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        if (isDevMode()) {\n            greetOverlord();\n        }\n        doWork();\n    }\n    expect: {\n        doWork();\n    }\n}\n\nissue_3217: {\n    options = {\n        collapse_vars: true,\n        global_defs: {\n            \"@o\": \"{fn:function(){var a=42;console.log(a)}}\",\n        },\n        inline: true,\n        properties: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        o.fn();\n    }\n    expect: {\n        console.log(42);\n    }\n}\n"
  },
  {
    "path": "test/compress/hoist_props.js",
    "content": "issue_2377_1: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var obj = {\n            foo: 1,\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(obj.foo, obj.cube(3));\n    }\n    expect: {\n        var obj_foo = 1, obj_cube = function(x) {\n            return x * x * x;\n        };\n        console.log(obj_foo, obj_cube(3));\n    }\n    expect_stdout: \"1 27\"\n}\n\nissue_2377_2: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var obj = {\n            foo: 1,\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(obj.foo, obj.cube(3));\n    }\n    expect: {\n        console.log(1, (x = 3, x * x * x));\n        var x;\n    }\n    expect_stdout: \"1 27\"\n}\n\nissue_2377_3: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        passes: 4,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var obj = {\n            foo: 1,\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(obj.foo, obj.cube(3));\n    }\n    expect: {\n        console.log(1, 27);\n    }\n    expect_stdout: \"1 27\"\n}\n\ndirect_access_1: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        var obj = {\n            a: 1,\n            b: 2,\n        };\n        for (var k in obj) a++;\n        console.log(a, obj.a);\n    }\n    expect: {\n        var a = 0;\n        var obj = {\n            a: 1,\n            b: 2,\n        };\n        for (var k in obj) a++;\n        console.log(a, obj.a);\n    }\n    expect_stdout: \"2 1\"\n}\n\ndirect_access_2: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = { a: 1 };\n        var f = function(k) {\n            if (o[k]) return \"PASS\";\n        };\n        console.log(f(\"a\"));\n    }\n    expect: {\n        var o = { a: 1 };\n        console.log(function(k) {\n            if (o[k]) return \"PASS\";\n        }(\"a\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\ndirect_access_3: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = { a: 1 };\n        o.b;\n        console.log(o.a);\n    }\n    expect: {\n        var o = { a: 1 };\n        o.b;\n        console.log(o.a);\n    }\n    expect_stdout: \"1\"\n}\n\nsingle_use: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var obj = {\n            bar: function() {\n                return 42;\n            },\n        };\n        console.log(obj.bar());\n    }\n    expect: {\n        console.log({\n            bar: function() {\n                return 42;\n            },\n        }.bar());\n    }\n}\n\nname_collision_1: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var obj_foo = 1;\n        var obj_bar = 2;\n        function f() {\n            var obj = {\n                foo: 3,\n                bar: 4,\n                \"b-r\": 5,\n                \"b+r\": 6,\n                \"b!r\": 7,\n            };\n            console.log(obj_foo, obj.foo, obj.bar, obj[\"b-r\"], obj[\"b+r\"], obj[\"b!r\"]);\n        }\n        f();\n    }\n    expect: {\n        var obj_foo = 1;\n        var obj_bar = 2;\n        function f() {\n            var obj,\n                obj_foo$0 = 3,\n                obj_bar = 4,\n                obj_b_r = 5,\n                obj_b_r$0 = 6,\n                obj_b_r$1 = 7;\n            console.log(obj_foo, obj_foo$0, obj_bar, obj_b_r, obj_b_r$0, obj_b_r$1);\n        }\n        f();\n    }\n    expect_stdout: \"1 3 4 5 6 7\"\n}\n\nname_collision_2: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            p: 1,\n            \"+\": function(x) {\n                return x;\n            },\n            \"-\": function(x) {\n                return x + 1;\n            }\n        }, o__$0 = 2, o__$1 = 3;\n        console.log(o.p === o.p, o[\"+\"](4), o[\"-\"](5), o__$0, o__$1);\n    }\n    expect: {\n        var o,\n            o_p = 1,\n            o__ = function(x) {\n                return x;\n            },\n            o__$2 = function(x) {\n                return x + 1;\n            },\n            o__$0 = 2,\n            o__$1 = 3;\n        console.log(o_p === o_p, o__(4), o__$2(5), o__$0, o__$1);\n    }\n    expect_stdout: \"true 4 6 2 3\"\n}\n\nname_collision_3: {\n    options = {\n        hoist_props: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            p: 1,\n            \"+\": function(x) {\n                return x;\n            },\n            \"-\": function(x) {\n                return x + 1;\n            }\n        }, o__$0 = 2, o__$1 = 3;\n        console.log(o.p === o.p, o[\"+\"](4), o[\"-\"](5));\n    }\n    expect: {\n        var o,\n            o_p = 1,\n            o__ = function(x) {\n                return x;\n            },\n            o__$2 = function(x) {\n                return x + 1;\n            },\n            o__$0 = 2,\n            o__$1 = 3;\n        console.log(o_p === o_p, o__(4), o__$2(5));\n    }\n    expect_stdout: \"true 4 6\"\n}\n\nname_collision_4: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {\n                p: 0,\n                q: \"PASS\",\n            };\n            return function(o_p) {\n                if (!o.p) return o_p;\n            }(o.q);\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var o, o_p$0 = 0, o_q = \"PASS\";\n            return function(o_p) {\n                if (!o_p$0) return o_p;\n            }(o_q);\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\ncontains_this_1: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            u: function() {\n                return this === this;\n            },\n            p: 1\n        };\n        console.log(o.p, o.p);\n    }\n    expect: {\n        console.log(1, 1);\n    }\n    expect_stdout: \"1 1\"\n}\n\ncontains_this_2: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            u: function() {\n                return this === this;\n            },\n            p: 1\n        };\n        console.log(o.p, o.p, o.u);\n    }\n    expect: {\n        console.log(1, 1, function() {\n            return this === this;\n        });\n    }\n    expect_stdout: true\n}\n\ncontains_this_3: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            u: function() {\n                return this === this;\n            },\n            p: 1\n        };\n        console.log(o.p, o.p, o.u());\n    }\n    expect: {\n        var o = {\n            u: function() {\n                return this === this;\n            },\n            p: 1\n        };\n        console.log(o.p, o.p, o.u());\n    }\n    expect_stdout: \"1 1 true\"\n}\n\nnew_this: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n            f: function(a) {\n                this.b = a;\n            }\n        };\n        console.log(new o.f(o.a).b, o.b);\n    }\n    expect: {\n        console.log(new function(a) {\n            this.b = a;\n        }(1).b, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nissue_2473_1: {\n    options = {\n        hoist_props: false,\n        reduce_vars: true,\n        top_retain: [\n            \"x\",\n            \"y\"\n        ],\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = {};\n        var y = [];\n        var z = {};\n    }\n    expect: {\n        var x = {};\n        var y = [];\n    }\n    expect_warnings: [\n        \"INFO: Retaining variable x\",\n        \"INFO: Retaining variable y\",\n        \"WARN: Dropping unused variable z [test/compress/hoist_props.js:3,12]\",\n    ]\n}\n\nissue_2473_2: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        top_retain: [\n            \"x\",\n            \"y\"\n        ],\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = {};\n        var y = [];\n        var z = {};\n    }\n    expect: {\n        var x = {};\n        var y = [];\n    }\n    expect_warnings: [\n        \"INFO: Retaining variable x\",\n        \"INFO: Retaining variable y\",\n        \"WARN: Dropping unused variable z [test/compress/hoist_props.js:3,12]\",\n    ]\n}\n\nissue_2473_3: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        top_retain: \"o\",\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(o.a, o.b);\n    }\n    expect: {\n        var o = {\n            a: 1,\n            b: 2,\n        };\n        console.log(o.a, o.b);\n    }\n    expect_stdout: \"1 2\"\n    expect_warnings: [\n        \"INFO: Retaining variable o\",\n    ]\n}\n\nissue_2473_4: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        top_retain: \"o\",\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var o = {\n                a: 1,\n                b: 2,\n            };\n            console.log(o.a, o.b);\n        })();\n    }\n    expect: {\n        (function() {\n            var o_a = 1, o_b = 2;\n            console.log(o_a, o_b);\n        })();\n    }\n    expect_stdout: \"1 2\"\n    expect_warnings: [\n        \"INFO: Dropping unused variable o [test/compress/hoist_props.js:2,16]\",\n    ]\n}\n\nissue_2508_1: {\n    options = {\n        collapse_vars: true,\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: [ 1 ],\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.a);\n    }\n    expect: {\n        (function(x) {\n            console.log(x);\n        })([ 1 ]);\n    }\n    expect_stdout: true\n}\n\nissue_2508_2: {\n    options = {\n        collapse_vars: true,\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: { b: 2 },\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.a);\n    }\n    expect: {\n        (function(x) {\n            console.log(x);\n        })({ b: 2 });\n    }\n    expect_stdout: true\n}\n\nissue_2508_3: {\n    options = {\n        collapse_vars: true,\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: [ o ],\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.a);\n    }\n    expect: {\n        var o = {\n            a: [ o ],\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.a);\n    }\n    expect_stdout: true\n}\n\nissue_2508_4: {\n    options = {\n        collapse_vars: true,\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: { b: o },\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.a);\n    }\n    expect: {\n        var o = {\n            a: { b: o },\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.a);\n    }\n    expect_stdout: true\n}\n\nissue_2508_5: {\n    options = {\n        collapse_vars: true,\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            f: function(x) {\n                console.log(x);\n            }\n        };\n        o.f(o.f);\n    }\n    expect: {\n        var o_f = function(x) {\n            console.log(x);\n        };\n        o_f(o_f);\n    }\n    expect_stdout: true\n}\n\nissue_2519: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        hoist_props: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function testFunc() {\n            var dimensions = {\n                minX: 5,\n                maxX: 6,\n            };\n            var scale = 1;\n            var d = {\n                x: (dimensions.maxX + dimensions.minX) / 2,\n            };\n            return d.x * scale;\n        }\n        console.log(testFunc());\n    }\n    expect: {\n        function testFunc() {\n            return +((6 + 5) / 2);\n        }\n        console.log(testFunc());\n    }\n    expect_stdout: \"5.5\"\n}\n\nundefined_key: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        join_vars: true,\n        passes: 4,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, o = {};\n        o[a] = 1;\n        o.b = 2;\n        console.log(o[a] + o.b);\n    }\n    expect: {\n        console.log(3);\n    }\n    expect_stdout: \"3\"\n}\n\nissue_3021: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 1, b = 2;\n        (function() {\n            b = a;\n            if (a++ + b--)\n                return 1;\n            return;\n            var b = {};\n        })();\n        console.log(a, b);\n    }\n    expect: {\n        var a = 1, b = 2;\n        (function() {\n            b = a;\n            if (a++ + b--)\n                return 1;\n            return;\n            var b = {};\n        })();\n        console.log(a, b);\n    }\n    expect_stdout: \"2 2\"\n}\n\nissue_3046: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            do {\n                var b = {\n                    c: a++\n                };\n            } while (b.c && a);\n            return a;\n        }(0));\n    }\n    expect: {\n        console.log(function(a) {\n            do {\n                var b, b_c = a++;\n            } while (b_c && a);\n            return a;\n        }(0));\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3071_1: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        join_vars: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var obj = {};\n            obj.one = 1;\n            obj.two = 2;\n            console.log(obj.one, obj.two);\n        })();\n    }\n    expect: {\n        console.log(1, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nissue_3071_1_toplevel: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        join_vars: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var obj = {};\n            obj.one = 1;\n            obj.two = 2;\n            console.log(obj.one, obj.two);\n        })();\n    }\n    expect: {\n        console.log(1, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nissue_3071_2: {\n    options = {\n        hoist_props: true,\n        inline: true,\n        join_vars: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            obj = {};\n            obj.one = 1;\n            obj.two = 2;\n            console.log(obj.one, obj.two);\n            var obj;\n        })();\n    }\n    expect: {\n        console.log(1, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nissue_3071_2_toplevel: {\n    options = {\n        hoist_props: true,\n        inline: true,\n        join_vars: true,\n        passes: 3,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            obj = {};\n            obj.one = 1;\n            obj.two = 2;\n            console.log(obj.one, obj.two);\n            var obj;\n        })();\n    }\n    expect: {\n        console.log(1, 2);\n    }\n    expect_stdout: \"1 2\"\n}\n\nissue_3071_3: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = 0;\n        (function(a, b) {\n            (function f(o) {\n                var n = 2;\n                while (--b + (o = {\n                    p: c++,\n                }) && --n > 0);\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(a, b) {\n            (function f(o) {\n                var n = 2;\n                while (--b + (o = {\n                    p: c++,\n                }) && --n > 0);\n            })();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_3411: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = 1;\n        !function f() {\n            var o = {\n                p: --c && f()\n            };\n            +o || console.log(\"PASS\");\n        }();\n    }\n    expect: {\n        var c = 1;\n        !function f() {\n            var o, o_p = --c && f();\n            +{} || console.log(\"PASS\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3440: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                console.log(o.p);\n            }\n            var o = {\n                p: \"PASS\",\n            };\n            return f;\n        })()();\n    }\n    expect: {\n        (function() {\n            var o_p = \"PASS\";\n            return function() {\n                console.log(o_p);\n            };\n        })()();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3868: {\n    options = {\n        hoist_props: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        (function(t) {\n            t = {};\n            ({\n                get p() {},\n                q: (console.log(\"PASS\"), +t),\n            }).r;\n        })();\n    }\n    expect: {\n        (function(t) {\n            t = {};\n            ({\n                get p() {},\n                q: (console.log(\"PASS\"), +t),\n            }).r;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3871: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            do {\n                var b = {\n                    get null() {\n                        c;\n                    }\n                };\n            } while (!b);\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            do {\n                var b = {\n                    get null() {\n                        c;\n                    }\n                };\n            } while (!b);\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3945_1: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            o.p;\n            var o = {\n                q: 0,\n            };\n        }\n    }\n    expect: {\n        function f() {\n            o.p;\n            var o, o_q = 0;\n        }\n    }\n}\n\nissue_3945_2: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(typeof o);\n        var o = {\n            p: 0,\n        };\n    }\n    expect: {\n        console.log(typeof o);\n        var o, o_p = 0;\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4023: {\n    options = {\n        comparisons: true,\n        hoist_props: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = function() {\n                return { p: 0 };\n            }();\n            return console.log(\"undefined\" != typeof a);\n        }\n        f();\n    }\n    expect: {\n        console.log(void 0 !== {});\n    }\n    expect_stdout: \"true\"\n}\n\nobject_super: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            f(a) {\n                return a ? console.log(\"PASS\") : super.log(\"PASS\");\n            },\n        };\n        o.f(42);\n    }\n    expect: {\n        var o = {\n            f(a) {\n                return a ? console.log(\"PASS\") : super.log(\"PASS\");\n            },\n        };\n        o.f(42);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4985: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = { p: 42 };\n        console.log(function() {\n            a;\n        }());\n    }\n    expect: {\n        var a, a_p = 42;\n        console.log(function() {\n            ({});\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5182: {\n    options = {\n        hoist_props: true,\n        merge_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = console;\n        log = o.log;\n        o = {\n            p: function(a) {\n                console.log(a ? \"PASS\" : \"FAIL\");\n                return a;\n            },\n        };\n        log(o.p(42));\n    }\n    expect: {\n        var o = console;\n        log = o.log;\n        o = function(a) {\n            console.log(a ? \"PASS\" : \"FAIL\");\n            return a;\n        };\n        log(o(42));\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n}\n\nissue_5441: {\n    options = {\n        hoist_props: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a) {\n            (function() {\n                a = { p: this };\n            })();\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            (function() {\n                a_p = this;\n            })();\n            var a_p;\n            return typeof {};\n        }());\n    }\n    expect_stdout: \"object\"\n}\n\nissue_5498: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            __proto__: 42,\n        };\n        while (console.log(typeof o.__proto__));\n    }\n    expect: {\n        var o = {\n            __proto__: 42,\n        };\n        while (console.log(typeof o.__proto__));\n    }\n    expect_stdout: \"object\"\n}\n"
  },
  {
    "path": "test/compress/hoist_vars.js",
    "content": "statements: {\n    options = {\n        hoist_funs: false,\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = 1;\n            var b = 2;\n            var c = 3;\n            function g() {}\n            return g(a, b, c);\n        }\n    }\n    expect: {\n        function f() {\n            var a = 1, b = 2, c = 3;\n            function g() {}\n            return g(a, b, c);\n        }\n    }\n}\n\nstatements_funs: {\n    options = {\n        hoist_funs: true,\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = 1;\n            var b = 2;\n            var c = 3;\n            function g() {}\n            return g(a, b, c);\n        }\n    }\n    expect: {\n        function f() {\n            function g() {}\n            var a = 1, b = 2, c = 3;\n            return g(a, b, c);\n        }\n    }\n}\n\nsequences: {\n    options = {\n        hoist_funs: false,\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = 1, b = 2;\n            function g() {}\n            var c = 3;\n            return g(a, b, c);\n        }\n    }\n    expect: {\n        function f() {\n            var c, a = 1, b = 2;\n            function g() {}\n            c = 3;\n            return g(a, b, c);\n        }\n    }\n}\n\nsequences_funs: {\n    options = {\n        hoist_funs: true,\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = 1, b = 2;\n            function g() {}\n            var c = 3;\n            return g(a, b, c);\n        }\n    }\n    expect: {\n        function f() {\n            function g() {}\n            var a = 1, b = 2, c = 3;\n            return g(a, b, c);\n        }\n    }\n}\n\ncatch_var: {\n    options = {\n        dead_code: true,\n        hoist_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            a;\n        } catch (a) {\n            var a = 0;\n            a;\n        }\n        console.log(a);\n    }\n    expect: {\n        a = \"PASS\";\n        var a;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2295: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        function foo(o) {\n            var a = o.a;\n            if (a) return a;\n            var a = 1;\n        }\n    }\n    expect: {\n        function foo(o) {\n            var a = o.a;\n            if (a) return a;\n            a = 1;\n        }\n    }\n}\n\nissue_4487_1: {\n    options = {\n        functions: true,\n        hoist_vars: true,\n        join_vars: true,\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            var f = console.log(typeof f);\n        };\n        var b = a();\n    }\n    expect: {\n        var a = function f() {\n            var f = console.log(typeof f);\n        };\n        a();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4487_2: {\n    options = {\n        functions: true,\n        hoist_vars: true,\n        join_vars: true,\n        keep_fnames: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            var f = console.log(typeof f);\n        };\n        var b = a();\n    }\n    expect: {\n        function a() {\n            var f = console.log(typeof f);\n        }\n        a();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4487_3: {\n    options = {\n        functions: true,\n        hoist_vars: true,\n        join_vars: true,\n        keep_fnames: true,\n        passes: 3,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            var f = console.log(typeof f);\n        };\n        var b = a();\n    }\n    expect: {\n        (function a() {\n            console.log(typeof void 0);\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4489: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = 0;\n        var o = !0 || null;\n        for (var k in o);\n        console.log(k);\n    }\n    expect: {\n        for (var k in !(A = 0));\n        console.log(k);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4517: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        join_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 2;\n            A = a;\n            var b = typeof !1;\n            return A + b;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return (A = 2) + typeof !1;\n        }());\n    }\n    expect_stdout: \"2boolean\"\n}\n\nissue_4736: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        hoist_vars: true,\n        join_vars: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f() {\n            (function g() {\n                var b = (a = 0, 1 << 30);\n                var c = (a = 0, console.log(b));\n                var d = c;\n            })(f);\n        }\n        f();\n    }\n    expect: {\n        (function() {\n            (function() {\n                0;\n                console.log(1 << 30);\n            })();\n        })();\n    }\n    expect_stdout: \"1073741824\"\n}\n\nissue_4839: {\n    options = {\n        evaluate: true,\n        hoist_vars: true,\n        join_vars: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var log = console.log, o = function(a, b) {\n            return b && b;\n        }(\"foo\");\n        for (var k in o)\n            throw \"FAIL\";\n        log(\"PASS\");\n    }\n    expect: {\n        var k, log = console.log;\n        for (k in void 0)\n            throw \"FAIL\";\n        log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4859: {\n    options = {\n        evaluate: true,\n        hoist_vars: true,\n        join_vars: true,\n        keep_infinity: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b = (a = 2, 1 / 0), c = 3;\n            var d = a + b;\n            console.log(d);\n            return f;\n        }\n        f();\n    }\n    expect: {\n        (function f(a) {\n            console.log(2 + 1 / 0);\n            return f;\n        })();\n    }\n    expect_stdout: \"Infinity\"\n}\n\nissue_4893_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {}\n            var a = null;\n            var b = null;\n            var c = null;\n            b.p += a = 42;\n            f;\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try{\n            (function() {\n                null.p += 42;\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4893_2: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {}\n            var a = null;\n            var b = null;\n            var c = null;\n            b.p += a = 42;\n            f;\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try{\n            (function() {\n                null.p += 42;\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4898: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        hoist_vars: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        do {\n            var b = [ console.log(\"PASS\") ];\n            var c = b;\n        } while (c.p = 0);\n    }\n    expect: {\n        var b;\n        b = [ console.log(\"PASS\") ];\n        b.p = 0;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5187_1: {\n    options = {\n        hoist_props: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = 42;\n            do {\n                var b = { 0: a++ };\n            } while (console.log(b[b ^= 0]));\n        }\n        f();\n    }\n    expect: {\n        (function() {\n            var a, b;\n            a = 42;\n            do {\n                b = { 0: a++ };\n            } while (console.log(b[b ^= 0]));\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5187_2: {\n    options = {\n        hoist_props: true,\n        hoist_vars: true,\n        join_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = 42;\n            do {\n                var b = { 0: a++ };\n            } while (console.log(b[b ^= 0]));\n        }\n        f();\n    }\n    expect: {\n        (function() {\n            var b, a = 42;\n            do {\n                b = { 0: a++ };\n            } while (console.log(b[b ^= 0]));\n        })();\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5195: {\n    options = {\n        hoist_props: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a;\n            do {\n                var b = { p: a };\n            } while (console.log(b += \"\"));\n        }\n        f();\n    }\n    expect: {\n        (function() {\n            var a, b;\n            do {\n                b = { p: a };\n            } while (console.log(b += \"\"));\n        })();\n    }\n    expect_stdout: \"[object Object]\"\n}\n\nissue_5378: {\n    options = {\n        hoist_vars: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 2;\n        while (a--)\n            (function() {\n                var b;\n                var c;\n                while (console.log(b));\n                --b;\n            })();\n    }\n    expect: {\n        var a = 2;\n        while (a--) {\n            b = void 0;\n            var b, c;\n            while (console.log(b));\n            --b;\n        }\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\nissue_5411_1: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        b++;\n        b = a;\n        var b = b, c = c && c[b];\n        console.log(b);\n    }\n    expect: {\n        var a, b, c;\n        b++;\n        b = a = \"PASS\";\n        c = c && c[b];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5411_2: {\n    options = {\n        collapse_vars: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        b++;\n        b = a;\n        var b = b, c = c && c[b];\n        console.log(b);\n    }\n    expect: {\n        var b, c;\n        b++,\n        b = \"PASS\",\n        c,\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5411_3: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = console;\n        a++;\n        var a = A = a;\n        console.log(A);\n    }\n    expect: {\n        var a;\n        a = console;\n        a = A = ++a;\n        console.log(A);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5411_4: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = console;\n        a++;\n        var a = A = a;\n        console.log(A);\n    }\n    expect: {\n        var a = console;\n        a = A = ++a;\n        console.log(A);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5626: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function() {\n            return console.log(arguments[0]), 42;\n        }(\"PASS\") ? null : \"foo\";\n        for (var b in a)\n            FAIL;\n    }\n    expect: {\n        (function() {\n            console.log(arguments[0]);\n        }(\"PASS\"));\n        for (var b in null)\n            FAIL;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5638_1: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var a = [ 42 ];\n        console || FAIL(a);\n        console.log(a++);\n    }\n    expect: {\n        var a;\n        a = \"FAIL\";\n        a = [ 42 ];\n        console || FAIL(a);\n        console.log(a++);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5638_2: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var a = [ 6 ];\n        console || FAIL(a);\n        console.log(a *= 7);\n    }\n    expect: {\n        var a;\n        a = \"FAIL\";\n        a = [ 6 ];\n        console || FAIL(a);\n        console.log(a *= 7);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5638_3: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var o = { foo: 42 };\n        for (var k in o) {\n            var v = o[k];\n            log(k || v, v++);\n        }\n    }\n    expect: {\n        var log, o, k, v;\n        log = console.log;\n        for (k in o = { foo: 42 }) {\n            v = o[k];\n            log(k || v, v++);\n        }\n    }\n    expect_stdout: \"foo 42\"\n}\n\nissue_5638_4: {\n    options = {\n        collapse_vars: true,\n        hoist_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var o = { foo: 6 };\n        for (var k in o) {\n            var v = o[k];\n            log(k || v, v *= 7);\n        }\n    }\n    expect: {\n        var log, o, k, v;\n        log = console.log;\n        for (k in o = { foo: 6 }) {\n            v = o[k];\n            log(k || v, v *= 7);\n        }\n    }\n    expect_stdout: \"foo 42\"\n}\n\nissue_5884_1: {\n    options = {\n        hoist_vars: true,\n        inline: true,\n        join_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            var f = function() {\n                var a = [ \"PASS\" ];\n                for (b in a)\n                    console.log(a[b]);\n            };\n            f();\n        } finally {\n            var b;\n        }\n    }\n    expect: {\n        var b;\n        try {\n            (function() {\n                var a = [ \"PASS\" ];\n                for (b in a)\n                    console.log(a[b]);\n            })();\n        } finally {}\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5884_2: {\n    options = {\n        hoist_vars: true,\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            var f = function() {\n                var a = [ \"PASS\" ];\n                for (b in a)\n                    console.log(a[b]);\n            };\n            f();\n        } finally {\n            var b;\n        }\n    }\n    expect: {\n        try {\n            var a = [ \"PASS\" ];\n            for (var b in a)\n                console.log(a[b]);\n        } finally {}\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/html_comments.js",
    "content": "html_comment_in_expression: {\n    input: {\n        (function(a, b) {\n            console.log(a < !--b && a-- > b, a, b);\n        })(1, 2);\n    }\n    expect_exact: \"(function(a,b){console.log(a<! --b&&a-- >b,a,b)})(1,2);\"\n    expect_stdout: \"false 1 1\"\n}\n\nhtml_comment_in_less_than: {\n    input: {\n        (function(a, b, c) {\n            console.log(\n                a < !--b,\n                a < !--b + c,\n                a + b < !--c,\n                a, b, c\n            );\n        })(1, 2, 3);\n    }\n    expect_exact: \"(function(a,b,c){console.log(a<! --b,a<! --b+c,a+b<! --c,a,b,c)})(1,2,3);\"\n    expect_stdout: \"false true false 1 0 2\"\n}\n\nhtml_comment_in_left_shift: {\n    input: {\n        (function(a, b, c) {\n            console.log(\n                a << !--b,\n                a << !--b + c,\n                a + b << !--c,\n                a, b, c\n            );\n        })(1, 2, 3);\n    }\n    expect_exact: \"(function(a,b,c){console.log(a<<! --b,a<<! --b+c,a+b<<! --c,a,b,c)})(1,2,3);\"\n    expect_stdout: \"1 16 1 1 0 2\"\n}\n\nhtml_comment_in_greater_than: {\n    input: {\n        (function(a, b, c) {\n            console.log(\n                a-- > b,\n                a-- > b + c,\n                a + b-- > c,\n                a, b, c\n            );\n        })(1, 2, 3);\n    }\n    expect_exact: \"(function(a,b,c){console.log(a-- >b,a-- >b+c,a+b-- >c,a,b,c)})(1,2,3);\"\n    expect_stdout: \"false false false -1 1 3\"\n}\n\nhtml_comment_in_greater_than_or_equal: {\n    input: {\n        (function(a, b, c) {\n            console.log(\n                a-- >= b,\n                a-- >= b + c,\n                a + b-- >= c,\n                a, b, c\n            );\n        })(1, 2, 3);\n    }\n    expect_exact: \"(function(a,b,c){console.log(a-- >=b,a-- >=b+c,a+b-- >=c,a,b,c)})(1,2,3);\"\n    expect_stdout: \"false false false -1 1 3\"\n}\n\nhtml_comment_in_right_shift: {\n    input: {\n        (function(a, b, c) {\n            console.log(\n                a-- >> b,\n                a-- >> b + c,\n                a + b-- >> c,\n                a, b, c\n            );\n        })(1, 2, 3);\n    }\n    expect_exact: \"(function(a,b,c){console.log(a-- >>b,a-- >>b+c,a+b-- >>c,a,b,c)})(1,2,3);\"\n    expect_stdout: \"0 0 0 -1 1 3\"\n}\n\nhtml_comment_in_zero_fill_right_shift: {\n    input: {\n        (function(a, b, c) {\n            console.log(\n                a-- >>> b,\n                a-- >>> b + c,\n                a + b-- >>> c,\n                a, b, c\n            );\n        })(1, 2, 3);\n    }\n    expect_exact: \"(function(a,b,c){console.log(a-- >>>b,a-- >>>b+c,a+b-- >>>c,a,b,c)})(1,2,3);\"\n    expect_stdout: \"0 0 0 -1 1 3\"\n}\n\nhtml_comment_in_string_literal: {\n    input: {\n        console.log(\"<!--HTML-->comment in<!--string literal-->\".length);\n    }\n    expect_exact: 'console.log(\"\\\\x3c!--HTML--\\\\x3ecomment in\\\\x3c!--string literal--\\\\x3e\".length);'\n    expect_stdout: \"42\"\n}\n"
  },
  {
    "path": "test/compress/ie.js",
    "content": "do_screw: {\n    options = {\n        ie: false,\n    }\n    beautify = {\n        ie: false,\n        ascii_only: true,\n    }\n    input: {\n        f(\"\\v\");\n    }\n    expect_exact: 'f(\"\\\\v\");'\n}\n\ndont_screw: {\n    options = {\n        ie: true,\n    }\n    beautify = {\n        ie: true,\n        ascii_only: true,\n    }\n    input: {\n        f(\"\\v\");\n    }\n    expect_exact: 'f(\"\\\\x0B\");'\n}\n\ndo_screw_constants: {\n    options = {\n        ie: false,\n    }\n    input: {\n        f(undefined, Infinity);\n    }\n    expect_exact: \"f(void 0,1/0);\"\n}\n\ndont_screw_constants: {\n    options = {\n        ie: true,\n    }\n    input: {\n        f(undefined, Infinity);\n    }\n    expect_exact: \"f(undefined,Infinity);\"\n}\n\ndo_screw_try_catch: {\n    options = {\n        ie: false,\n    }\n    mangle = {\n        ie: false,\n    }\n    beautify = {\n        ie: false,\n    }\n    input: {\n        good = function(e){\n            return function(error){\n                try {\n                    e()\n                } catch (e) {\n                    error(e)\n                }\n            }\n        };\n    }\n    expect: {\n        good = function(n){\n            return function(t){\n                try {\n                    n()\n                } catch (n) {\n                    t(n)\n                }\n            }\n        };\n    }\n}\n\ndont_screw_try_catch: {\n    options = {\n        ie: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    beautify = {\n        ie: true,\n    }\n    input: {\n        bad = function(e){\n            return function(error){\n                try {\n                    e()\n                } catch (e) {\n                    error(e)\n                }\n            }\n        };\n    }\n    expect: {\n        bad = function(t){\n            return function(n){\n                try {\n                    t()\n                } catch (t) {\n                    n(t)\n                }\n            }\n        };\n    }\n}\n\ndo_screw_try_catch_undefined: {\n    options = {\n        ie: false,\n    }\n    mangle = {\n        ie: false,\n    }\n    beautify = {\n        ie: false,\n    }\n    input: {\n        function a(b) {\n            try {\n                throw \"Stuff\";\n            } catch (undefined) {\n                console.log(\"caught: \" + undefined);\n            }\n            console.log(\"undefined is \" + undefined);\n            return b === undefined;\n        }\n        console.log(a(42), a(void 0));\n    }\n    expect: {\n        function a(o) {\n            try {\n                throw \"Stuff\";\n            } catch (o) {\n                console.log(\"caught: \" + o);\n            }\n            console.log(\"undefined is \" + void 0);\n            return void 0 === o;\n        }\n        console.log(a(42), a(void 0));\n    }\n    expect_stdout: [\n        \"caught: Stuff\",\n        \"undefined is undefined\",\n        \"caught: Stuff\",\n        \"undefined is undefined\",\n        \"false true\",\n    ]\n}\n\ndont_screw_try_catch_undefined: {\n    options = {\n        ie: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    beautify = {\n        ie: true,\n    }\n    input: {\n        function a(b) {\n            try {\n                throw \"Stuff\";\n            } catch (undefined) {\n                console.log(\"caught: \" + undefined);\n            }\n            // IE8: undefined is Stuff\n            console.log(\"undefined is \" + undefined);\n            return b === undefined;\n        }\n        console.log(a(42), a(void 0));\n    }\n    expect: {\n        function a(n) {\n            try {\n                throw \"Stuff\";\n            } catch (undefined) {\n                console.log(\"caught: \" + undefined);\n            }\n            console.log(\"undefined is \" + undefined);\n            return n === undefined;\n        }\n        console.log(a(42), a(void 0));\n    }\n    expect_stdout: [\n        \"caught: Stuff\",\n        \"undefined is undefined\",\n        \"caught: Stuff\",\n        \"undefined is undefined\",\n        \"false true\",\n    ]\n}\n\nreduce_vars: {\n    options = {\n        evaluate: true,\n        ie: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    input: {\n        function f() {\n            var a;\n            try {\n                x();\n            } catch (a) {\n                y();\n            }\n            alert(a);\n        }\n    }\n    expect: {\n        function f() {\n            var t;\n            try {\n                x();\n            } catch (t) {\n                y();\n            }\n            alert(t);\n        }\n    }\n}\n\ntypeof_getAttribute: {\n    options = {\n        comparisons: true,\n        ie: false,\n        typeofs: true,\n    }\n    input: {\n        document = {\n            createElement: function() {\n                return {\n                    getAttribute: function() {},\n                };\n            },\n            write: console.log,\n        };\n        document.write(function(element) {\n            if (element)\n                return \"undefined\" === typeof element.getAttribute;\n        }(document.createElement(\"foo\")) ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        document = {\n            createElement: function() {\n                return {\n                    getAttribute: function() {},\n                };\n            },\n            write: console.log,\n        };\n        document.write(function(element) {\n            if (element)\n                // IE6~10: Access is denied.\n                return void 0 === element.getAttribute;\n        }(document.createElement(\"foo\")) ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ntypeof_getAttribute_ie6: {\n    options = {\n        comparisons: true,\n        ie: true,\n        typeofs: true,\n    }\n    input: {\n        document = {\n            createElement: function() {\n                return {\n                    getAttribute: function() {},\n                };\n            },\n            write: console.log,\n        };\n        document.write(function(element) {\n            if (element)\n                return \"undefined\" === typeof element.getAttribute;\n        }(document.createElement(\"foo\")) ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        document = {\n            createElement: function() {\n                return {\n                    getAttribute: function() {},\n                };\n            },\n            write: console.log,\n        };\n        document.write(function(element) {\n            if (element)\n                return \"undefined\" == typeof element.getAttribute;\n        }(document.createElement(\"foo\")) ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1586_1: {\n    options = {\n        ie: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    input: {\n        function f() {\n            try {\n                x();\n            } catch (err) {\n                console.log(err.message);\n            }\n        }\n    }\n    expect_exact: \"function f(){try{x()}catch(c){console.log(c.message)}}\"\n}\n\nissue_1586_2: {\n    options = {\n        ie: false,\n    }\n    mangle = {\n        ie: false,\n    }\n    input: {\n        function f() {\n            try {\n                x();\n            } catch (err) {\n                console.log(err.message);\n            }\n        }\n    }\n    expect_exact: \"function f(){try{x()}catch(c){console.log(c.message)}}\"\n}\n\nissue_2120_1: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (c) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (c) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (t) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (t) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2120_2: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (c) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (c) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (c) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (c) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2254_1: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        \"eeeeee\";\n        try {\n            console.log(f(\"PASS\"));\n        } catch (e) {}\n        function f(s) {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return s;\n            }\n        }\n    }\n    expect: {\n        \"eeeeee\";\n        try {\n            console.log(f(\"PASS\"));\n        } catch (e) {}\n        function f(t) {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return t;\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2254_2: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        \"eeeeee\";\n        try {\n            console.log(f(\"PASS\"));\n        } catch (e) {}\n        function f(s) {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return s;\n            }\n        }\n    }\n    expect: {\n        \"eeeeee\";\n        try {\n            console.log(f(\"PASS\"));\n        } catch (e) {}\n        function f(t) {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                return t;\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_24_1: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        (function(a) {\n            console.log(typeof function f(){} === typeof a ? \"FAIL\" : \"PASS\");\n        })();\n    }\n    expect: {\n        (function(o) {\n            console.log(typeof function o(){} === typeof o ? \"FAIL\" : \"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_24_2: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        (function(a) {\n            console.log(typeof function f(){} === typeof a ? \"FAIL\" : \"PASS\");\n        })();\n    }\n    expect: {\n        (function(o) {\n            console.log(typeof function n(){} === typeof o ? \"FAIL\" : \"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2976_1: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        console.log(function f() {\n            var a;\n            return a === f ? \"FAIL\" : \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function n() {\n            var o;\n            return o === n ? \"FAIL\" : \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2976_2: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        console.log(function f() {\n            var a;\n            return a === f ? \"FAIL\" : \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            var n;\n            return n === f ? \"FAIL\" : \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2976_3: {\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(function f() {\n            var a;\n            return a === f ? \"FAIL\" : \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function o() {\n            var n;\n            return n === o ? \"FAIL\" : \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3035: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(a) {\n            try {\n                throw 1;\n            } catch (b) {\n                try {\n                    throw 0;\n                } catch (a) {\n                    b && (c = \"PASS\");\n                }\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(o) {\n            try {\n                throw 1;\n            } catch (t) {\n                try {\n                    throw 0;\n                } catch (o) {\n                    t && (c = \"PASS\");\n                }\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3035_ie8: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(a) {\n            try {\n                throw 1;\n            } catch (b) {\n                try {\n                    throw 0;\n                } catch (a) {\n                    b && (c = \"PASS\");\n                }\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(t) {\n            try {\n                throw 1;\n            } catch (o) {\n                try {\n                    throw 0;\n                } catch (t) {\n                    o && (c = \"PASS\");\n                }\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3197_1: {\n    options = {\n        ie: false,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {\n        ie: false,\n    }\n    input: {\n        !function() {\n            function Foo() {\n                console.log(this instanceof Foo);\n            }\n            window.Foo = Foo;\n        }();\n        new window.Foo();\n    }\n    expect: {\n        window.Foo = function o() {\n            console.log(this instanceof o);\n        };\n        new window.Foo();\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3197_1_ie8: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    input: {\n        !function() {\n            function Foo() {\n                console.log(this instanceof Foo);\n            }\n            window.Foo = Foo;\n        }();\n        new window.Foo();\n    }\n    expect: {\n        window.Foo = function Foo() {\n            console.log(this instanceof Foo);\n        };\n        new window.Foo();\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3197_2: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        (function(a) {\n            var f = function f() {\n                console.log(this instanceof f);\n            };\n            new f(a);\n        })();\n    }\n    expect: {\n        (function(n) {\n            var o = function n() {\n                console.log(this instanceof n);\n            };\n            new o(n);\n        })();\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3197_2_ie8: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        (function(a) {\n            var f = function f() {\n                console.log(this instanceof f);\n            };\n            new f(a);\n        })();\n    }\n    expect: {\n        (function(n) {\n            var o = function o() {\n                console.log(this instanceof o);\n            };\n            new o(n);\n        })();\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3206_1: {\n    options = {\n        evaluate: true,\n        ie: false,\n        reduce_vars: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var foo = function bar() {};\n            var baz = function moo() {};\n            return \"function\" == typeof bar;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return \"function\" == typeof bar;\n        }());\n    }\n    expect_stdout: \"false\"\n}\n\nissue_3206_2: {\n    options = {\n        evaluate: true,\n        ie: true,\n        reduce_vars: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var foo = function bar() {};\n            var baz = function moo() {};\n            return \"function\" == typeof bar;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            (function bar() {});\n            return \"function\" == typeof bar;\n        }());\n    }\n    expect_stdout: \"false\"\n}\n\nissue_3215_1: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        console.log(function foo() {\n            var bar = function bar(name) {\n                return \"PASS\";\n            };\n            try {\n                \"moo\";\n            } catch (e) {\n                bar = function bar(name) {\n                    return \"FAIL\";\n                };\n            }\n            return bar;\n        }()());\n    }\n    expect: {\n        console.log(function n() {\n            var o = function n(o) {\n                return \"PASS\";\n            };\n            try {\n                \"moo\";\n            } catch (n) {\n                o = function n(o) {\n                    return \"FAIL\";\n                };\n            }\n            return o;\n        }()());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3215_2: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        console.log(function foo() {\n            var bar = function bar(name) {\n                return \"PASS\";\n            };\n            try {\n                \"moo\";\n            } catch (e) {\n                bar = function bar(name) {\n                    return \"FAIL\";\n                };\n            }\n            return bar;\n        }()());\n    }\n    expect: {\n        console.log(function foo() {\n            var o = function o(n) {\n                return \"PASS\";\n            };\n            try {\n                \"moo\";\n            } catch (n) {\n                o = function o(n) {\n                    return \"FAIL\";\n                };\n            }\n            return o;\n        }()());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3215_3: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        console.log(function foo() {\n            var bar = function bar(name) {\n                return \"FAIL\";\n            };\n            try {\n                moo;\n            } catch (e) {\n                bar = function bar(name) {\n                    return \"PASS\";\n                };\n            }\n            return bar;\n        }()());\n    }\n    expect: {\n        console.log(function n() {\n            var o = function n(o) {\n                return \"FAIL\";\n            };\n            try {\n                moo;\n            } catch (n) {\n                o = function n(o) {\n                    return \"PASS\";\n                };\n            }\n            return o;\n        }()());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3215_4: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        console.log(function foo() {\n            var bar = function bar(name) {\n                return \"FAIL\";\n            };\n            try {\n                moo;\n            } catch (e) {\n                bar = function bar(name) {\n                    return \"PASS\";\n                };\n            }\n            return bar;\n        }()());\n    }\n    expect: {\n        console.log(function foo() {\n            var o = function o(n) {\n                return \"FAIL\";\n            };\n            try {\n                moo;\n            } catch (n) {\n                o = function o(n) {\n                    return \"PASS\";\n                };\n            }\n            return o;\n        }()());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3355_1: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        (function f() {\n            var f;\n        })();\n        (function g() {\n        })();\n        console.log(typeof f === typeof g);\n    }\n    expect: {\n        (function o() {\n            var o;\n        })();\n        (function o() {\n        })();\n        console.log(typeof f === typeof g);\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3355_2: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        (function f() {\n            var f;\n        })();\n        (function g() {\n        })();\n        console.log(typeof f === typeof g);\n    }\n    expect: {\n        (function f() {\n            var f;\n        })();\n        (function g() {\n        })();\n        console.log(typeof f === typeof g);\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3355_3: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        !function(a) {\n            \"aaaaaaaaaa\";\n            a();\n            var b = function c() {\n                var c = 42;\n                console.log(\"FAIL\");\n            };\n        }(function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect: {\n        !function(a) {\n            \"aaaaaaaaaa\";\n            a();\n            var o = function a() {\n                var a = 42;\n                console.log(\"FAIL\");\n            };\n        }(function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3355_4: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        !function(a) {\n            \"aaaaaaaaaa\";\n            a();\n            var b = function c() {\n                var c = 42;\n                console.log(\"FAIL\");\n            };\n        }(function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect: {\n        !function(a) {\n            \"aaaaaaaaaa\";\n            a();\n            var o = function n() {\n                var n = 42;\n                console.log(\"FAIL\");\n            };\n        }(function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3468: {\n    options = {\n        collapse_vars: true,\n        ie: false,\n    }\n    input: {\n        var a = 42;\n        console.log(function a() {\n            a++;\n            return typeof a;\n        }());\n    }\n    expect: {\n        var a = 42;\n        console.log(function a() {\n            a++;\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3468_ie8: {\n    options = {\n        collapse_vars: true,\n        ie: true,\n    }\n    input: {\n        var a = 42;\n        console.log(function a() {\n            a++;\n            return typeof a;\n        }());\n    }\n    expect: {\n        var a = 42;\n        console.log(function a() {\n            a++;\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3471: {\n    options = {\n        ie: false,\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var c = 1;\n        function f() {\n            var a = function g() {\n                --c && f();\n                g.p = 0;\n            };\n            for (var p in a)\n                a[p];\n        }\n        f();\n    }\n    expect: {\n        var c = 1;\n        (function f() {\n            function a() {\n                --c && f();\n                a.p = 0;\n            }\n            for (var p in a)\n                a[p];\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_3471_ie8: {\n    options = {\n        ie: true,\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var c = 1;\n        function f() {\n            var a = function g() {\n                --c && f();\n                g.p = 0;\n            };\n            for (var p in a)\n                a[p];\n        }\n        f();\n    }\n    expect: {\n        var c = 1;\n        (function f() {\n            var a = function g() {\n                --c && f();\n                g.p = 0;\n            };\n            for (var p in a)\n                a[p];\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_3473: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var d = 42, a = 100, b = 10, c = 0;\n        (function b() {\n            try {\n                c++;\n            } catch (b) {}\n        })();\n        console.log(a, b, c);\n    }\n    expect: {\n        var d = 42, a = 100, b = 10, c = 0;\n        (function a() {\n            try {\n                c++;\n            } catch (a) {}\n        })();\n        console.log(a, b, c);\n    }\n    expect_stdout: \"100 10 1\"\n}\n\nissue_3473_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var d = 42, a = 100, b = 10, c = 0;\n        (function b() {\n            try {\n                c++;\n            } catch (b) {}\n        })();\n        console.log(a, b, c);\n    }\n    expect: {\n        var d = 42, a = 100, b = 10, c = 0;\n        (function b() {\n            try {\n                c++;\n            } catch (b) {}\n        })();\n        console.log(a, b, c);\n    }\n    expect_stdout: \"100 10 1\"\n}\n\nissue_3473_toplevel: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var d = 42, a = 100, b = 10, c = 0;\n        (function b() {\n            try {\n                c++;\n            } catch (b) {}\n        })();\n        console.log(a, b, c);\n    }\n    expect: {\n        var c = 42, o = 100, n = 10, t = 0;\n        (function c() {\n            try {\n                t++;\n            } catch (c) {}\n        })();\n        console.log(o, n, t);\n    }\n    expect_stdout: \"100 10 1\"\n}\n\nissue_3473_ie8_toplevel: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var d = 42, a = 100, b = 10, c = 0;\n        (function b() {\n            try {\n                c++;\n            } catch (b) {}\n        })();\n        console.log(a, b, c);\n    }\n    expect: {\n        var c = 42, o = 100, n = 10, t = 0;\n        (function n() {\n            try {\n                t++;\n            } catch (n) {}\n        })();\n        console.log(o, n, t);\n    }\n    expect_stdout: \"100 10 1\"\n}\n\nissue_3475: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        \"ooooo ddddd\";\n        var a = \"FAIL\";\n        try {\n            throw 42;\n        } catch (b) {\n            (function f() {\n                a = \"PASS\";\n            })();\n        }\n        console.log(a);\n    }\n    expect: {\n        \"ooooo ddddd\";\n        var a = \"FAIL\";\n        try {\n            throw 42;\n        } catch (o) {\n            (function o() {\n                a = \"PASS\";\n            })();\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3475_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        \"ooooo ddddd\";\n        var a = \"FAIL\";\n        try {\n            throw 42;\n        } catch (b) {\n            (function f() {\n                a = \"PASS\";\n            })();\n        }\n        console.log(a);\n    }\n    expect: {\n        \"ooooo ddddd\";\n        var a = \"FAIL\";\n        try {\n            throw 42;\n        } catch (b) {\n            (function f() {\n                a = \"PASS\";\n            })();\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3475_toplevel: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        \"ooooo ddddd\";\n        var a = \"FAIL\";\n        try {\n            throw 42;\n        } catch (b) {\n            (function f() {\n                a = \"PASS\";\n            })();\n        }\n        console.log(a);\n    }\n    expect: {\n        \"ooooo ddddd\";\n        var d = \"FAIL\";\n        try {\n            throw 42;\n        } catch (o) {\n            (function o() {\n                d = \"PASS\";\n            })();\n        }\n        console.log(d);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3475_ie8_toplevel: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        \"ooooo ddddd\";\n        var a = \"FAIL\";\n        try {\n            throw 42;\n        } catch (b) {\n            (function f() {\n                a = \"PASS\";\n            })();\n        }\n        console.log(a);\n    }\n    expect: {\n        \"ooooo ddddd\";\n        var o = \"FAIL\";\n        try {\n            throw 42;\n        } catch (d) {\n            (function c() {\n                o = \"PASS\";\n            })();\n        }\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3478_1: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        \"aaaaaaaaaa\";\n        (function f() {\n            (function f() {\n                var a;\n                console.log(typeof f);\n            })();\n        })();\n    }\n    expect: {\n        \"aaaaaaaaaa\";\n        (function a() {\n            (function a() {\n                var o;\n                console.log(typeof a);\n            })();\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3478_1_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        \"aaaaaaaaaa\";\n        (function f() {\n            (function f() {\n                var a;\n                console.log(typeof f);\n            })();\n        })();\n    }\n    expect: {\n        \"aaaaaaaaaa\";\n        (function f() {\n            (function f() {\n                var a;\n                console.log(typeof f);\n            })();\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3478_1_toplevel: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        \"aaaaaaaaaa\";\n        (function f() {\n            (function f() {\n                var a;\n                console.log(typeof f);\n            })();\n        })();\n    }\n    expect: {\n        \"aaaaaaaaaa\";\n        (function a() {\n            (function a() {\n                var o;\n                console.log(typeof a);\n            })();\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3478_1_ie8_toplevel: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        \"aaaaaaaaaa\";\n        (function f() {\n            (function f() {\n                var a;\n                console.log(typeof f);\n            })();\n        })();\n    }\n    expect: {\n        \"aaaaaaaaaa\";\n        (function o() {\n            (function o() {\n                var a;\n                console.log(typeof o);\n            })();\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3478_2: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        \"bbbbbbb\";\n        var c = \"FAIL\";\n        (function f() {\n            (function f() {\n                var b = function g() {\n                    f && (c = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        \"bbbbbbb\";\n        var c = \"FAIL\";\n        (function b() {\n            (function n() {\n                var b = function b() {\n                    n && (c = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3478_2_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        \"bbbbbbb\";\n        var c = \"FAIL\";\n        (function f() {\n            (function f() {\n                var b = function g() {\n                    f && (c = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        \"bbbbbbb\";\n        var c = \"FAIL\";\n        (function f() {\n            (function f() {\n                var b = function n() {\n                    f && (c = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3478_2_toplevel: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        \"bbbbbbb\";\n        var c = \"FAIL\";\n        (function f() {\n            (function f() {\n                var b = function g() {\n                    f && (c = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        \"bbbbbbb\";\n        var o = \"FAIL\";\n        (function b() {\n            (function n() {\n                var b = function b() {\n                    n && (o = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3478_2_ie8_toplevel: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        \"bbbbbbb\";\n        var c = \"FAIL\";\n        (function f() {\n            (function f() {\n                var b = function g() {\n                    f && (c = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        \"bbbbbbb\";\n        var o = \"FAIL\";\n        (function c() {\n            (function c() {\n                var b = function n() {\n                    c && (o = \"PASS\");\n                }();\n            })();\n        })();\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3482_1: {\n    options = {\n        evaluate: true,\n        ie: false,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (NaN) {\n            var a = +\"a\";\n        }\n        console.log(a, NaN, 0 / 0);\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (NaN) {\n            var a = 0 / 0;\n        }\n        console.log(a, NaN, NaN);\n    }\n    expect_stdout: \"NaN NaN NaN\"\n}\n\nissue_3482_1_ie8: {\n    options = {\n        evaluate: true,\n        ie: true,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (NaN) {\n            var a = +\"a\";\n        }\n        // IE8: NaN 42 NaN\n        console.log(a, NaN, 0 / 0);\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (NaN) {\n            var a = 0 / 0;\n        }\n        console.log(a, NaN, 0 / 0);\n    }\n    expect_stdout: \"NaN NaN NaN\"\n}\n\nissue_3482_2: {\n    options = {\n        evaluate: true,\n        ie: false,\n    }\n    input: {\n        (function() {\n            try {\n                throw 42;\n            } catch (NaN) {\n                a = +\"a\";\n            }\n        })();\n        console.log(a, NaN, 0 / 0);\n    }\n    expect: {\n        (function() {\n            try {\n                throw 42;\n            } catch (NaN) {\n                a = 0 / 0;\n            }\n        })();\n        console.log(a, NaN, NaN);\n    }\n    expect_stdout: \"NaN NaN NaN\"\n}\n\nissue_3482_2_ie8: {\n    options = {\n        evaluate: true,\n        ie: true,\n    }\n    input: {\n        (function() {\n            try {\n                throw 42;\n            } catch (NaN) {\n                a = +\"a\";\n            }\n        })();\n        console.log(a, NaN, 0 / 0);\n    }\n    expect: {\n        (function() {\n            try {\n                throw 42;\n            } catch (NaN) {\n                a = 0 / 0;\n            }\n        })();\n        console.log(a, NaN, 0 / 0);\n    }\n    expect_stdout: \"NaN NaN NaN\"\n}\n\nissue_3484_1: {\n    options = {\n        ie: false,\n        side_effects: true,\n        toplevel: false,\n    }\n    input: {\n        (function f() {})();\n        console.log(typeof f);\n    }\n    expect: {\n        console.log(typeof f);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3484_1_ie8: {\n    options = {\n        ie: true,\n        side_effects: true,\n        toplevel: false,\n    }\n    input: {\n        (function f() {})();\n        // IE8: function\n        console.log(typeof f);\n    }\n    expect: {\n        (function f() {})();\n        console.log(typeof f);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3484_1_toplevel: {\n    options = {\n        ie: false,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function f() {})();\n        console.log(typeof f);\n    }\n    expect: {\n        console.log(typeof f);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3484_1_ie8_toplevel: {\n    options = {\n        ie: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        (function f() {})();\n        // IE8: function\n        console.log(typeof f);\n    }\n    expect: {\n        (function f() {})();\n        console.log(typeof f);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3484_2: {\n    options = {\n        evaluate: true,\n        ie: false,\n        reduce_vars: true,\n        toplevel: false,\n    }\n    input: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        console.log(typeof (1 / 0), typeof Infinity);\n    }\n    expect: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        console.log(\"number\", \"number\");\n    }\n    expect_stdout: \"number number\"\n}\n\nissue_3484_2_ie8: {\n    options = {\n        evaluate: true,\n        ie: true,\n        reduce_vars: true,\n        toplevel: false,\n    }\n    input: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        // IE8: number function\n        console.log(typeof (1 / 0), typeof Infinity);\n    }\n    expect: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        console.log(\"number\", typeof Infinity);\n    }\n    expect_stdout: \"number number\"\n}\n\nissue_3484_2_toplevel: {\n    options = {\n        evaluate: true,\n        ie: false,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        console.log(typeof (1 / 0), typeof Infinity);\n    }\n    expect: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        console.log(\"number\", \"number\");\n    }\n    expect_stdout: \"number number\"\n}\n\nissue_3484_2_ie8_toplevel: {\n    options = {\n        evaluate: true,\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        // IE8: number function\n        console.log(typeof (1 / 0), typeof Infinity);\n    }\n    expect: {\n        (function Infinity() {\n            var Infinity;\n        })();\n        console.log(\"number\", typeof Infinity);\n    }\n    expect_stdout: \"number number\"\n}\n\nissue_3486: {\n    options = {\n        conditionals: true,\n        ie: false,\n        reduce_vars: true,\n    }\n    input: {\n        (function a() {\n            (function a(a) {\n                console.log(a ? \"FAIL\" : \"PASS\");\n            })();\n        })();\n    }\n    expect: {\n        (function a() {\n            (function a(a) {\n                console.log(a ? \"FAIL\" : \"PASS\");\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3486_ie8: {\n    options = {\n        conditionals: true,\n        ie: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function a() {\n            (function a(a) {\n                console.log(a ? \"FAIL\" : \"PASS\");\n            })();\n        })();\n    }\n    expect: {\n        (function a() {\n            (function a(a) {\n                console.log(a ? \"FAIL\" : \"PASS\");\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3493: {\n    options = {\n        dead_code: true,\n        ie: false,\n    }\n    input: {\n        var c = \"PASS\";\n        (function() {\n            try {\n                (function a() {\n                    throw {};\n                })();\n            } catch (a) {\n                a >>= 0;\n                a && (c = \"FAIL\");\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"PASS\";\n        (function() {\n            try {\n                (function a() {\n                    throw {};\n                })();\n            } catch (a) {\n                a >>= 0;\n                a && (c = \"FAIL\");\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3493_ie8: {\n    options = {\n        dead_code: true,\n        ie: true,\n    }\n    input: {\n        var c = \"PASS\";\n        (function() {\n            try {\n                (function a() {\n                    throw {};\n                })();\n            } catch (a) {\n                a >>= 0;\n                a && (c = \"FAIL\");\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"PASS\";\n        (function() {\n            try {\n                (function a() {\n                    throw {};\n                })();\n            } catch (a) {\n                a >>= 0;\n                a && (c = \"FAIL\");\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523: {\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var f, g, h, i, j, k, l, m, n, o, p, q, r, s;\n        })();\n        try {\n            throw 0;\n        } catch (t) {\n            (function() {\n                (function t() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function e() {\n                try {} catch (t) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var c, n, t, o, a, r, f, i, u, h, l, v, y, A;\n        })();\n        try {\n            throw 0;\n        } catch (n) {\n            (function() {\n                (function n() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function c() {\n                try {} catch (c) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_ie8: {\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var f, g, h, i, j, k, l, m, n, o, p, q, r, s;\n        })();\n        try {\n            throw 0;\n        } catch (t) {\n            (function() {\n                (function t() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function e() {\n                try {} catch (t) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var c, t, n, o, a, r, f, i, u, h, e, l, v, y;\n        })();\n        try {\n            throw 0;\n        } catch (t) {\n            (function() {\n                (function t() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function e() {\n                try {} catch (t) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_toplevel: {\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var f, g, h, i, j, k, l, m, n, o, p, q, r, s;\n        })();\n        try {\n            throw 0;\n        } catch (t) {\n            (function() {\n                (function t() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function e() {\n                try {} catch (t) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var c = 0, n, t = \"FAIL\";\n        (function() {\n            var c, n, t, o, r, a, f, i, u, h, l, v, y, A;\n        })();\n        try {\n            throw 0;\n        } catch (c) {\n            (function() {\n                (function c() {\n                    t = \"PASS\";\n                })();\n            })();\n            (function c() {\n                try {} catch (c) {}\n            })();\n        }\n        console.log(t);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_ie8_toplevel: {\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var f, g, h, i, j, k, l, m, n, o, p, q, r, s;\n        })();\n        try {\n            throw 0;\n        } catch (t) {\n            (function() {\n                (function t() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function e() {\n                try {} catch (t) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var c = 0, n, t = \"FAIL\";\n        (function() {\n            var c, n, t, o, r, a, f, i, u, h, l, v, y, A;\n        })();\n        try {\n            throw 0;\n        } catch (o) {\n            (function() {\n                (function o() {\n                    t = \"PASS\";\n                })();\n            })();\n            (function r() {\n                try {} catch (o) {}\n            })();\n        }\n        console.log(t);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_rename: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var d, e, f, g, h, i, j, k, l, m, o, p, q, r;\n        })();\n        try {\n            throw 0;\n        } catch (e) {\n            (function() {\n                (function e() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function d() {\n                try {\n                } catch (e) {\n                }\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var c, n, t, o, a, r, f, i, u, h, l, v, y, A;\n        })();\n        try {\n            throw 0;\n        } catch (n) {\n            (function() {\n                (function n() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function c() {\n                try {} catch (c) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_rename_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var d, e, f, g, h, i, j, k, l, m, o, p, q, r;\n        })();\n        try {\n            throw 0;\n        } catch (e) {\n            (function() {\n                (function e() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function d() {\n                try {\n                } catch (e) {\n                }\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var c, n, t, o, a, r, e, f, i, u, h, l, v, y;\n        })();\n        try {\n            throw 0;\n        } catch (e) {\n            (function() {\n                (function e() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function d() {\n                try {} catch (e) {}\n            })();\n        }\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_rename_toplevel: {\n    rename = true\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var d, e, f, g, h, i, j, k, l, m, o, p, q, r;\n        })();\n        try {\n            throw 0;\n        } catch (e) {\n            (function() {\n                (function e() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function d() {\n                try {\n                } catch (e) {\n                }\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var c = 0, n, t = \"FAIL\";\n        (function() {\n            var c, n, t, o, r, a, f, i, u, h, l, v, y, A;\n        })();\n        try {\n            throw 0;\n        } catch (c) {\n            (function() {\n                (function c() {\n                    t = \"PASS\";\n                })();\n            })();\n            (function c() {\n                try {} catch (c) {}\n            })();\n        }\n        console.log(t);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3523_rename_ie8_toplevel: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b, c = \"FAIL\";\n        (function() {\n            var d, e, f, g, h, i, j, k, l, m, o, p, q, r;\n        })();\n        try {\n            throw 0;\n        } catch (e) {\n            (function() {\n                (function e() {\n                    c = \"PASS\";\n                })();\n            })();\n            (function d() {\n                try {\n                } catch (e) {\n                }\n            })();\n        }\n        console.log(c);\n    }\n    expect: {\n        var c = 0, n, t = \"FAIL\";\n        (function() {\n            var c, n, t, o, r, a, f, i, u, h, l, v, y, A;\n        })();\n        try {\n            throw 0;\n        } catch (o) {\n            (function() {\n                (function o() {\n                    t = \"PASS\";\n                })();\n            })();\n            (function r() {\n                try {} catch (o) {}\n            })();\n        }\n        console.log(t);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3542: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        var b = a++;\n        var c = b && function a() {} || b;\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        a++;\n        (function a() {});\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3703: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            var b;\n            function g() {\n                a = \"FAIL\";\n            }\n            var c = g;\n            function h() {\n                f;\n            }\n            a ? b |= c : b.p;\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            var b;\n            var c = function() {\n                a = \"FAIL\";\n            };\n            a ? b |= c : b.p;\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3750: {\n    options = {\n        evaluate: true,\n        ie: true,\n    }\n    input: {\n        (function(a) {\n            return function a() {\n                return a && console.log(\"PASS\");\n            }();\n        })();\n    }\n    expect: {\n        (function(a) {\n            return function a() {\n                return a && console.log(\"PASS\");\n            }();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3823: {\n    options = {\n        ie: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var i = 0; i < 1; i++) {\n            var a = a ? function f() {\n                f;\n            } : 0;\n            console.log(\"PASS\", typeof f);\n        }\n    }\n    expect: {\n        for (var i = 0; i < 1; i++) {\n            (function f() {\n                f;\n            });\n            console.log(\"PASS\", typeof f);\n        }\n    }\n    expect_stdout: \"PASS undefined\"\n}\n\nissue_3825: {\n    options = {\n        ie: true,\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        console.log({}[void (0..length ? 1 : 2)]);\n    }\n    expect: {\n        console.log({}[void 0]);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3889: {\n    options = {\n        evaluate: true,\n        ie: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            a = 0;\n            (function a() {\n                var a;\n                console.log(a);\n            })();\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            a = 0;\n            (function a() {\n                var a;\n                console.log(a);\n            })();\n        }\n        f();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3918: {\n    options = {\n        conditionals: true,\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    input: {\n        if (console.log(\"PASS\")) {\n            var a = function f() {\n                f.p;\n                try {\n                    console.log(\"FAIL\");\n                } catch (e) {}\n            }, b = a;\n        }\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\") && (a = function f() {\n            f.p;\n            try {\n                console.log(\"FAIL\");\n            } catch (o) {}\n        }, a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3999: {\n    rename = true\n    mangle = {\n        ie: true,\n    }\n    input: {\n        (function() {\n            (function f() {\n                for (var i = 0; i < 2; i++)\n                    try {\n                        f[0];\n                    } catch (f) {\n                        var f = 0;\n                        console.log(i);\n                    }\n            })();\n        })(typeof f);\n    }\n    expect: {\n        (function() {\n            (function f() {\n                for (var o = 0; o < 2; o++)\n                    try {\n                        f[0];\n                    } catch (f) {\n                        var f = 0;\n                        console.log(o);\n                    }\n            })();\n        })(typeof f);\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n    ]\n}\n\nissue_4001_1: {\n    options = {\n        collapse_vars: true,\n        ie: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: false,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            function f() {\n                return a;\n                var b;\n            }\n            var c = f();\n            (function g() {\n                c[42];\n                f;\n            })();\n            (function a() {});\n        }(42));\n    }\n    expect: {\n        function f() {\n            return a;\n        }\n        var a;\n        console.log((a = 42, f()[42], void f, void function a() {}));\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4001_2: {\n    options = {\n        collapse_vars: true,\n        ie: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            function f() {\n                return a;\n                var b;\n            }\n            var c = f();\n            (function g() {\n                c[42];\n                f;\n            })();\n            (function a() {});\n        }(42));\n    }\n    expect: {\n        function f() {\n            return a;\n        }\n        var a;\n        console.log((a = 42, void f()[42]));\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4015: {\n    rename = true\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var n, a = 0, b;\n        function f() {\n            try {\n                throw 0;\n            } catch (b) {\n                (function g() {\n                    (function b() {\n                        a++;\n                    })();\n                })();\n            }\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var n, o = 0, c;\n        function t() {\n            try {\n                throw 0;\n            } catch (c) {\n                (function n() {\n                    (function c() {\n                        o++;\n                    })();\n                })();\n            }\n        }\n        t();\n        console.log(o);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4019: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = function() {\n            try {\n                console.log(\"FAIL\");\n            } catch (b) {}\n        }, a = (console.log(a.length), ++a);\n    }\n    expect: {\n        var o = function() {\n            try {\n                console.log(\"FAIL\");\n            } catch (o) {}\n        };\n        console.log(o.length),\n        ++o;\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4028: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    input: {\n        function a() {\n            try {\n                A;\n            } catch (e) {}\n        }\n        var b = a += a;\n        console.log(typeof b);\n    }\n    expect: {\n        function a() {\n            try {\n                A;\n            } catch (a) {}\n        }\n        var b = a += a;\n        console.log(typeof b);\n    }\n    expect_stdout: \"string\"\n}\n\nissue_2737: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            a();\n        })(function f() {\n            console.log(typeof f);\n        });\n    }\n    expect: {\n        (function(a) {\n            a();\n        })(function f() {\n            console.log(typeof f);\n        });\n    }\n    expect_stdout: \"function\"\n}\n\nsingle_use_catch_redefined: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n        }\n        console.log(g());\n    }\n    expect: {\n        var a = 1;\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n        }\n        console.log(g());\n    }\n    expect_stdout: true\n}\n\nsingle_use_inline_catch_redefined: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n        }\n        console.log(g());\n    }\n    expect: {\n        var a = 1;\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n        }\n        console.log(g());\n    }\n    expect_stdout: true\n}\n\ndirect_inline_catch_redefined: {\n    options = {\n        ie: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        function f() {\n            return a;\n        }\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n            console.log(a, f(), g());\n        }\n        console.log(a, f(), g());\n    }\n    expect: {\n        var a = 1;\n        function f() {\n            return a;\n        }\n        try {\n            throw 2;\n        } catch (a) {\n            function g() {\n                return a;\n            }\n            console.log(a, f(), g());\n        }\n        console.log(a, a, g());\n    }\n    expect_stdout: true\n}\n\nissue_4186: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        ie: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {\n            (function NaN() {\n                var a = 1;\n                while (a--)\n                    try {} finally {\n                        console.log(0/0);\n                        var b;\n                    }\n            })(f);\n        }\n        f();\n        NaN;\n    }\n    expect: {\n        (function() {\n            (function NaN() {\n                var n = 1;\n                while (n--)\n                    console.log(0/0);\n            })();\n        })();\n        NaN;\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4235: {\n    options = {\n        ie: true,\n        unused: true,\n    }\n    input: {\n        try {} catch (e) {}\n        console.log(function e() {\n            var e = 0;\n        }());\n    }\n    expect: {\n        try {} catch (e) {}\n        console.log(function e() {}());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4250: {\n    options = {\n        ie: true,\n        loops: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {\n            (function() {\n                for (f in \"f\");\n            })();\n            return f;\n            var f;\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            (function() {\n                for (f in \"f\");\n            })();\n            return f;\n            var f;\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4568: {\n    options = {\n        ie: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof f, function(a) {\n            return a.length;\n        }([ function f() {} ]));\n    }\n    expect: {\n        console.log(typeof f, function(a) {\n            return a.length;\n        }([ function f() {} ]));\n    }\n    expect_stdout: \"undefined 1\"\n}\n\nissue_4729: {\n    options = {\n        ie: true,\n        pure_getters: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            f;\n        } catch (e) {\n            var a = a && a[function f() {}];\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            f;\n        } catch (e) {\n            (function f() {});\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4928_1: {\n    options = {\n        ie: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function f() {\n            f(a);\n        };\n        console.log(typeof f);\n    }\n    expect: {\n        var a = function f() {\n            f(a);\n        };\n        console.log(typeof f);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4928_2: {\n    options = {\n        ie: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        switch (42) {\n          case console:\n            var a = function f() {\n                f(a);\n            };\n          case 42:\n            var a = console.log(\"PASS\");\n        }\n    }\n    expect: {\n        switch (42) {\n          case console:\n            var a = function f() {\n                f(a);\n            };\n          case 42:\n            a = console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4958: {\n    options = {\n        collapse_vars: true,\n        ie: true,\n    }\n    input: {\n        console.log(function arguments(a) {\n            a = 21;\n            return arguments[0] + 21;\n        }(\"FAIL\"));\n    }\n    expect: {\n        console.log(function arguments(a) {\n            a = 21;\n            return arguments[0] + 21;\n        }(\"FAIL\"));\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5081_call: {\n    options = {\n        ie: false,\n        merge_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return a(b = \"A\") + (b += \"SS\");\n        }\n        console.log(f(function() {\n            return \"P\";\n        }));\n    }\n    expect: {\n        function f(a) {\n            // IE5-10: TypeError: Function expected\n            return a(a = \"A\") + (a += \"SS\");\n        }\n        console.log(f(function() {\n            return \"P\";\n        }));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5081_call_ie: {\n    options = {\n        ie: true,\n        merge_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return a(b = \"A\") + (b += \"SS\");\n        }\n        console.log(f(function() {\n            return \"P\";\n        }));\n    }\n    expect: {\n        function f(a) {\n            var b;\n            return a(b = \"A\") + (b += \"SS\");\n        }\n        console.log(f(function() {\n            return \"P\";\n        }));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5081_property_access: {\n    options = {\n        ie: false,\n        merge_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return a[b = \"A\"] + (b += \"SS\");\n        }\n        console.log(f({ A: \"P\" }));\n    }\n    expect: {\n        function f(a) {\n            return a[a = \"A\"] + (a += \"SS\");\n        }\n        // IE9-11: undefinedASS\n        console.log(f({ A: \"P\" }));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5081_property_access_ie: {\n    options = {\n        ie: true,\n        merge_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return a[b = \"A\"] + (b += \"SS\");\n        }\n        console.log(f({ A: \"P\" }));\n    }\n    expect: {\n        function f(a) {\n            var b;\n            return a[b = \"A\"] + (b += \"SS\");\n        }\n        console.log(f({ A: \"P\" }));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5269_1: {\n    options = {\n        ie: false,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            (function() {\n                try {\n                    throw \"PASS\";\n                } catch (e) {\n                    console.log(e);\n                }\n            })();\n        } while (!console);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                console.log(e);\n            }\n        } while (!console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5269_1_ie: {\n    options = {\n        ie: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            (function() {\n                try {\n                    throw \"PASS\";\n                } catch (e) {\n                    console.log(e);\n                }\n            })();\n        } while (!console);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                console.log(e);\n            }\n        } while (!console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5269_2: {\n    options = {\n        ie: false,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var i = 0; i < 2; i++)\n            (function() {\n                console.log(e);\n                try {\n                    console;\n                } catch (e) {\n                    var e = \"FAIL 1\";\n                }\n                e = \"FAIL 2\";\n                console;\n            })();\n    }\n    expect: {\n        for (var i = 0; i < 2; i++) {\n            e = void 0;\n            console.log(e);\n            try {\n                console;\n            } catch (e) {\n                var e = \"FAIL 1\";\n            }\n            e = \"FAIL 2\";\n            console;\n        }\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\nissue_5269_2_ie: {\n    options = {\n        ie: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var i = 0; i < 2; i++)\n            (function() {\n                console.log(e);\n                try {\n                    console;\n                } catch (e) {\n                    var e = \"FAIL 1\";\n                }\n                e = \"FAIL 2\";\n                console;\n            })();\n    }\n    expect: {\n        for (var i = 0; i < 2; i++) {\n            e = void 0;\n            console.log(e);\n            try {\n                console;\n            } catch (e) {\n                var e = \"FAIL 1\";\n            }\n            e = \"FAIL 2\";\n            console;\n        }\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n}\n\nissue_5269_3: {\n    options = {\n        ie: false,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        e = \"foo\";\n        for (var i = 0; i < 2; i++)\n            (function() {\n                console.log(e);\n                try {\n                    console;\n                } catch (e) {\n                    e = \"FAIL\";\n                }\n                e = \"bar\";\n                console;\n            })();\n    }\n    expect: {\n        e = \"foo\";\n        for (var i = 0; i < 2; i++) {\n            console.log(e);\n            try {\n                console;\n            } catch (e) {\n                e = \"FAIL\";\n            }\n            e = \"bar\";\n            console;\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_5269_3_ie: {\n    options = {\n        ie: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        e = \"foo\";\n        for (var i = 0; i < 2; i++)\n            (function() {\n                console.log(e);\n                try {\n                    console;\n                } catch (e) {\n                    e = \"FAIL\";\n                }\n                e = \"bar\";\n                console;\n            })();\n    }\n    expect: {\n        e = \"foo\";\n        for (var i = 0; i < 2; i++) {\n            console.log(e);\n            try {\n                console;\n            } catch (e) {\n                e = \"FAIL\";\n            }\n            e = \"bar\";\n            console;\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_5350: {\n    options = {\n        ie: false,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(typeof f, [ 42, function f() {} ][0]);\n    }\n    expect: {\n        console.log(typeof f, 42);\n    }\n    expect_stdout: \"undefined 42\"\n}\n\nissue_5350_ie: {\n    options = {\n        ie: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(typeof f, [ 42, function f() {} ][0]);\n    }\n    expect: {\n        console.log(typeof f, (function f() {}, 42));\n    }\n    expect_stdout: \"undefined 42\"\n}\n\nissue_5958: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        ie: false,\n        inline: true,\n        loops: true,\n        sequences: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        while (function() {\n            if (a === console.log(\"PASS\")) {\n                var a = function b() {};\n                try {\n                    a++;\n                } catch (b) {\n                    b[a];\n                }\n            }\n        }());\n    }\n    expect: {\n        \"use strict\";\n        if (a = void 0, a === console.log(\"PASS\")) {\n            var a = function b() {};\n            try {\n                a++;\n            } catch (b) {\n                b[a];\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5958_ie: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        ie: true,\n        inline: true,\n        loops: true,\n        sequences: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        while (function() {\n            if (a === console.log(\"PASS\")) {\n                var a = function b() {};\n                try {\n                    a++;\n                } catch (b) {\n                    b[a];\n                }\n            }\n        }());\n    }\n    expect: {\n        \"use strict\";\n        if (a = void 0, a === console.log(\"PASS\")) {\n            var a = function b() {};\n            try {\n                a++;\n            } catch (b) {\n                b[a];\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5961: {\n    options = {\n        ie: false,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a in [ 1, 2 ]) {\n            (function() {\n                try {\n                    (function f() {});\n                } finally {\n                    var b = f, f = \"FAIL\";\n                    console.log(b || \"PASS\");\n                }\n            })();\n        }\n    }\n    expect: {\n        for (var a in [ 1, 2 ]) {\n            b = void 0;\n            f = void 0;\n            try {\n                (function f() {});\n            } finally {\n                var b = f, f = \"FAIL\";\n                console.log(b || \"PASS\");\n            }\n        }\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_5961_ie: {\n    options = {\n        ie: true,\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        for (var a in [ 1, 2 ]) {\n            (function() {\n                try {\n                    (function f() {});\n                } finally {\n                    var b = f, f = \"FAIL\";\n                    console.log(b || \"PASS\");\n                }\n            })();\n        }\n    }\n    expect: {\n        for (var a in [ 1, 2 ]) {\n            b = void 0;\n            f = void 0;\n            try {\n                (function f() {});\n            } finally {\n                var b = f, f = \"FAIL\";\n                console.log(b || \"PASS\");\n            }\n        }\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/if_return.js",
    "content": "if_return_1: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n            if (x) {\n                return true;\n            }\n        }\n    }\n    expect: {\n        function f(x){if(x)return!0}\n    }\n}\n\nif_return_2: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            if (x)\n                return 3;\n            if (y)\n                return c();\n        }\n    }\n    expect: {\n        function f(x,y){return x?3:y?c():void 0}\n    }\n}\n\nif_return_3: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n            a();\n            if (x) {\n                b();\n                return false;\n            }\n        }\n    }\n    expect: {\n        function f(x){if(a(),x)return b(),!1}\n    }\n}\n\nif_return_4: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x, y) {\n            a();\n            if (x) return 3;\n            b();\n            if (y) return c();\n        }\n    }\n    expect: {\n        function f(x,y){return a(),x?3:(b(),y?c():void 0)}\n    }\n}\n\nif_return_5: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            if (x)\n                return;\n            return 7;\n            if (y)\n                return j;\n        }\n    }\n    expect: {\n        function f(){if(!x)return 7}\n    }\n}\n\nif_return_6: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n          return x ? true : void 0;\n          return y;\n        }\n    }\n    expect: {\n        // suboptimal\n        function f(x){return!!x||void 0}\n    }\n}\n\nif_return_7: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n            if (x) {\n                return true;\n            }\n            foo();\n            bar();\n        }\n    }\n    expect: {\n        function f(x){if(x)return!0;foo(),bar()}\n    }\n}\n\nif_return_8: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f(e) {\n            if (2 == e) return foo();\n            if (3 == e) return bar();\n            if (4 == e) return baz();\n            fail(e);\n        }\n\n        function g(e) {\n            if (a(e)) return foo();\n            if (b(e)) return bar();\n            if (c(e)) return baz();\n            fail(e);\n        }\n\n        function h(e) {\n            if (a(e)) return foo();\n            else if (b(e)) return bar();\n            else if (c(e)) return baz();\n            else fail(e);\n        }\n\n        function i(e) {\n            if (a(e)) return foo();\n            else if (b(e)) return bar();\n            else if (c(e)) return baz();\n            fail(e);\n        }\n    }\n    expect: {\n        function f(e){return 2==e?foo():3==e?bar():4==e?baz():void fail(e)}\n        function g(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}\n        function h(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}\n        function i(e){return a(e)?foo():b(e)?bar():c(e)?baz():void fail(e)}\n    }\n}\n\nif_return_9: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        !function() {\n            if (console.log(\"foo\"))\n                return 42;\n            var a = console.log(\"bar\");\n        }();\n    }\n    expect: {\n        !function() {\n            var a;\n            return console.log(\"foo\") || (a = console.log(\"bar\"), void 0);\n        }();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nif_return_10: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        !function() {\n            if (console.log(\"foo\"))\n                return 42;\n            if (console.log(\"bar\"))\n                return null;\n            var a = console.log(\"baz\");\n        }();\n    }\n    expect: {\n        !function() {\n            var a;\n            return console.log(\"foo\") || !console.log(\"bar\") && (a = console.log(\"baz\"), void 0);\n        }();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nif_return_cond_void_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                return console.log(\"foo\") ? console.log(\"bar\") : void 0;\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            return a && console.log(\"foo\") ? console.log(\"bar\") : void 0;\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: \"foo\"\n}\n\nif_return_cond_void_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                return console.log(\"foo\") ? void 0 : console.log(\"bar\");\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            return !a || console.log(\"foo\") ? void 0 : console.log(\"bar\");\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nif_return_cond_void_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                return console.log(\"foo\") ? void console.log(\"bar\") : void console.log(\"baz\");\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                return console.log(\"foo\") ? void console.log(\"bar\") : void console.log(\"baz\");\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n    ]\n}\n\nissue_1089: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function x() {\n            var f = document.getElementById(\"fname\");\n            if (f.files[0].size > 12345) {\n                alert(\"alert\");\n                f.focus();\n                return false;\n            }\n        }\n    }\n    expect: {\n        function x() {\n            var f = document.getElementById(\"fname\");\n            if (12345 < f.files[0].size)\n                return alert(\"alert\"), f.focus(), !1;\n        }\n    }\n}\n\nissue_1437: {\n    options = {\n        conditionals: false,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        function x() {\n            if (a())\n                return b();\n            if (c())\n                return d();\n            else\n                e();\n            f();\n        }\n    }\n    expect: {\n        function x() {\n            if (a())\n                return b();\n            if (c())\n                return d();\n            else\n                e()\n            f();\n        }\n    }\n}\n\nissue_1437_conditionals: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        function x() {\n            if (a())\n                return b();\n            if (c())\n                return d();\n            else\n                e();\n            f();\n        }\n    }\n    expect: {\n        function x() {\n            return a() ? b() : c() ? d() : (e(), f(), void 0);\n        }\n    }\n}\n\nissue_512: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function a() {\n            if (b()) {\n                c();\n                return;\n            }\n            throw e;\n        }\n    }\n    expect: {\n        function a() {\n            if (!b()) throw e;\n            c();\n        }\n    }\n}\n\nif_var_return_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        function f() {\n            var a;\n            return;\n            var b;\n        }\n        function g() {\n            var a;\n            if (u()) {\n                var b;\n                return v();\n                var c;\n            }\n            var d;\n            if (w()) {\n                var e;\n                return x();\n                var f;\n            } else {\n                var g;\n                y();\n                var h;\n            }\n            var i;\n            z();\n            var j;\n        }\n    }\n    expect: {\n        function f() {\n            var a, b;\n        }\n        function g() {\n            var a, b, c, d, e, f, g, h, i, j;\n            return u() ? v() : w() ? x() : (y(), z(), void 0);\n        }\n    }\n}\n\nif_var_return_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        (function() {\n            var a = w();\n            if (x())\n                return y();\n            z();\n        })();\n    }\n    expect: {\n        (function() {\n            var a = w();\n            return x() ? y() : (z(), void 0);\n        })();\n    }\n}\n\nif_var_return_3: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        f(function() {\n            var a = w();\n            if (x())\n                return y(a);\n            z();\n        });\n    }\n    expect: {\n        f(function() {\n            var a = w();\n            if (x())\n                return y(a);\n            z();\n        });\n    }\n}\n\nif_var_return_4: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        function f() {\n            if (u())\n                return v();\n            var a = w();\n            if (x())\n                return y(a);\n            z();\n        }\n    }\n    expect: {\n        function f() {\n            var a;\n            return u() ? v() : (a = w(), x() ? y(a) : (z(), void 0));\n        }\n    }\n}\n\nif_var_return_5: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f() {\n            if (w())\n                return x();\n            var a = y();\n            return z(a);\n        }\n    }\n    expect: {\n        function f() {\n            var a;\n            return w() ? x() : (a = y(), z(a));\n        }\n    }\n}\n\nif_defns_return_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            if (u())\n                return v();\n            function g() {}\n            if (w())\n                return x(g);\n            var a = y();\n            z(a);\n        }\n    }\n    expect: {\n        function f() {\n            var a;\n            return u() ? v() : w() ? x(g) : (a = y(), void z(a));\n            function g() {}\n        }\n    }\n}\n\nif_defns_return_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a, b, c) {\n            if (v())\n                return a();\n            if (w())\n                return b();\n            if (x()) {\n                var d = c();\n                return y(d);\n            }\n            return z();\n        }\n    }\n    expect: {\n        function f(a, b, c) {\n            var d;\n            return v() ? a() : w() ? b() : x() ? (d = c(), y(d)) : z();\n        }\n    }\n}\n\nif_if_return_return: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a, b) {\n            if (a) {\n                if (b)\n                    return b;\n                return;\n            }\n            g();\n        }\n    }\n    expect: {\n        function f(a, b) {\n            if (a)\n                return b || void 0;\n            g();\n        }\n    }\n}\n\nif_body_return_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        var c = \"PASS\";\n        function f(a, b) {\n            if (a) {\n                if (b) throw new Error(c);\n                return 42;\n            }\n            return true;\n        }\n        console.log(f(0, 0));\n        console.log(f(0, 1));\n        console.log(f(1, 0));\n        try {\n            f(1, 1);\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(e.message);\n        }\n    }\n    expect: {\n        var c = \"PASS\";\n        function f(a, b) {\n            if (a) {\n                if (b) throw new Error(c);\n                return 42;\n            }\n            return true;\n        }\n        console.log(f(0, 0));\n        console.log(f(0, 1));\n        console.log(f(1, 0));\n        try {\n            f(1, 1);\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(e.message);\n        }\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"42\",\n        \"PASS\",\n    ]\n}\n\nif_body_return_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        var c = \"PASS\";\n        function f(a, b) {\n            if (0 + a) {\n                if (b) throw new Error(c);\n                return 42;\n            }\n            return true;\n        }\n        console.log(f(0, 0));\n        console.log(f(0, 1));\n        console.log(f(1, 0));\n        try {\n            f(1, 1);\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(e.message);\n        }\n    }\n    expect: {\n        var c = \"PASS\";\n        function f(a, b) {\n            if (0 + a) {\n                if (b) throw new Error(c);\n                return 42;\n            }\n            return true;\n        }\n        console.log(f(0, 0));\n        console.log(f(0, 1));\n        console.log(f(1, 0));\n        try {\n            f(1, 1);\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(e.message);\n        }\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"42\",\n        \"PASS\",\n    ]\n}\n\nif_body_return_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        var c = \"PASS\";\n        function f(a, b) {\n            if (1 == a) {\n                if (b) throw new Error(c);\n                return 42;\n            }\n            return true;\n        }\n        console.log(f(0, 0));\n        console.log(f(0, 1));\n        console.log(f(1, 0));\n        try {\n            f(1, 1);\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(e.message);\n        }\n    }\n    expect: {\n        var c = \"PASS\";\n        function f(a, b) {\n            if (1 != a) return true;\n            if (b) throw new Error(c);\n            return 42;\n        }\n        console.log(f(0, 0));\n        console.log(f(0, 1));\n        console.log(f(1, 0));\n        try {\n            f(1, 1);\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(e.message);\n        }\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"42\",\n        \"PASS\",\n    ]\n}\n\nissue_3600_1: {\n    options = {\n        if_return: true,\n        inline: 3,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            if ([ ][c++]); else return;\n            return void function() {\n                var b = --b, a = c = 42;\n                return c;\n            }();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function() {\n            if ([][c++]) b = --b, c = 42;\n            var b;\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3600_2: {\n    options = {\n        if_return: true,\n        inline: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            if ([ ][c++]); else return;\n            return void function() {\n                var b = --b, a = c = 42;\n                return c;\n            }();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function() {\n            if ([][c++])\n                b = --b,\n                c = 42;\n            var b;\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\niife_if_return_simple: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        inline: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            if (console)\n                return console.log(\"PASS\");\n            console.log(\"FAIL\");\n        })();\n    }\n    expect: {\n        console ? console.log(\"PASS\") : console.log(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nnested_if_break: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        side_effects: true,\n    }\n    input: {\n        for (var i = 0; i < 3; i++)\n            L1: if (\"number\" == typeof i) {\n                if (0 === i) break L1;\n                console.log(i);\n            }\n    }\n    expect: {\n        for (var i = 0; i < 3; i++)\n            L1: \"number\" == typeof i && 0 !== i && console.log(i);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\nnested_if_continue: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        join_vars: true,\n        loops: true,\n    }\n    input: {\n        function f(n) {\n            var i = 0;\n            do {\n                if (\"number\" == typeof n) {\n                    if (0 === n) {\n                        console.log(\"even\", i);\n                        continue;\n                    }\n                    if (1 === n) {\n                        console.log(\"odd\", i);\n                        continue;\n                    }\n                    i++;\n                }\n            } while (0 <= (n -= 2));\n        }\n        f(37);\n        f(42);\n    }\n    expect: {\n        function f(n) {\n            for (var i = 0;\n                \"number\" == typeof n\n                    && (0 === n\n                        ? console.log(\"even\", i)\n                        : 1 === n\n                        ? console.log(\"odd\", i)\n                        : i++),\n                0 <= (n -= 2););\n        }\n        f(37);\n        f(42);\n    }\n    expect_stdout: [\n        \"odd 18\",\n        \"even 21\",\n    ]\n}\n\nnested_if_return: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f() {\n            if (A) {\n                if (B)\n                    return B;\n                if (C)\n                    return D;\n                if (E)\n                    return F;\n                if (G)\n                    return H;\n                if (I) {\n                    if (J)\n                        return K;\n                    return;\n                }\n                if (L) {\n                    if (M)\n                        return;\n                    return N;\n                }\n            }\n        }\n    }\n    expect: {\n        function f() {\n            if (A)\n                return B || (C ? D : E ? F : G ? H : I ? J ? K : void 0 : L && !M ? N : void 0);\n        }\n    }\n}\n\nissue_866_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: false,\n    };\n    input: {\n        function f(a) {\n            if (a)\n                return \"\";\n            console.log(a);\n        }\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                return \"\";\n            console.log(a);\n        }\n    }\n}\n\nissue_866_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n    }\n    input: {\n        (function() {\n            if (a)\n                if (b)\n                    c;\n                else\n                    return d;\n        })();\n    }\n    expect: {\n        (function() {\n            if (a) {\n                if (!b)\n                    return d;\n                c;\n            }\n        })();\n    }\n}\n\nidentical_returns_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        console.log(function() {\n            if (console.log(\"foo\"))\n                return 42;\n            else\n                while (console.log(\"bar\"));\n            return 42;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (!console.log(\"foo\"))\n                while (console.log(\"bar\"));\n            return 42;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"42\",\n    ]\n}\n\nidentical_returns_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        console.log(function() {\n            if (console.log(\"foo\"))\n                while (console.log(\"FAIL\"));\n            else\n                return \"bar\";\n            return \"bar\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (console.log(\"foo\"))\n                while (console.log(\"FAIL\"));\n            return \"bar\";\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nidentical_returns_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                return 42;\n            if (a)\n                return;\n            return 42;\n        }\n        if (f(console))\n            console.log(\"PASS\");\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                return 42;\n            if (a)\n                ;\n            else\n                return 42;\n        }\n        if (f(console))\n            console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4374: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            console.log(f(console));\n            function f(a) {\n                if (console) return 0;\n                if (a) return 1;\n                return 0;\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(function(a) {\n                return !console && a ? 1 : 0;\n            }(console));\n        })();\n    }\n    expect_stdout: \"0\"\n}\n\nissue_5521: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        console.log(function() {\n            if (console)\n                try {\n                    return \"FAIL\";\n                } finally {\n                    return;\n                }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (console)\n                try {\n                    return \"FAIL\";\n                } finally {\n                    return;\n                }\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5523: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        console.log(function() {\n            if (console)\n                try {\n                    FAIL;\n                } finally {\n                    return;\n                }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (console)\n                try {\n                    FAIL;\n                } finally {\n                    return;\n                }\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\ndrop_catch: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw 42;\n            } catch (e) {\n                return console.log(\"foo\"), \"bar\";\n            } finally {\n                console.log(\"baz\");\n            }\n            return \"bar\";\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            try {\n                throw 42;\n            } catch (e) {\n                console.log(\"foo\");\n            } finally {\n                console.log(\"baz\");\n            }\n            return \"bar\";\n        }\n        console.log(f());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n}\n\nretain_catch: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                throw 42;\n            } catch (e) {\n                return console.log(\"foo\");\n            } finally {\n                console.log(\"bar\");\n            }\n            return console.log(\"foo\");\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            try {\n                throw 42;\n            } catch (e) {\n                return console.log(\"foo\");\n            } finally {\n                console.log(\"bar\");\n            }\n            return console.log(\"foo\");\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nretain_finally: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                return console.log(\"foo\"), FAIL;\n            } catch (e) {\n                return console.log(\"bar\"), \"FAIL\";\n            } finally {\n                return console.log(\"baz\"), console.log(\"moo\");\n            }\n            return console.log(\"moo\");\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            try {\n                return console.log(\"foo\"), FAIL;\n            } catch (e) {\n                return console.log(\"bar\"), \"FAIL\";\n            } finally {\n                return console.log(\"baz\"), console.log(\"moo\");\n            }\n            return console.log(\"moo\");\n        }\n        console.log(f());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"moo\",\n        \"undefined\",\n    ]\n}\n\ndrop_try: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                return console.log(\"foo\"), \"bar\";\n            } finally {\n                console.log(\"baz\");\n            }\n            return \"bar\";\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            try {\n                console.log(\"foo\");\n            } finally {\n                console.log(\"baz\");\n            }\n            return \"bar\";\n        }\n        console.log(f());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n}\n\nretain_try: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            try {\n                return console.log(\"foo\");\n            } finally {\n                console.log(\"bar\");\n            }\n            return console.log(\"foo\");\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            try {\n                return console.log(\"foo\");\n            } finally {\n                console.log(\"bar\");\n            }\n            return console.log(\"foo\");\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ndrop_try_catch: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            try {\n                if (a())\n                    return console.log(\"foo\"), console.log(\"baz\");\n            } catch (e) {\n                return console.log(\"bar\"), console.log(\"baz\");\n            }\n            return console.log(\"baz\");\n        }\n        f(function() {\n            return 42;\n        });\n        f(function() {});\n        f();\n    }\n    expect: {\n        function f(a) {\n            try {\n                if (a())\n                    console.log(\"foo\");\n            } catch (e) {\n                console.log(\"bar\");\n            }\n            return console.log(\"baz\");\n        }\n        f(function() {\n            return 42;\n        });\n        f(function() {});\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"baz\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nempty_try: {\n    options = {\n        if_return: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return f;\n            function f() {\n                try {} finally {}\n                return \"PASS\";\n            }\n        }()());\n    }\n    expect: {\n        console.log(function() {\n            return function() {\n                try {} finally {}\n                return \"PASS\";\n            };\n        }()());\n    }\n    expect_stdout: \"PASS\"\n}\n\nsequence_void_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            {\n                if (console)\n                    return console, void console.log(\"PASS\");\n                return;\n            }\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            if (console)\n                console, void console.log(\"PASS\");\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nsequence_void_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            {\n                if (console)\n                    return console, void console.log(\"PASS\");\n                return;\n            }\n            FAIL;\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            if (console)\n                console, void console.log(\"PASS\");\n            else {\n                return;\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\ntail_match: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a) {\n                console.log(\"foo\");\n                return console.log(\"bar\");\n            }\n            while (console.log(\"baz\"));\n            return console.log(\"moo\"), console.log(\"bar\");\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                console.log(\"foo\");\n            else {\n                while (console.log(\"baz\"));\n                console.log(\"moo\");\n            }\n            return console.log(\"bar\");\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"baz\",\n        \"moo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nvoid_match: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a) {\n                console.log(\"foo\");\n                return;\n            }\n            while (console.log(\"bar\"));\n            return console.log(\"baz\"), void console.log(\"moo\");\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                console.log(\"foo\");\n            else {\n                while (console.log(\"bar\"));\n                console.log(\"baz\"),\n                console.log(\"moo\");\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"baz\",\n        \"moo\",\n        \"foo\",\n    ]\n}\n\nswitch_break: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              default:\n                if (console.log(\"foo\"))\n                    break;\n                while (console.log(\"bar\"));\n              case 42:\n                if (console.log(\"baz\"))\n                    break;\n                while (console.log(\"moo\"));\n                break;\n              case null:\n                if (console.log(\"moz\"))\n                    break;\n            }\n        }\n        f();\n        f(42);\n        f(null);\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              default:\n                if (console.log(\"foo\"))\n                    break;\n                while (console.log(\"bar\"));\n              case 42:\n                if (!console.log(\"baz\"))\n                    while (console.log(\"moo\"));\n                break;\n              case null:\n                console.log(\"moz\");\n            }\n        }\n        f();\n        f(42);\n        f(null);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"moo\",\n        \"baz\",\n        \"moo\",\n        \"moz\",\n    ]\n}\n\nswitch_return_1: {\n    options = {\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"PASS\"):\n                return;\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"PASS\"):\n                return;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nswitch_return_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"PASS\"):\n                if (console)\n                    return;\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"PASS\"):\n                if (console);\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nswitch_return_3: {\n    options = {\n        if_return: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"foo\"):\n                if (console)\n                    return void console.log(\"bar\");\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"foo\"):\n                if (console)\n                    console.log(\"bar\");\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nswitch_return_4: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"foo\"):\n                if (console) {\n                    console.log(\"bar\");\n                    return;\n                }\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"foo\"):\n                console && console.log(\"bar\");\n                break;\n              case 42:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nswitch_return_5: {\n    options = {\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (a)\n                    return;\n                return;\n                break;\n              case null:\n                FAIL;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (a);\n                return;\n              case null:\n                FAIL;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nmerged_references_1: {\n    options = {\n        if_return: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a, b = \"PASS\";\n        console.log(function(c) {\n            if (c = b)\n                return a || c;\n            c = FAIL;\n            return a || c;\n        }());\n    }\n    expect: {\n        var a, b = \"PASS\";\n        console.log(function(c) {\n            if (c = b);\n            else\n                c = FAIL;\n            return a || c;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nmerged_references_2: {\n    options = {\n        if_return: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a;\n        console.log(function(b) {\n            if (a = b)\n                return console && a;\n            a = FAIL;\n            return console && a;\n        }(A));\n    }\n    expect: {\n        A = \"PASS\";\n        var a;\n        console.log(function(b) {\n            if (a = b);\n            else\n                a = FAIL;\n            return console && a;\n        }(A));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5583: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        side_effects: true,\n    }\n    input: {\n        do {\n            switch (console) {\n              default:\n                if (!console.log(\"foo\"))\n                    continue;\n                break;\n              case console.log(\"bar\"):\n                FAIL;\n            }\n        } while (console.log(\"baz\"));\n    }\n    expect: {\n        do {\n            switch (console) {\n              default:\n                console.log(\"foo\");\n                break;\n              case console.log(\"bar\"):\n                FAIL;\n            }\n        } while (console.log(\"baz\"));\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"baz\",\n    ]\n}\n\nissue_5584_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case 42:\n                if (!console.log(\"PASS\"))\n                    return;\n                return FAIL;\n            }\n        }\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case 42:\n                if (console.log(\"PASS\"))\n                    return FAIL;\n            }\n        }\n        f(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5584_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"PASS\"):\n                if (console)\n                    break;\n                return FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case console.log(\"PASS\"):\n                if (console)\n                    break;\n                return FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5584_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f() {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console)\n                    break;\n                return;\n            }\n            console.log(\"baz\");\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console)\n                    break;\n                return;\n            }\n            console.log(\"baz\");\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5584_4: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (a)\n                    return;\n                break;\n            }\n            console.log(\"baz\");\n        }\n        f();\n    }\n    expect: {\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (a)\n                    return;\n                break;\n            }\n            console.log(\"baz\");\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5586: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        L: do {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console)\n                    break;\n                break L;\n            }\n        } while (console.log(\"baz\"));\n    }\n    expect: {\n        L: do {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console)\n                    break;\n                break L;\n            }\n        } while (console.log(\"baz\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5587_1: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (console)\n                return a ? void 0 : console.log(\"PASS\");\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            return !console || a ? void 0 : console.log(\"PASS\");\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5587_2: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (console)\n                return a ? console.log(\"PASS\") : void 0;\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            return console && a ? console.log(\"PASS\") : void 0;\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5589_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (a) {\n              case 42:\n                if (!console.log(\"PASS\"))\n                    return;\n                return 0;\n                break;\n              case null:\n                FAIL;\n            }\n        }\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            switch (a) {\n              case 42:\n                if (console.log(\"PASS\"))\n                    return 0;\n                break;\n              case null:\n                FAIL;\n            }\n        }\n        f(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5589_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (a)\n                    return void console.log(\"baz\");\n                return;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (a)\n                    void console.log(\"baz\");\n                return;\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5589_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            do {\n                switch (console.log(\"foo\")) {\n                  case console.log(\"bar\"):\n                    if (a)\n                        return void console.log(\"baz\");\n                    continue;\n                }\n            } while (console.log(\"moo\"));\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        function f(a) {\n            do {\n                switch (console.log(\"foo\")) {\n                  case console.log(\"bar\"):\n                    if (a)\n                        return void console.log(\"baz\");\n                    continue;\n                }\n            } while (console.log(\"moo\"));\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5592_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        L: {\n            do {\n                switch (console.log(\"foo\")) {\n                  case console.log(\"bar\"):\n                    if (console)\n                        break;\n                    break L;\n                }\n            } while (console.log(\"baz\"));\n        }\n    }\n    expect: {\n        L: do {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console)\n                    break;\n                break L;\n            }\n        } while (console.log(\"baz\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5592_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        L: {\n            do {\n                switch (console.log(\"foo\")) {\n                  case console.log(\"bar\"):\n                    if (!console)\n                        break L;\n                    break;\n                }\n            } while (console.log(\"baz\"));\n        }\n    }\n    expect: {\n        L: do {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console)\n                    break;\n                break L;\n            }\n        } while (console.log(\"baz\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_5595: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        function f(a) {\n            if (a) {\n                var b;\n                if (b++)\n                    return \"FAIL\";\n            } else\n                return \"PASS\";\n        }\n        console.log(f());\n    }\n    expect: {\n        function f(a) {\n            var b;\n            return a ? b++ ? \"FAIL\" : void 0 : \"PASS\";\n        }\n        console.log(f());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5597: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            if (a) L: {\n                return;\n                var b;\n            } else\n                return \"FAIL\";\n        }\n        console.log(f(42) || \"PASS\");\n    }\n    expect: {\n        function f(a) {\n            if (!a)\n                return \"FAIL\";\n        }\n        console.log(f(42) || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5619_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        console.log(function() {\n            if (console)\n                if (console)\n                    return \"PASS\";\n            var a = FAIL;\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (console)\n                if (console)\n                    return \"PASS\";\n            var a = FAIL;\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5619_2: {\n    options = {\n        dead_code: true,\n        if_return: true,\n        loops: true,\n    }\n    input: {\n        console.log(function() {\n            if (console)\n                while (console)\n                    return \"PASS\";\n            var a = FAIL;\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (console) {\n                if (console)\n                    return \"PASS\";\n            }\n            var a = FAIL;\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5649: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        console.log(function() {\n            try {\n                throw new Error(\"FAIL\");\n            } catch (e) {\n                return \"PASS\";\n            }\n            throw new Error(\"FAIL\");\n        }());\n    }\n    expect: {\n        console.log(function() {\n            try {\n                throw new Error(\"FAIL\");\n            } catch (e) {\n                return \"PASS\";\n            }\n            throw new Error(\"FAIL\");\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5688: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        L: do {\n            switch (console) {\n              default:\n                if (console)\n                    break;\n                if (FAIL_1)\n                    ;\n                else\n                    break L;\n                break;\n              case 42:\n                FAIL_2;\n            }\n        } while (console.log(\"PASS\"));\n    }\n    expect: {\n        L: do {\n            switch (console) {\n              default:\n                if (console)\n                    break;\n                if (FAIL_1)\n                    break;\n                break L;\n              case 42:\n                FAIL_2;\n            }\n        } while (console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/imports.js",
    "content": "nought: {\n    input: {\n        import \"foo\";\n    }\n    expect_exact: 'import\"foo\";'\n}\n\ndefault_only: {\n    input: {\n        import foo from \"bar\";\n    }\n    expect_exact: 'import foo from\"bar\";'\n}\n\nall_only: {\n    input: {\n        import * as foo from \"bar\";\n    }\n    expect_exact: 'import*as foo from\"bar\";'\n}\n\nkeys_only: {\n    input: {\n        import { as as foo, bar, delete as baz } from \"moo\";\n    }\n    expect_exact: 'import{as as foo,bar,delete as baz}from\"moo\";'\n}\n\ndefault_all: {\n    input: {\n        import foo, * as bar from \"baz\";\n    }\n    expect_exact: 'import foo,*as bar from\"baz\";'\n}\n\ndefault_keys: {\n    input: {\n        import foo, { bar } from \"baz\";\n    }\n    expect_exact: 'import foo,{bar}from\"baz\";'\n}\n\nnon_identifiers: {\n    beautify = {\n        quote_style: 3,\n    }\n    input: {\n        import { '42' as foo } from \"bar\";\n        import { \"foo\" as bar } from 'baz';\n    }\n    expect_exact: \"import{'42'as foo}from\\\"bar\\\";import{foo as bar}from'baz';\"\n}\n\ndynamic: {\n    input: {\n        (async a => await import(a))(\"foo\").then(bar);\n    }\n    expect_exact: '(async a=>await import(a))(\"foo\").then(bar);'\n}\n\ndynamic_nought: {\n    input: {\n        import(foo);\n    }\n    expect_exact: \"import(foo);\"\n}\n\nimport_meta_1: {\n    input: {\n        console.log(import.meta, import.meta.url);\n    }\n    expect_exact: \"console.log(import.meta,import.meta.url);\"\n}\n\nimport_meta_2: {\n    input: {\n        import.meta.url.split(\"/\").forEach(function(part, index) {\n            console.log(index, part);\n        });\n    }\n    expect_exact: 'import.meta.url.split(\"/\").forEach(function(part,index){console.log(index,part)});'\n}\n\nsame_quotes: {\n    beautify = {\n        beautify: true,\n        quote_style: 3,\n    }\n    input: {\n        import 'foo';\n        import \"bar\";\n    }\n    expect_exact: [\n        \"import 'foo';\",\n        \"\",\n        'import \"bar\";',\n    ]\n}\n\ndrop_unused: {\n    options = {\n        imports: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        import a, * as b from \"foo\";\n        import { c } from \"bar\";\n        import { d, _ as e } from \"baz\";\n        console.log(d);\n    }\n    expect: {\n        import \"foo\";\n        import \"bar\";\n        import { d as d } from \"baz\";\n        console.log(d);\n    }\n}\n\ndrop_side_effect_free: {\n    options = {\n        imports: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        import foo from \"bar\";\n        var a = foo;\n    }\n    expect: {\n        import \"bar\";\n    }\n}\n\nmangle: {\n    rename = false\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        import foo, { bar } from \"baz\";\n        console.log(moo);\n        import * as moo from \"moz\";\n    }\n    expect: {\n        import o, { bar as m } from \"baz\";\n        console.log(r);\n        import * as r from \"moz\";\n    }\n}\n\nrename_mangle: {\n    rename = true\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        import foo, { bar } from \"baz\";\n        console.log(moo);\n        import * as moo from \"moz\";\n    }\n    expect: {\n        import o, { bar as m } from \"baz\";\n        console.log(r);\n        import * as r from \"moz\";\n    }\n}\n\nmangle_export_import: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        export let o = A;\n        import { p as A } from \"foo\";\n    }\n    expect: {\n        export let o = p;\n        import { p } from \"foo\";\n    }\n}\n\nmangle_import_export: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        import { p as A } from \"foo\";\n        export let o = A;\n    }\n    expect: {\n        import { p } from \"foo\";\n        export let o = p;\n    }\n}\n\nkeep_ref: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        import foo from \"bar\";\n        foo();\n    }\n    expect: {\n        import foo from \"bar\";\n        foo();\n    }\n}\n\nforbid_merge: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        import A from \"foo\";\n        export default class extends A {}\n        var f = () => () => {};\n        f();\n        f();\n    }\n    expect: {\n        import A from \"foo\";\n        export default class extends A {}\n        var f = () => () => {};\n        f();\n        f();\n    }\n}\n\nissue_4708_1: {\n    options = {\n        imports: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        import a from \"foo\";\n    }\n    expect: {\n        var a;\n        import a from \"foo\";\n    }\n}\n\nissue_4708_2: {\n    options = {\n        imports: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(a);\n        import a from \"foo\";\n    }\n    expect: {\n        var a;\n        console.log(a);\n        import a from \"foo\";\n    }\n}\n\npr_5550_1: {\n    input: {\n        if (console)\n            import(\"foo\");\n        else\n            import.meta.url.replace(/bar/g, console.log);\n    }\n    expect: {\n        if (console)\n            import(\"foo\");\n        else\n            import.meta.url.replace(/bar/g, console.log);\n    }\n}\n\npr_5550_2: {\n    input: {\n        L: {\n            import(\"foo\");\n            import.meta.url.replace(/bar/g, console.log);\n        }\n    }\n    expect: {\n        L: {\n            import(\"foo\");\n            import.meta.url.replace(/bar/g, console.log);\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/indentation.js",
    "content": "numeric: {\n    beautify = {\n        beautify: true,\n        indent_start: 1,\n        indent_level: 3,\n    }\n    input: {\n        switch (42) {\n          case null:\n            console.log(\"FAIL\");\n        }\n        console.log(\"PASS\");\n    }\n    expect_exact: [\n        \" switch (42) {\",\n        \"  case null:\",\n        '    console.log(\"FAIL\");',\n        \" }\",\n        \"\",\n        ' console.log(\"PASS\");',\n    ]\n    expect_stdout: \"PASS\"\n}\n\nspaces: {\n    beautify = {\n        beautify: true,\n        indent_start: \" \",\n        indent_level: \"   \",\n    }\n    input: {\n        switch (42) {\n          case null:\n            console.log(\"FAIL\");\n        }\n        console.log(\"PASS\");\n    }\n    expect_exact: [\n        \" switch (42) {\",\n        \"  case null:\",\n        '    console.log(\"FAIL\");',\n        \" }\",\n        \"\",\n        ' console.log(\"PASS\");',\n    ]\n    expect_stdout: \"PASS\"\n}\n\ntabs: {\n    beautify = {\n        beautify: true,\n        indent_start: \"\\t\",\n        indent_level: \"\\t\",\n    }\n    input: {\n        switch (42) {\n          case null:\n            console.log(\"FAIL\");\n        }\n        console.log(\"PASS\");\n    }\n    expect_exact: [\n        \"\\tswitch (42) {\",\n        \"\\tcase null:\",\n        '\\t\\tconsole.log(\"FAIL\");',\n        \"\\t}\",\n        \"\",\n        '\\tconsole.log(\"PASS\");',\n    ]\n    expect_stdout: \"PASS\"\n}\n\nmixed: {\n    beautify = {\n        beautify: true,\n        indent_start: \"\\n\",\n        indent_level: \"       \\t\",\n    }\n    input: {\n        switch (42) {\n          case null:\n            console.log(\"FAIL\");\n        }\n        console.log(\"PASS\");\n    }\n    expect_exact: [\n        \"\",\n        \"switch (42) {\",\n        \"\",\n        \"    case null:\",\n        \"\",\n        '       \\tconsole.log(\"FAIL\");',\n        \"\",\n        \"}\",\n        \"\",\n        \"\",\n        'console.log(\"PASS\");',\n    ]\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/issue-1034.js",
    "content": "non_hoisted_function_after_return: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: false,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function foo(x) {\n            if (x) {\n                return bar();\n                not_called1();\n            } else {\n                return baz();\n                not_called2();\n            }\n            function bar() { return 7; }\n            return not_reached;\n            function UnusedFunction() {}\n            function baz() { return 8; }\n        }\n    }\n    expect: {\n        function foo(x) {\n            return (x ? bar : baz)();\n            function bar() { return 7 }\n            function baz() { return 8 }\n        }\n    }\n    expect_warnings: [\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]\",\n        \"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]\",\n    ]\n}\n\nnon_hoisted_function_after_return_2a: {\n    options = {\n        booleans: true,\n        collapse_vars: false,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: false,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function foo(x) {\n            if (x) {\n                return bar(1);\n                var a = not_called(1);\n            } else {\n                return bar(2);\n                var b = not_called(2);\n            }\n            var c = bar(3);\n            function bar(x) { return 7 - x; }\n            function nope() {}\n            return b || c;\n        }\n    }\n    expect: {\n        function foo(x) {\n            return bar(x ? 1 : 2);\n            function bar(x) {\n                return 7 - x;\n            }\n        }\n    }\n    expect_warnings: [\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:4,16]\",\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:7,16]\",\n        \"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]\",\n        \"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]\",\n        \"INFO: pass 0: last_count: Infinity, count: 35\",\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]\",\n        \"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]\",\n        \"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]\",\n        \"INFO: pass 1: last_count: 35, count: 18\",\n    ]\n}\n\nnon_hoisted_function_after_return_2b: {\n    options = {\n        booleans: true,\n        collapse_vars: false,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: false,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function foo(x) {\n            if (x) {\n                return bar(1);\n            } else {\n                return bar(2);\n                var b;\n            }\n            var c = bar(3);\n            function bar(x) {\n                return 7 - x;\n            }\n            return b || c;\n        }\n    }\n    expect: {\n        function foo(x) {\n            return bar(x ? 1 : 2);\n            function bar(x) { return 7 - x; }\n        }\n    }\n    expect_warnings: [\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:8,12]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]\",\n    ]\n}\n\nnon_hoisted_function_after_return_strict: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: false,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function foo(x) {\n            if (x) {\n                return bar();\n                not_called1();\n            } else {\n                return baz();\n                not_called2();\n            }\n            function bar() { return 7; }\n            return not_reached;\n            function UnusedFunction() {}\n            function baz() { return 8; }\n        }\n        console.log(foo(0), foo(1));\n    }\n    expect: {\n        \"use strict\";\n        function foo(x) {\n            return (x ? bar : baz)();\n            function bar() { return 7 }\n            function baz() { return 8 }\n        }\n        console.log(foo(0), foo(1));\n    }\n    expect_stdout: \"8 7\"\n    expect_warnings: [\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:11,12]\",\n        \"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:12,21]\",\n    ]\n}\n\nnon_hoisted_function_after_return_2a_strict: {\n    options = {\n        booleans: true,\n        collapse_vars: false,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: false,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function foo(x) {\n            if (x) {\n                return bar(1);\n                var a = not_called(1);\n            } else {\n                return bar(2);\n                var b = not_called(2);\n            }\n            var c = bar(3);\n            function bar(x) { return 7 - x; }\n            function nope() {}\n            return b || c;\n        }\n        console.log(foo(0), foo(1));\n    }\n    expect: {\n        \"use strict\";\n        function foo(x) {\n            return bar(x ? 1 : 2);\n            function bar(x) {\n                return 7 - x;\n            }\n        }\n        console.log(foo(0), foo(1));\n    }\n    expect_stdout: \"5 6\"\n    expect_warnings: [\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:5,16]\",\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:8,16]\",\n        \"WARN: Dropping unused variable a [test/compress/issue-1034.js:5,20]\",\n        \"WARN: Dropping unused function nope [test/compress/issue-1034.js:12,21]\",\n        \"INFO: pass 0: last_count: Infinity, count: 46\",\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:10,12]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]\",\n        \"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]\",\n        \"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]\",\n        \"INFO: pass 1: last_count: 46, count: 29\",\n    ]\n}\n\nnon_hoisted_function_after_return_2b_strict: {\n    options = {\n        booleans: true,\n        collapse_vars: false,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: false,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function foo(x) {\n            if (x) {\n                return bar(1);\n            } else {\n                return bar(2);\n                var b;\n            }\n            var c = bar(3);\n            function bar(x) {\n                return 7 - x;\n            }\n            return b || c;\n        }\n        console.log(foo(0), foo(1));\n    }\n    expect: {\n        \"use strict\";\n        function foo(x) {\n            return bar(x ? 1 : 2);\n            function bar(x) { return 7 - x; }\n        }\n        console.log(foo(0), foo(1));\n    }\n    expect_stdout: \"5 6\"\n    expect_warnings: [\n        \"WARN: Dropping initialization in unreachable code [test/compress/issue-1034.js:9,12]\",\n        \"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-1041.js",
    "content": "const_pragma: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n\n    input: {\n        /** @const */ var goog = goog || {};\n    }\n    expect: {\n        var goog = goog || {};\n    }\n}\n\n// for completeness' sake\nnot_const: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n\n    input: {\n        var goog = goog || {};\n    }\n    expect: {\n        var goog = goog || {};\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1052.js",
    "content": "multiple_functions: {\n    options = {\n        hoist_funs: false,\n        if_return: true,\n    }\n    input: {\n        (function() {\n            if (!window)\n                return;\n            function f() {}\n            function g() {}\n        })();\n    }\n    expect: {\n        (function() {\n            // NOTE: other compression steps will reduce this\n            // down to just `window`.\n            if (!window);\n            function f() {}\n            function g() {}\n        })();\n    }\n}\n\nsingle_function: {\n    options = {\n        hoist_funs: false,\n        if_return: true,\n    }\n    input: {\n        (function() {\n            if (!window)\n                return;\n            function f() {}\n        })();\n    }\n    expect: {\n        (function() {\n            if (!window);\n            function f() {}\n        })();\n    }\n}\n\ndeeply_nested: {\n    options = {\n        hoist_funs: false,\n        if_return: true,\n    }\n    input: {\n        (function() {\n            if (!window)\n                return;\n            function f() {}\n            function g() {}\n            if (!document)\n                return;\n            function h() {}\n        })();\n    }\n    expect: {\n        (function() {\n            // NOTE: other compression steps will reduce this\n            // down to just `window`.\n            if (!window);\n            else if (!document);\n            function f() {}\n            function g() {}\n            function h() {}\n        })();\n    }\n}\n\nnot_hoisted_when_already_nested: {\n    options = {\n        hoist_funs: false,\n        if_return: true,\n    }\n    input: {\n        (function() {\n            if (!window)\n                return;\n            if (foo) function f() {}\n        })();\n    }\n    expect: {\n        (function() {\n            if (!window);\n            else if (foo)\n                function f() {}\n        })();\n    }\n}\n\ndefun_if_return: {\n    options = {\n        hoist_funs: false,\n        if_return: true,\n    }\n    input: {\n        function e() {\n            function f() {}\n            if (!window)\n                return;\n            else\n                function g() {}\n            function h() {}\n        }\n    }\n    expect: {\n        function e() {\n            function f() {}\n            if (!window);\n            else\n                function g() {}\n            function h() {}\n        }\n    }\n}\n\ndefun_hoist_funs: {\n    options = {\n        hoist_funs: true,\n        if_return: true,\n    }\n    input: {\n        function e() {\n            function f() {}\n            if (!window)\n                return;\n            else\n                function g() {}\n            function h() {}\n        }\n    }\n    expect: {\n        function e() {\n            function f() {}\n            function g() {}\n            function h() {}\n            if (!window);\n        }\n    }\n}\n\ndefun_else_if_return: {\n    options = {\n        hoist_funs: false,\n        if_return: true,\n    }\n    input: {\n        function e() {\n            function f() {}\n            if (window)\n                function g() {}\n            else\n                return;\n            function h() {}\n        }\n    }\n    expect: {\n        function e() {\n            function f() {}\n            if (window)\n                function g() {}\n            function h() {}\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1105.js",
    "content": "with_in_global_scope: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var o = 42;\n        with(o) {\n            var foo = 'something'\n        }\n        doSomething(o);\n    }\n    expect: {\n        var o=42;\n        with(o)\n            var foo = \"something\";\n        doSomething(o);\n    }\n}\nwith_in_function_scope: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function foo() {\n            var o = 42;\n            with(o) {\n                var foo = \"something\"\n            }\n            doSomething(o);\n        }\n    }\n    expect: {\n        function foo() {\n            var o=42;\n            with(o)\n                var foo = \"something\";\n            doSomething(o)\n        }\n    }\n}\ncompress_with_with_in_other_scope: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function foo() {\n            var o = 42;\n            with(o) {\n                var foo = \"something\"\n            }\n            doSomething(o);\n        }\n        function bar() {\n            var unused = 42;\n            return something();\n        }\n    }\n    expect: {\n        function foo() {\n            var o = 42;\n            with(o)\n                var foo = \"something\";\n            doSomething(o)\n        }\n        function bar() {\n            return something()\n        }\n    }\n}\nwith_using_existing_variable_outside_scope: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f() {\n            var o = {};\n            var unused = {}; // Doesn't get removed because upper scope uses with\n            function foo() {\n                with(o) {\n                    var foo = \"something\"\n                }\n                doSomething(o);\n            }\n            foo()\n        }\n    }\n    expect: {\n        function f() {\n            var o = {};\n            var unused = {};\n            function foo() {\n                with(o)\n                    var foo = \"something\";\n                doSomething(o)\n            }\n            foo()\n        }\n    }\n}\ncheck_drop_unused_in_peer_function: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function outer() {\n            var o = {};\n            var unused = {};     // should be kept\n            function foo() {     // should be kept\n                function not_in_use() {\n                    var nested_unused = \"foo\"; // should be dropped\n                    return 24;\n                }\n                var unused = {}; // should be kept\n                with (o) {\n                    var foo = \"something\";\n                }\n                doSomething(o);\n            }\n            function bar() {\n                var unused = {}; // should be dropped\n                doSomethingElse();\n            }\n            foo();\n            bar();\n        }\n    }\n    expect: {\n        function outer() {\n            var o = {};\n            var unused = {};     // should be kept\n            function foo() {     // should be kept\n                function not_in_use() {\n                    return 24;\n                }\n                var unused = {}; // should be kept\n                with (o)\n                    var foo = \"something\";\n                doSomething(o);\n            }\n            function bar() {\n                doSomethingElse();\n            }\n            foo();\n            bar();\n        }\n    }\n}\n\nInfinity_not_in_with_scope: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var o = { Infinity: \"FAIL\" };\n        var vInfinity = \"Infinity\";\n        vInfinity = Infinity;\n        console.log(vInfinity);\n    }\n    expect: {\n        var o = { Infinity: \"FAIL\" };\n        var vInfinity = \"Infinity\";\n        vInfinity = 1/0;\n        console.log(vInfinity);\n    }\n    expect_stdout: \"Infinity\"\n}\n\nInfinity_in_with_scope: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var o = { Infinity: \"PASS\" };\n        var vInfinity = \"Infinity\";\n        with (o) { vInfinity = Infinity; }\n        console.log(vInfinity);\n    }\n    expect: {\n        var o = { Infinity: \"PASS\" };\n        var vInfinity = \"Infinity\";\n        with (o) vInfinity = Infinity;\n        console.log(vInfinity);\n    }\n    expect_stdout: \"PASS\"\n}\n\nassorted_Infinity_NaN_undefined_in_with_scope: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        keep_infinity: false,\n        sequences: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var f = console.log;\n        var o = {\n            undefined : 3,\n            NaN       : 4,\n            Infinity  : 5,\n        };\n        if (o) {\n            f(undefined, void 0);\n            f(NaN, 0/0);\n            f(Infinity, 1/0);\n            f(-Infinity, -(1/0));\n            f(2 + 7 + undefined, 2 + 7 + void 0);\n        }\n        with (o) {\n            f(undefined, void 0);\n            f(NaN, 0/0);\n            f(Infinity, 1/0);\n            f(-Infinity, -(1/0));\n            f(2 + 7 + undefined, 2 + 7 + void 0);\n        }\n    }\n    expect: {\n        var f = console.log, o = {\n            undefined : 3,\n            NaN       : 4,\n            Infinity  : 5\n        };\n        if (o) {\n            f(void 0, void 0);\n            f(NaN, NaN);\n            f(1/0, 1/0);\n            f(-1/0, -1/0);\n            f(NaN, NaN);\n        }\n        with (o) {\n            f(undefined, void 0);\n            f(NaN, 0/0);\n            f(Infinity, 1/0);\n            f(-Infinity, -1/0);\n            f(9 + undefined, 9 + void 0);\n        }\n    }\n    expect_stdout: true\n}\n\nassorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        keep_infinity: true,\n        sequences: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var f = console.log;\n        var o = {\n            undefined : 3,\n            NaN       : 4,\n            Infinity  : 5,\n        };\n        if (o) {\n            f(undefined, void 0);\n            f(NaN, 0/0);\n            f(Infinity, 1/0);\n            f(-Infinity, -(1/0));\n            f(2 + 7 + undefined, 2 + 7 + void 0);\n        }\n        with (o) {\n            f(undefined, void 0);\n            f(NaN, 0/0);\n            f(Infinity, 1/0);\n            f(-Infinity, -(1/0));\n            f(2 + 7 + undefined, 2 + 7 + void 0);\n        }\n    }\n    expect: {\n        var f = console.log, o = {\n            undefined : 3,\n            NaN       : 4,\n            Infinity  : 5\n        };\n        if (o) {\n            f(void 0, void 0);\n            f(NaN, NaN);\n            f(Infinity, 1/0);\n            f(-Infinity, -1/0);\n            f(NaN, NaN);\n        }\n        with (o) {\n            f(undefined, void 0);\n            f(NaN, 0/0);\n            f(Infinity, 1/0);\n            f(-Infinity, -1/0);\n            f(9 + undefined, 9 + void 0);\n        }\n    }\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/issue-12.js",
    "content": "keep_name_of_getter: {\n    options = {\n        unused: true,\n    }\n    input: {\n        a = {\n            get foo() {},\n        };\n    }\n    expect: {\n        a = {\n            get foo() {},\n        };\n    }\n}\n\nkeep_name_of_setter: {\n    options = {\n        unused: true,\n    }\n    input: {\n        a = {\n            set foo(v) {},\n        };\n    }\n    expect: {\n        a = {\n            set foo(v) {},\n        };\n    }\n}\n\nsetter_with_operator_keys: {\n    input: {\n        var tokenCodes = {\n            get instanceof() {\n                return test0;\n            },\n            set instanceof(value) {\n                test0 = value;\n            },\n            set typeof(value) {\n                test1 = value;\n            },\n            get typeof() {\n                return test1;\n            },\n            set else(value) {\n                test2 = value;\n            },\n            get else() {\n                return test2;\n            },\n        };\n    }\n    expect: {\n        var tokenCodes = {\n            get instanceof() {\n                return test0;\n            },\n            set instanceof(value) {\n                test0 = value;\n            },\n            set typeof(value) {\n                test1 = value;\n            },\n            get typeof() {\n                return test1;\n            },\n            set else(value) {\n                test2 = value;\n            },\n            get else() {\n                return test2;\n            },\n        };\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1202.js",
    "content": "mangle_keep_fnames_false: {\n    options = {\n        keep_fargs: true,\n        keep_fnames: true,\n    }\n    mangle = {\n        keep_fnames: false,\n    }\n    input: {\n        \"use strict\";\n        function total() {\n            return function n(a, b, c) {\n                return a + b + c;\n            };\n        }\n    }\n    expect: {\n        \"use strict\";\n        function total() {\n            return function t(n, r, u) {\n                return n + r + u;\n            };\n        }\n    }\n}\n\nmangle_keep_fnames_true: {\n    options = {\n        keep_fargs: true,\n        keep_fnames: true,\n    }\n    mangle = {\n        keep_fnames: true,\n    }\n    input: {\n        \"use strict\";\n        function total() {\n            return function n(a, b, c) {\n                return a + b + c;\n            };\n        }\n    }\n    expect: {\n        \"use strict\";\n        function total() {\n            return function n(t, r, u) {\n                return t + r + u;\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-126.js",
    "content": "concatenate_rhs_strings: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        foo(bar() + 123 + \"Hello\" + \"World\");\n        foo(bar() + (123 + \"Hello\") + \"World\");\n        foo((bar() + 123) + \"Hello\" + \"World\");\n        foo(bar() + 123 + \"Hello\" + \"World\" + (\"Foo\" + \"Bar\"));\n        foo(\"Foo\" + \"Bar\" + bar() + 123 + \"Hello\" + \"World\" + (\"Foo\" + \"Bar\"));\n        foo(\"Hello\" + bar() + 123 + \"World\");\n        foo(bar() + 'Foo' + (10 + parseInt('10')));\n    }\n    expect: {\n        foo(bar() + 123 + \"HelloWorld\");\n        foo(bar() + \"123HelloWorld\");\n        foo((bar() + 123) + \"HelloWorld\");\n        foo(bar() + 123 + \"HelloWorldFooBar\");\n        foo(\"FooBar\" + bar() + \"123HelloWorldFooBar\");\n        foo(\"Hello\" + bar() + \"123World\");\n        foo(bar() + 'Foo' + (10 + parseInt('10')));\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1261.js",
    "content": "pure_function_calls: {\n    options = {\n        annotations: true,\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        evaluate: true,\n        if_return: true,\n        join_vars: true,\n        negate_iife: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        // pure top-level IIFE will be dropped\n        // @__PURE__ - comment\n        (function() {\n            console.log(\"iife0\");\n        })();\n\n        // pure top-level IIFE assigned to unreferenced var will not be dropped\n        var iife1 = /*@__PURE__*/(function() {\n            console.log(\"iife1\");\n            function iife1() {}\n            return iife1;\n        })();\n\n        (function(){\n            // pure IIFE in function scope assigned to unreferenced var will be dropped\n            var iife2 = /*#__PURE__*/(function() {\n                console.log(\"iife2\");\n                function iife2() {}\n                return iife2;\n            })();\n        })();\n\n        // comment #__PURE__ comment\n        bar(), baz(), quux();\n        a.b(), /* @__PURE__ */ c.d.e(), f.g();\n    }\n    expect: {\n        var iife1 = function() {\n            console.log(\"iife1\");\n            function iife1() {}\n            return iife1;\n        }();\n\n        baz(), quux();\n        a.b(), f.g();\n    }\n    expect_warnings: [\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]\",\n        \"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:25,31]\",\n    ]\n}\n\npure_function_calls_toplevel: {\n    options = {\n        annotations: true,\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        evaluate: true,\n        if_return: true,\n        join_vars: true,\n        negate_iife: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        // pure top-level IIFE will be dropped\n        // @__PURE__ - comment\n        (function() {\n            console.log(\"iife0\");\n        })();\n\n        // pure top-level IIFE assigned to unreferenced var will be dropped\n        var iife1 = /*@__PURE__*/(function() {\n            console.log(\"iife1\");\n            function iife1() {}\n            return iife1;\n        })();\n\n        (function(){\n            // pure IIFE in function scope assigned to unreferenced var will be dropped\n            var iife2 = /*#__PURE__*/(function() {\n                console.log(\"iife2\");\n                function iife2() {}\n                return iife2;\n            })();\n        })();\n\n        // pure top-level calls will be dropped regardless of the leading comments position\n        var MyClass = /*#__PURE__*//*@class*/(function(){\n            function MyClass() {}\n            MyClass.prototype.method = function() {};\n            return MyClass;\n        })();\n\n        // comment #__PURE__ comment\n        bar(), baz(), quux();\n        a.b(), /* @__PURE__ */ c.d.e(), f.g();\n    }\n    expect: {\n        baz(), quux();\n        a.b(), f.g();\n    }\n    expect_warnings: [\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]\",\n        \"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:31,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:32,31]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,33]\",\n        \"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:8,12]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,45]\",\n        \"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:24,12]\",\n    ]\n}\n\nshould_warn: {\n    options = {\n        annotations: true,\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        /* @__PURE__ */(function(){x})(), void/* @__PURE__ */(function(){y})();\n        /* @__PURE__ */(function(){x})() || true ? foo() : bar();\n        true || /* @__PURE__ */(function(){y})() ? foo() : bar();\n        /* @__PURE__ */(function(){x})() && false ? foo() : bar();\n        false && /* @__PURE__ */(function(){y})() ? foo() : bar();\n        /* @__PURE__ */(function(){x})() + \"foo\" ? bar() : baz();\n        \"foo\" + /* @__PURE__ */(function(){y})() ? bar() : baz();\n        /* @__PURE__ */(function(){x})() ? foo() : foo();\n        [/* @__PURE__ */(function(){x})()] ? foo() : bar();\n        !{ foo: /* @__PURE__ */(function(){x})() } ? bar() : baz();\n    }\n    expect: {\n        foo();\n        foo();\n        bar();\n        bar();\n        bar();\n        bar();\n        foo();\n        foo();\n        baz();\n    }\n    expect_warnings: [\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,61]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,23]\",\n        \"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:1,23]\",\n        \"WARN: Boolean || always true [test/compress/issue-1261.js:2,23]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:2,23]\",\n        \"WARN: Condition always true [test/compress/issue-1261.js:2,23]\",\n        \"WARN: Condition left of || always true [test/compress/issue-1261.js:3,8]\",\n        \"WARN: Condition always true [test/compress/issue-1261.js:3,8]\",\n        \"WARN: Boolean && always false [test/compress/issue-1261.js:4,23]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:4,23]\",\n        \"WARN: Condition always false [test/compress/issue-1261.js:4,23]\",\n        \"WARN: Condition left of && always false [test/compress/issue-1261.js:5,8]\",\n        \"WARN: Condition always false [test/compress/issue-1261.js:5,8]\",\n        \"WARN: + in boolean context always true [test/compress/issue-1261.js:6,23]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:6,23]\",\n        \"WARN: Condition always true [test/compress/issue-1261.js:6,23]\",\n        \"WARN: + in boolean context always true [test/compress/issue-1261.js:7,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:7,31]\",\n        \"WARN: Condition always true [test/compress/issue-1261.js:7,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,23]\",\n        \"WARN: Condition always true [test/compress/issue-1261.js:9,8]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:9,24]\",\n        \"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:10,31]\",\n        \"WARN: Condition always false [test/compress/issue-1261.js:10,8]\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-1275.js",
    "content": "string_plus_optimization: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function foo(anything) {\n            function throwing_function() {\n                throw \"nope\";\n            }\n            try {\n                console.log('0' + throwing_function() ? \"yes\" : \"no\");\n            } catch (ex) {\n                console.log(ex);\n            }\n            console.log('0' + anything ? \"yes\" : \"no\");\n            console.log(anything + '0' ? \"Yes\" : \"No\");\n            console.log('' + anything);\n            console.log(anything + '');\n        }\n        foo();\n    }\n    expect: {\n        function foo(anything) {\n            function throwing_function() {\n                throw \"nope\";\n            }\n            try {\n                console.log((throwing_function(), \"yes\"));\n            } catch (ex) {\n                console.log(ex);\n            }\n            console.log(\"yes\");\n            console.log(\"Yes\");\n            console.log('' + anything);\n            console.log(anything + '');\n        }\n        foo();\n    }\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/issue-1321.js",
    "content": "issue_1321_no_debug: {\n    mangle = {\n        properties: {\n            domprops: true,\n            keep_quoted: true,\n        },\n    }\n    input: {\n        var x = {};\n        x.foo = 1;\n        x[\"a\"] = 2 * x.foo;\n        console.log(x.foo, x[\"a\"]);\n    }\n    expect: {\n        var x = {};\n        x.x = 1;\n        x[\"a\"] = 2 * x.x;\n        console.log(x.x, x[\"a\"]);\n    }\n    expect_stdout: true\n}\n\nissue_1321_debug: {\n    mangle = {\n        properties: {\n            debug: \"\",\n            domprops: true,\n            keep_quoted: true,\n        },\n    }\n    input: {\n        var x = {};\n        x.foo = 1;\n        x[\"_$foo$_\"] = 2 * x.foo;\n        console.log(x.foo, x[\"_$foo$_\"]);\n    }\n    expect: {\n        var x = {};\n        x.x = 1;\n        x[\"_$foo$_\"] = 2 * x.x;\n        console.log(x.x, x[\"_$foo$_\"]);\n    }\n    expect_stdout: true\n}\n\nissue_1321_with_quoted: {\n    mangle = {\n        properties: {\n            domprops: true,\n            keep_quoted: false,\n        },\n    }\n    input: {\n        var x = {};\n        x.foo = 1;\n        x[\"a\"] = 2 * x.foo;\n        console.log(x.foo, x[\"a\"]);\n    }\n    expect: {\n        var x = {};\n        x.x = 1;\n        x[\"o\"] = 2 * x.x;\n        console.log(x.x, x[\"o\"]);\n    }\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/issue-143.js",
    "content": "/**\n * There was an incorrect sort behavior documented in issue #143:\n * (x = f(…)) <= x → x >= (x = f(…))\n *\n * For example, let the equation be:\n * (a = parseInt('100')) <= a\n *\n * If a was an integer and has the value of 99,\n * (a = parseInt('100')) <= a → 100 <= 100 → true\n *\n * When transformed incorrectly:\n * a >= (a = parseInt('100')) → 99 >= 100 → false\n */\n\ntransformation_sort_order_equal: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        console.log((a = parseInt(\"100\")) == a);\n    }\n    expect: {\n        console.log((a = parseInt(\"100\")) == a);\n    }\n    expect_stdout: \"true\"\n}\n\ntransformation_sort_order_unequal: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        console.log((a = parseInt(\"100\")) != a);\n    }\n    expect: {\n        console.log((a = parseInt(\"100\")) != a);\n    }\n    expect_stdout: \"false\"\n}\n\ntransformation_sort_order_lesser_or_equal: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        console.log((a = parseInt(\"100\")) <= a);\n    }\n    expect: {\n        console.log((a = parseInt(\"100\")) <= a);\n    }\n    expect_stdout: \"true\"\n}\n\ntransformation_sort_order_greater_or_equal: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        console.log((a = parseInt(\"100\")) >= a);\n    }\n    expect: {\n        console.log((a = parseInt(\"100\")) >= a);\n    }\n    expect_stdout: \"true\"\n}\n"
  },
  {
    "path": "test/compress/issue-1431.js",
    "content": "level_zero: {\n    options = {\n        keep_fnames: true,\n    }\n    mangle = {\n        keep_fnames: true\n    }\n    input: {\n        function f(x) {\n            function n(a) {\n                return a * a;\n            }\n            return function() {\n                return x;\n            };\n        }\n    }\n    expect: {\n        function f(r) {\n            function n(n) {\n                return n * n;\n            }\n            return function() {\n                return r;\n            };\n        }\n    }\n}\n\nlevel_one: {\n    options = {\n        keep_fnames: true,\n    }\n    mangle = {\n        keep_fnames: true\n    }\n    input: {\n        function f(x) {\n            return function() {\n                function n(a) {\n                    return a * a;\n                }\n                return x(n);\n            };\n        }\n    }\n    expect: {\n        function f(r) {\n            return function() {\n                function n(n) {\n                    return n * n;\n                }\n                return r(n);\n            };\n        }\n    }\n}\n\nlevel_two: {\n    options = {\n        keep_fnames: true,\n    }\n    mangle = {\n        keep_fnames: true\n    }\n    input: {\n        function f(x) {\n            return function() {\n                function r(a) {\n                    return a * a;\n                }\n                return function() {\n                    function n(a) {\n                        return a * a;\n                    }\n                    return x(n);\n                };\n            };\n        }\n    }\n    expect: {\n        function f(t) {\n            return function() {\n                function r(n) {\n                    return n * n;\n                }\n                return function() {\n                    function n(n) {\n                        return n * n;\n                    }\n                    return t(n);\n                };\n            };\n        }\n    }\n}\n\nlevel_three: {\n    options = {\n        keep_fnames: true,\n    }\n    mangle = {\n        keep_fnames: true\n    }\n    input: {\n        function f(x) {\n            return function() {\n                function r(a) {\n                    return a * a;\n                }\n                return [\n                    function() {\n                        function t(a) {\n                            return a * a;\n                        }\n                        return t;\n                    },\n                    function() {\n                        function n(a) {\n                            return a * a;\n                        }\n                        return x(n);\n                    }\n                ];\n            };\n        }\n    }\n    expect: {\n        function f(t) {\n            return function() {\n                function r(n) {\n                    return n * n;\n                }\n                return [\n                    function() {\n                        function t(n) {\n                            return n * n;\n                        }\n                        return t;\n                    },\n                    function() {\n                        function n(n) {\n                            return n * n;\n                        }\n                        return t(n);\n                    }\n                ];\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1443.js",
    "content": "// tests assume that variable `undefined` not redefined and has `void 0` as value\n\nunsafe_undefined: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        unsafe_undefined: true,\n    }\n    mangle = {}\n    input: {\n        function f(undefined) {\n            return function() {\n                if (a)\n                    return b;\n                if (c)\n                    return d;\n            };\n        }\n    }\n    expect: {\n        function f(n) {\n            return function() {\n                return a ? b : c ? d : n;\n            };\n        }\n    }\n}\n\nkeep_fnames: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        unsafe_undefined: true,\n    }\n    mangle = {\n        keep_fnames: true\n    }\n    input: {\n        function f(undefined) {\n            return function() {\n                function n(a) {\n                    return a * a;\n                }\n                if (a)\n                    return b;\n                if (c)\n                    return d;\n            };\n        }\n    }\n    expect: {\n        function f(r) {\n            return function() {\n                function n(n) {\n                    return n * n;\n                }\n                return a ? b : c ? d : r;\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1446.js",
    "content": "typeof_eq_undefined: {\n    options = {\n        comparisons: true,\n        typeofs: true,\n    }\n    input: {\n        var a = typeof b != \"undefined\";\n        b = typeof a != \"undefined\";\n        var c = typeof d.e !== \"undefined\";\n        var f = \"undefined\" === typeof g;\n        g = \"undefined\" === typeof f;\n        var h = \"undefined\" == typeof i.j;\n    }\n    expect: {\n        var a = \"undefined\" != typeof b;\n        b = void 0 !== a;\n        var c = void 0 !== d.e;\n        var f = \"undefined\" == typeof g;\n        g = void 0 === f;\n        var h = void 0 === i.j;\n    }\n}\n\ntypeof_eq_undefined_ie8: {\n    options = {\n        comparisons: true,\n        ie: true,\n        typeofs: true,\n    }\n    input: {\n        var a = typeof b != \"undefined\";\n        b = typeof a != \"undefined\";\n        var c = typeof d.e !== \"undefined\";\n        var f = \"undefined\" === typeof g;\n        g = \"undefined\" === typeof f;\n        var h = \"undefined\" == typeof i.j;\n    }\n    expect: {\n        var a = \"undefined\" != typeof b;\n        b = void 0 !== a;\n        var c = \"undefined\" != typeof d.e;\n        var f = \"undefined\" == typeof g;\n        g = void 0 === f;\n        var h = \"undefined\" == typeof i.j;\n    }\n}\n\nundefined_redefined: {\n    options = {\n        comparisons: true,\n        typeofs: true,\n    }\n    input: {\n        function f(undefined) {\n            var n = 1;\n            return typeof n == \"undefined\";\n        }\n    }\n    expect_exact: \"function f(undefined){var n=1;return void 0===n}\"\n}\n\nundefined_redefined_mangle: {\n    options = {\n        comparisons: true,\n        typeofs: true,\n    }\n    mangle = {}\n    input: {\n        function f(undefined) {\n            var n = 1;\n            return typeof n == \"undefined\";\n        }\n    }\n    expect_exact: \"function f(n){var r=1;return void 0===r}\"\n}\n"
  },
  {
    "path": "test/compress/issue-1447.js",
    "content": "else_with_empty_block: {\n    options = {}\n    input: {\n        if (x)\n            yes();\n        else {\n        }\n    }\n    expect_exact: \"if(x)yes();\"\n}\n\nelse_with_empty_statement: {\n    options = {}\n    input: {\n        if (x)\n            yes();\n        else\n            ;\n    }\n    expect_exact: \"if(x)yes();\"\n}\n\nconditional_false_stray_else_in_loop: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: false,\n        dead_code: true,\n        evaluate: true,\n        hoist_vars: true,\n        if_return: true,\n        join_vars: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        for (var i = 1; i <= 4; ++i) {\n            if (i <= 2) continue;\n            console.log(i);\n        }\n    }\n    expect_exact: \"for(var i=1;i<=4;++i)if(i<=2);else console.log(i);\"\n    expect_stdout: [\n        \"3\",\n        \"4\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-1569.js",
    "content": "inner_reference: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        !function f(a) {\n            return a && f(a - 1) + a;\n        }(42);\n        !function g(a) {\n            return a;\n        }(42);\n    }\n    expect: {\n        !function f(a) {\n            return a && f(a - 1) + a;\n        }(42);\n        !void 0;\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1588.js",
    "content": "screw_ie8: {\n    options = {\n        ie: false,\n    }\n    mangle = {\n        ie: false,\n    }\n    input: {\n        try { throw \"foo\"; } catch (x) { console.log(x); }\n    }\n    expect_exact: 'try{throw\"foo\"}catch(o){console.log(o)}'\n    expect_stdout: [\n        \"foo\"\n    ]\n}\n\nsupport_ie8: {\n    options = {\n        ie: true,\n    }\n    mangle = {\n        ie: true,\n    }\n    input: {\n        try { throw \"foo\"; } catch (x) { console.log(x); }\n    }\n    expect_exact: 'try{throw\"foo\"}catch(x){console.log(x)}'\n    expect_stdout: \"foo\"\n}\n\nsafe_undefined: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        unsafe: false,\n    }\n    mangle = {}\n    input: {\n        var a, c;\n        console.log(function(undefined) {\n            return function() {\n                if (a)\n                    return b;\n                if (c)\n                    return d;\n            };\n        }(1)());\n    }\n    expect: {\n        var a, c;\n        console.log(function(n) {\n            return function() {\n                return a ? b : c ? d : void 0;\n            };\n        }(1)());\n    }\n    expect_stdout: true\n}\n\nunsafe_undefined: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        unsafe_undefined: true,\n    }\n    mangle = {}\n    input: {\n        var a, c;\n        console.log(function(undefined) {\n            return function() {\n                if (a)\n                    return b;\n                if (c)\n                    return d;\n            };\n        }()());\n    }\n    expect: {\n        var a, c;\n        console.log(function(n) {\n            return function() {\n                return a ? b : c ? d : n;\n            };\n        }()());\n    }\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/issue-1609.js",
    "content": "chained_evaluation_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = 1;\n            (function() {\n                var b = a, c;\n                c = f(b);\n                c.bar = b;\n            })();\n        })();\n    }\n    expect: {\n        (function() {\n            (function() {\n                f(1).bar = 1;\n            })();\n        })();\n    }\n}\n\nchained_evaluation_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = \"long piece of string\";\n            (function() {\n                var b = a, c;\n                c = f(b);\n                c.bar = b;\n            })();\n        })();\n    }\n    expect: {\n        (function() {\n            (function() {\n                var b = \"long piece of string\";\n                f(b).bar = b;\n            })();\n        })();\n    }\n}\n\nchained_evaluation_3: {\n    options = {\n        collapse_vars: true,\n        evaluate: 10,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = \"long piece of string\";\n            (function() {\n                var b = a, c;\n                c = f(b);\n                c.bar = b;\n            })();\n        })();\n    }\n    expect: {\n        (function() {\n            (function() {\n                f(\"long piece of string\").bar = \"long piece of string\";\n            })();\n        })();\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1639.js",
    "content": "issue_1639_1: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        join_vars: true,\n        loops: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        var L1 = 5;\n        while (--L1 > 0) {\n            if ((--b), false) {\n                if (b) {\n                    var ignore = 0;\n                }\n            }\n        }\n        console.log(a, b);\n    }\n    expect: {\n        for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {\n            --b;\n        }\n        console.log(a, b);\n    }\n    expect_stdout: \"100 6\"\n}\n\nissue_1639_2: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        join_vars: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        function f19() {\n            if (++a, false)\n                if (a)\n                    if (++a);\n        }\n        f19();\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        function f19() {\n            ++a, 1;\n        }\n        f19(),\n        console.log(a, b);\n    }\n    expect_stdout: \"101 10\"\n}\n\nissue_1639_3: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        a++ && false && a ? 0 : 0;\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        a++,\n        console.log(a, b);\n    }\n    expect_stdout: \"101 10\"\n}\n"
  },
  {
    "path": "test/compress/issue-1656.js",
    "content": "f7: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        drop_debugger: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        loops: true,\n        negate_iife: true,\n        passes: 3,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        function f22464() {\n            var brake146670 = 5;\n            while (((b = a) ? !a : ~a ? null : b += a) && --brake146670 > 0) {\n            }\n        }\n        f22464();\n        console.log(a, b);\n    }\n    expect_exact: [\n        \"console.log(100, 100);\",\n    ]\n    expect_stdout: \"100 100\"\n}\n"
  },
  {
    "path": "test/compress/issue-1673.js",
    "content": "side_effects_catch: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                try {\n                    throw 0;\n                } catch (e) {\n                    console.log(\"PASS\");\n                }\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            (function() {\n                try {\n                    throw 0;\n                } catch (e) {\n                    console.log(\"PASS\");\n                }\n            })();\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nside_effects_else: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n            function g() {\n                if (x);\n                else console.log(\"PASS\");\n            }\n            g();\n        }\n        f(0);\n    }\n    expect: {\n        function f(x) {\n            (function() {\n                if (x);\n                else console.log(\"PASS\");\n            })();\n        }\n        f(0);\n    }\n    expect_stdout: \"PASS\"\n}\n\nside_effects_finally: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                try {\n                    x();\n                } catch (e) {\n                } finally {\n                    console.log(\"PASS\");\n                }\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            (function() {\n                try {\n                    x();\n                } catch (e) {\n                } finally {\n                    console.log(\"PASS\");\n                }\n            })();\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nside_effects_label: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n            function g() {\n                L: {\n                    console.log(\"PASS\");\n                    break L;\n                }\n            }\n            g();\n        }\n        f(0);\n    }\n    expect: {\n        function f(x) {\n            (function() {\n                L: {\n                    console.log(\"PASS\");\n                    break L;\n                }\n            })();\n        }\n        f(0);\n    }\n    expect_stdout: \"PASS\"\n}\n\nside_effects_switch: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                switch (0) {\n                  default:\n                  case console.log(\"PASS\"):\n                }\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            (function() {\n                switch (0) {\n                  default:\n                  case console.log(\"PASS\"):\n                }\n            })();\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/issue-1704.js",
    "content": "mangle_catch: {\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(o){a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_ie8: {\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(args){a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var: {\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(o){var a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var_ie8: {\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(args){var a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_toplevel: {\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var c=\"FAIL\";try{throw 1}catch(o){c=\"PASS\"}console.log(c);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_ie8_toplevel: {\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"FAIL\";try{throw 1}catch(c){o=\"PASS\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var_toplevel: {\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var r=\"FAIL\";try{throw 1}catch(o){var r=\"PASS\"}console.log(r);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var_ie8_toplevel: {\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"FAIL\";try{throw 1}catch(r){var o=\"PASS\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1: {\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"PASS\";try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1_ie8: {\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"PASS\";try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1_toplevel: {\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"PASS\";try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1_ie8_toplevel: {\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"PASS\";try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_2: {\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_2_ie8: {\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_2_toplevel: {\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_2_ie8_toplevel: {\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_3: {\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var o = \"PASS\";\n        try {\n            throw 0;\n        } catch (o) {\n            // prints \"FAIL\" if inlined on Node.js v4-\n            (function() {\n                function f() {\n                    o = \"FAIL\";\n                }\n                f(), f();\n            })();\n        }\n        console.log(o);\n    }\n    expect_exact: 'var o=\"PASS\";try{throw 0}catch(o){(function(){function c(){o=\"FAIL\"}c(),c()})()}console.log(o);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_catch_redef_3_toplevel: {\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var o = \"PASS\";\n        try {\n            throw 0;\n        } catch (o) {\n            // prints \"FAIL\" if inlined on Node.js v4-\n            (function() {\n                function f() {\n                    o = \"FAIL\";\n                }\n                f(), f();\n            })();\n        }\n        console.log(o);\n    }\n    expect_exact: 'var c=\"PASS\";try{throw 0}catch(c){(function(){function o(){c=\"FAIL\"}o(),o()})()}console.log(c);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_catch_redef_3_ie8: {\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var o = \"PASS\";\n        try {\n            throw 0;\n        } catch (o) {\n            // prints \"FAIL\" if inlined on Node.js v4-\n            (function() {\n                function f() {\n                    o = \"FAIL\";\n                }\n                f(), f();\n            })();\n        }\n        console.log(o);\n    }\n    expect_exact: 'var o=\"PASS\";try{throw 0}catch(o){(function(){function c(){o=\"FAIL\"}c(),c()})()}console.log(o);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmangle_catch_redef_3_ie8_toplevel: {\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var o = \"PASS\";\n        try {\n            throw 0;\n        } catch (o) {\n            // prints \"FAIL\" if inlined on Node.js v4-\n            (function() {\n                function f() {\n                    o = \"FAIL\";\n                }\n                f(), f();\n            })();\n        }\n        console.log(o);\n    }\n    expect_exact: 'var c=\"PASS\";try{throw 0}catch(c){(function(){function o(){c=\"FAIL\"}o(),o()})()}console.log(c);'\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n"
  },
  {
    "path": "test/compress/issue-1733.js",
    "content": "function_iife_catch: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        function f(n) {\n            !function() {\n                try {\n                    throw 0;\n                } catch (n) {\n                    var a = 1;\n                    console.log(n, a);\n                }\n            }();\n        }\n        f();\n    }\n    expect_exact: \"function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();\"\n    expect_stdout: \"0 1\"\n}\n\nfunction_iife_catch_ie8: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        function f(n) {\n            !function() {\n                try {\n                    throw 0;\n                } catch (n) {\n                    var a = 1;\n                    console.log(n, a);\n                }\n            }();\n        }\n        f();\n    }\n    expect_exact: \"function f(c){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();\"\n    expect_stdout: \"0 1\"\n}\n\nfunction_catch_catch: {\n    mangle = {\n        ie: false,\n    }\n    input: {\n        var o = 0;\n        function f() {\n            try {\n                throw 1;\n            } catch (c) {\n                try {\n                    throw 2;\n                } catch (o) {\n                    var o = 3;\n                    console.log(o);\n                }\n            }\n            console.log(o);\n        }\n        f();\n    }\n    expect_exact: \"var o=0;function f(){try{throw 1}catch(o){try{throw 2}catch(c){var c=3;console.log(c)}}console.log(c)}f();\"\n    expect_stdout: [\n        \"3\",\n        \"undefined\",\n    ]\n}\n\nfunction_catch_catch_ie8: {\n    mangle = {\n        ie: true,\n    }\n    input: {\n        var o = 0;\n        function f() {\n            try {\n                throw 1;\n            } catch (c) {\n                try {\n                    throw 2;\n                } catch (o) {\n                    var o = 3;\n                    console.log(o);\n                }\n            }\n            console.log(o);\n        }\n        f();\n    }\n    expect_exact: \"var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();\"\n    expect_stdout: [\n        \"3\",\n        \"undefined\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-1750.js",
    "content": "case_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        switch (true) {\n          case a || true:\n          default:\n            b = 2;\n          case true:\n        }\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 1;\n        switch (true) {\n          case a || true:\n            b = 2;\n        }\n        console.log(a, b);\n    }\n    expect_stdout: \"0 2\"\n}\n\ncase_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        switch (0) {\n          default:\n            b = 2;\n          case a:\n            a = 3;\n          case 0:\n        }\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 1;\n        switch (0) {\n          case a:\n            a = 3;\n        }\n        console.log(a, b);\n    }\n    expect_stdout: \"3 1\"\n}\n"
  },
  {
    "path": "test/compress/issue-1770.js",
    "content": "mangle_props: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        var obj = {\n            undefined: 1,\n            NaN: 2,\n            Infinity: 3,\n            \"-Infinity\": 4,\n            null: 5,\n        };\n        console.log(\n            obj[void 0],\n            obj[undefined],\n            obj[\"undefined\"],\n            obj[0/0],\n            obj[NaN],\n            obj[\"NaN\"],\n            obj[1/0],\n            obj[Infinity],\n            obj[\"Infinity\"],\n            obj[-1/0],\n            obj[-Infinity],\n            obj[\"-Infinity\"],\n            obj[null],\n            obj[\"null\"]\n        );\n    }\n    expect: {\n        var obj = {\n            undefined: 1,\n            NaN: 2,\n            Infinity: 3,\n            \"-Infinity\": 4,\n            null: 5,\n        };\n        console.log(\n            obj[void 0],\n            obj[void 0],\n            obj[\"undefined\"],\n            obj[0/0],\n            obj[NaN],\n            obj[\"NaN\"],\n            obj[1/0],\n            obj[1/0],\n            obj[\"Infinity\"],\n            obj[-1/0],\n            obj[-(1/0)],\n            obj[\"-Infinity\"],\n            obj[null],\n            obj[\"null\"]\n        );\n    }\n    expect_stdout: \"1 1 1 2 2 2 3 3 3 4 4 4 5 5\"\n    expect_warnings: [\n        \"INFO: Preserving reserved property undefined\",\n        \"INFO: Preserving reserved property NaN\",\n        \"INFO: Preserving reserved property Infinity\",\n        \"INFO: Preserving reserved property -Infinity\",\n        \"INFO: Preserving reserved property null\",\n        \"INFO: Preserving reserved property log\",\n    ]\n}\n\nnumeric_literal: {\n    mangle = {\n        properties: {\n            domprops: true,\n        },\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        var obj = {\n            0: 0,\n            \"-0\": 1,\n            42: 2,\n            \"42\": 3,\n            0x25: 4,\n            \"0x25\": 5,\n            1E42: 6,\n            \"1E42\": 7,\n            \"1e+42\": 8,\n        };\n        console.log(obj[-0], obj[-\"\"], obj[\"-0\"]);\n        console.log(obj[42], obj[\"42\"]);\n        console.log(obj[0x25], obj[\"0x25\"], obj[37], obj[\"37\"]);\n        console.log(obj[1E42], obj[\"1E42\"], obj[\"1e+42\"]);\n    }\n    expect_exact: [\n        'var obj = {',\n        '    0: 0,',\n        '    \"-0\": 1,',\n        '    42: 2,',\n        '    42: 3,',\n        '    37: 4,',\n        '    o: 5,',\n        '    1e42: 6,',\n        '    b: 7,',\n        '    1e42: 8',\n        '};',\n        '',\n        'console.log(obj[-0], obj[-\"\"], obj[\"-0\"]);',\n        '',\n        'console.log(obj[42], obj[\"42\"]);',\n        '',\n        'console.log(obj[37], obj[\"o\"], obj[37], obj[\"37\"]);',\n        '',\n        'console.log(obj[1e42], obj[\"b\"], obj[\"1e+42\"]);',\n    ]\n    expect_stdout: [\n        \"0 0 1\",\n        \"3 3\",\n        \"4 5 4 4\",\n        \"8 7 8\",\n    ]\n    expect_warnings: [\n        \"INFO: Mapping property 0x25 to o\",\n        \"INFO: Mapping property 1E42 to b\",\n        \"INFO: Preserving reserved property log\",\n    ]\n}\n\nidentifier: {\n    mangle = {\n        properties: {\n            builtins: true,\n            domprops: true,\n        },\n    }\n    input: {\n        var obj = {\n            abstract: 1,\n            boolean: 2,\n            byte: 3,\n            char: 4,\n            class: 5,\n            double: 6,\n            enum: 7,\n            export: 8,\n            extends: 9,\n            final: 10,\n            float: 11,\n            goto: 12,\n            implements: 13,\n            import: 14,\n            int: 15,\n            interface: 16,\n            let: 17,\n            long: 18,\n            native: 19,\n            package: 20,\n            private: 21,\n            protected: 22,\n            public: 23,\n            short: 24,\n            static: 25,\n            super: 26,\n            synchronized: 27,\n            this: 28,\n            throws: 29,\n            transient: 30,\n            volatile: 31,\n            yield: 32,\n            false: 33,\n            null: 34,\n            true: 35,\n            break: 36,\n            case: 37,\n            catch: 38,\n            const: 39,\n            continue: 40,\n            debugger: 41,\n            default: 42,\n            delete: 43,\n            do: 44,\n            else: 45,\n            finally: 46,\n            for: 47,\n            function: 48,\n            if: 49,\n            in: 50,\n            instanceof: 51,\n            new: 52,\n            return: 53,\n            switch: 54,\n            throw: 55,\n            try: 56,\n            typeof: 57,\n            var: 58,\n            void: 59,\n            while: 60,\n            with: 61,\n        };\n    }\n    expect: {\n        var obj = {\n            e: 1,\n            t: 2,\n            n: 3,\n            a: 4,\n            i: 5,\n            o: 6,\n            r: 7,\n            l: 8,\n            s: 9,\n            c: 10,\n            f: 11,\n            u: 12,\n            d: 13,\n            h: 14,\n            p: 15,\n            b: 16,\n            v: 17,\n            w: 18,\n            y: 19,\n            g: 20,\n            m: 21,\n            k: 22,\n            x: 23,\n            j: 24,\n            z: 25,\n            q: 26,\n            A: 27,\n            B: 28,\n            C: 29,\n            D: 30,\n            E: 31,\n            F: 32,\n            G: 33,\n            H: 34,\n            I: 35,\n            J: 36,\n            K: 37,\n            L: 38,\n            M: 39,\n            N: 40,\n            O: 41,\n            P: 42,\n            Q: 43,\n            R: 44,\n            S: 45,\n            T: 46,\n            U: 47,\n            V: 48,\n            W: 49,\n            X: 50,\n            Y: 51,\n            Z: 52,\n            $: 53,\n            _: 54,\n            ee: 55,\n            te: 56,\n            ne: 57,\n            ae: 58,\n            ie: 59,\n            oe: 60,\n            re: 61,\n        };\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-1787.js",
    "content": "unary_prefix: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var x = -(2 / 3);\n            return x;\n        }());\n    }\n    expect_exact: \"console.log(-2/3);\"\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/issue-1833.js",
    "content": "iife_for: {\n    options = {\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                L: for (;;) break L;\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        !function() {\n            !function() {\n                L: for (;;) break L;\n            }();\n        }();\n    }\n}\n\niife_for_in: {\n    options = {\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                L: for (var a in x) break L;\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        !function() {\n            !function() {\n                L: for (var a in x) break L;\n            }();\n        }();\n    }\n}\n\niife_do: {\n    options = {\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                L: do {\n                    break L;\n                } while (1);\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        !function() {\n            !function() {\n                L: do {\n                    break L;\n                } while (1);\n            }();\n        }();\n    }\n}\n\niife_while: {\n    options = {\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                L: while (1) break L;\n            }\n            g();\n        }\n        f();\n    }\n    expect: {\n        !function() {\n            !function() {\n                L: while (1) break L;\n            }();\n        }();\n    }\n}\n\nlabel_do: {\n    options = {\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        L: do {\n            continue L;\n        } while (0);\n    }\n    expect: {\n        L: do {\n            continue L;\n        } while (0);\n    }\n}\n\nlabel_while: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        function f() {\n            L: while (0) continue L;\n        }\n    }\n    expect_exact: \"function f(){L:0}\"\n}\n"
  },
  {
    "path": "test/compress/issue-1943.js",
    "content": "operator: {\n    input: {\n        a. //comment\n        typeof\n    }\n    expect_exact: \"a.typeof;\"\n}\n\nname: {\n    input: {\n        a. //comment\n        b\n    }\n    expect_exact: \"a.b;\"\n}\n\nkeyword: {\n    input: {\n        a. //comment\n        default\n    }\n    expect_exact: \"a.default;\"\n}\n\natom: {\n    input: {\n        a. //comment\n        true\n    }\n    expect_exact: \"a.true;\"\n}\n"
  },
  {
    "path": "test/compress/issue-208.js",
    "content": "do_not_update_lhs: {\n    options = {\n        global_defs: {\n            DEBUG: 0,\n        },\n    }\n    input: {\n        DEBUG++;\n        DEBUG += 1;\n        DEBUG = 1;\n    }\n    expect: {\n        DEBUG++;\n        DEBUG += 1;\n        DEBUG = 1;\n    }\n}\n\ndo_update_rhs: {\n    options = {\n        global_defs: {\n            DEBUG: 0,\n        },\n    }\n    input: {\n        MY_DEBUG = DEBUG;\n        MY_DEBUG += DEBUG;\n    }\n    expect: {\n        MY_DEBUG = 0;\n        MY_DEBUG += 0;\n    }\n}\n\nmixed: {\n    options = {\n        evaluate: true,\n        global_defs: {\n            DEBUG: 0,\n            ENV: 1,\n            FOO: 2,\n        },\n    }\n    input: {\n        var ENV = 3;\n        var FOO = 4;\n        f(ENV * 10);\n        --FOO;\n        DEBUG = 1;\n        DEBUG++;\n        DEBUG += 1;\n        f(DEBUG);\n        x = DEBUG;\n    }\n    expect: {\n        var ENV = 3;\n        var FOO = 4;\n        f(10);\n        --FOO;\n        DEBUG = 1;\n        DEBUG++;\n        DEBUG += 1;\n        f(0);\n        x = 0;\n    }\n    expect_warnings: [\n        \"WARN: global_defs ENV redefined [test/compress/issue-208.js:1,12]\",\n        \"WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]\",\n        \"WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]\",\n        \"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]\",\n        \"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,8]\",\n        \"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:7,8]\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-22.js",
    "content": "return_with_no_value_in_if_body: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function foo(bar) {\n            if (bar) {\n                return;\n            } else {\n                return 1;\n            }\n        }\n    }\n    expect: {\n        function foo (bar) {\n            return bar ? void 0 : 1;\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-2652.js",
    "content": "insert_semicolon: {\n    beautify = {\n        beautify: true,\n        comments: \"all\",\n    }\n    input: {\n        var a\n        /* foo */ var b\n    }\n    expect_exact: [\n        \"var a\",\n        \"/* foo */;\",\n        \"\",\n        \"var b;\",\n    ]\n}\n\nunary_postfix: {\n    beautify = {\n        beautify: true,\n        comments: \"all\",\n    }\n    input: {\n        a\n        /* foo */++b\n    }\n    expect_exact: [\n        \"a\",\n        \"/* foo */;\",\n        \"\",\n        \"++b;\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-267.js",
    "content": "issue_267: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        x = a % b / b * c * 2;\n        x = a % b * 2\n    }\n    expect: {\n        x = a % b / b * c * 2;\n        x = a % b * 2;\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-269.js",
    "content": "issue_269_1: {\n    options = {\n        unsafe: true,\n    }\n    input: {\n        var x = {};\n        console.log(\n            String(x),\n            Number(x),\n            Boolean(x),\n\n            String(),\n            Number(),\n            Boolean()\n        );\n    }\n    expect: {\n        var x = {};\n        console.log(\n            \"\" + x, +(\"\" + x), !!x,\n            \"\", 0, false\n        );\n    }\n    expect_stdout: true\n}\n\nissue_269_dangers: {\n    options = {\n        unsafe: true,\n    }\n    input: {\n        var x = {};\n        console.log(\n            String(x, x),\n            Number(x, x),\n            Boolean(x, x)\n        );\n    }\n    expect: {\n        var x = {};\n        console.log(String(x, x), Number(x, x), Boolean(x, x));\n    }\n    expect_stdout: true\n}\n\nissue_269_in_scope: {\n    options = {\n        unsafe: true,\n    }\n    input: {\n        var String, Number, Boolean;\n        var x = {};\n        console.log(\n            String(x),\n            Number(x, x),\n            Boolean(x)\n        );\n    }\n    expect: {\n        var String, Number, Boolean;\n        var x = {};\n        console.log(String(x), Number(x, x), Boolean(x));\n    }\n    expect_stdout: true\n}\n\nstrings_concat: {\n    options = {\n        strings: true,\n        unsafe: true,\n    }\n    input: {\n        var x = {};\n        console.log(\n            String(x + \"str\"),\n            String(\"str\" + x)\n        );\n    }\n    expect: {\n        var x = {};\n        console.log(\n            x + \"str\",\n            \"str\" + x\n        );\n    }\n    expect_stdout: true\n}\n\nregexp: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        RegExp(\"foo\");\n        RegExp(\"bar\", \"ig\");\n        RegExp(foo);\n        RegExp(\"bar\", ig);\n        RegExp(\"should\", \"fail\");\n    }\n    expect: {\n        /foo/;\n        /bar/ig;\n        RegExp(foo);\n        RegExp(\"bar\", ig);\n        RegExp(\"should\", \"fail\");\n    }\n    expect_warnings: [\n        'WARN: Error converting RegExp(\"should\",\"fail\") [test/compress/issue-269.js:5,8]',\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-2719.js",
    "content": "warn: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return g();\n        }\n        function g() {\n            return g[\"call\" + \"er\"].arguments;\n        }\n        // 3\n        console.log(f(1, 2, 3).length);\n    }\n    expect: {\n        // TypeError: Cannot read property 'arguments' of null\n        console.log(function g() {\n            return g.caller.arguments;\n        }().length);\n    }\n    expect_warnings: [\n        \"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]\",\n        \"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-281.js",
    "content": "collapse_vars_constants: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f1(x) {\n            var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();\n            return b + (function() { return d - a * e - c; })();\n        }\n        function f2(x) {\n            var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();\n            return b + (function() { return -a * e - c; })();\n        }\n    }\n    expect: {\n        function f1(x) {\n            var b = x.prop, d = sideeffect1(), e = sideeffect2();\n            return b + (d - 4 * e - 5);\n        }\n        function f2(x) {\n            var b = x.prop;\n            sideeffect1();\n            return b + (-4 * sideeffect2() - 5);\n        }\n    }\n}\n\nmodified: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        function f5(b) {\n            var a = function() {\n                return b;\n            }();\n            return b++ + a;\n        }\n        console.log(f5(1));\n    }\n    expect: {\n        function f5(b) {\n            var a = b;\n            return b++ + a;\n        }\n        console.log(f5(1));\n    }\n    expect_stdout: \"2\"\n}\n\nref_scope: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 1, b = 2, c = 3;\n            var a = c++, b = b /= a;\n            return function() {\n                return a;\n            }() + b;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a = 1, b = 2, c = 3;\n            b = b /= a = c++;\n            return a + b;\n        }());\n    }\n    expect_stdout: true\n}\n\nsafe_undefined: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        inline: true,\n        unsafe: false,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var a, c;\n        console.log(function(undefined) {\n            return function() {\n                if (a)\n                    return b;\n                if (c)\n                    return d;\n            };\n        }(1)());\n    }\n    expect: {\n        var a, c;\n        console.log(a ? b : c ? d : void 0);\n    }\n    expect_stdout: true\n}\n\nnegate_iife_3: {\n    expression = true\n    options = {\n        conditionals: true,\n        expression: true,\n        inline: true,\n        negate_iife: true,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        t ? console.log(true) : console.log(false);\n    }\n}\n\nnegate_iife_3_off: {\n    expression = true\n    options = {\n        conditionals: true,\n        expression: true,\n        inline: true,\n        negate_iife: false,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        t ? console.log(true) : console.log(false);\n    }\n}\n\nnegate_iife_4: {\n    options = {\n        conditionals: true,\n        expression: true,\n        inline: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        t ? console.log(true) : console.log(false), void console.log(\"something\");\n    }\n}\n\nnegate_iife_5: {\n    options = {\n        conditionals: true,\n        expression: true,\n        inline: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        if ((function(){ return t })()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        t ? foo(true) : bar(false), void console.log(\"something\");\n    }\n}\n\nnegate_iife_5_off: {\n    options = {\n        conditionals: true,\n        expression: true,\n        inline: true,\n        negate_iife: false,\n        sequences: true,\n    }\n    input: {\n        if ((function(){ return t })()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        t ? foo(true) : bar(false), void console.log(\"something\");\n    }\n}\n\nissue_1254_negate_iife_true: {\n    expression = true\n    options = {\n        expression: true,\n        inline: true,\n        negate_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()();\n    }\n    expect_exact: 'void console.log(\"test\")'\n    expect_stdout: true\n}\n\nissue_1254_negate_iife_nested: {\n    expression = true\n    options = {\n        expression: true,\n        inline: true,\n        negate_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()()()()();\n    }\n    expect_exact: '(void console.log(\"test\"))()()()'\n}\n\nnegate_iife_issue_1073: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        new (function(a) {\n            return function Foo() {\n                this.x = a;\n                console.log(this);\n            };\n        }(7))();\n    }\n    expect: {\n        new function() {\n            this.x = 7,\n            console.log(this);\n        }();\n    }\n    expect_stdout: true\n}\n\nissue_1288_side_effects: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        negate_iife: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        if (w) ;\n        else {\n            (function f() {})();\n        }\n        if (!x) {\n            (function() {\n                x = {};\n            })();\n        }\n        if (y)\n            (function() {})();\n        else\n            (function(z) {\n                return z;\n            })(0);\n    }\n    expect: {\n        w;\n        x || (x = {});\n        y;\n    }\n}\n\ninner_var_for_in_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            var a = 1, b = 2;\n            for (b in (function() {\n                return x(a, b, c);\n            })()) {\n                var c = 3, d = 4;\n                x(a, b, c, d);\n            }\n            x(a, b, c, d);\n        }\n    }\n    expect: {\n        function f() {\n            var a = 1, b = 2;\n            for (b in x(1, b, c)) {\n                var c = 3, d = 4;\n                x(1, b, c, d);\n            }\n            x(1, b, c, d);\n        }\n    }\n}\n\nissue_1595_3: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return g(a + 1);\n        })(2);\n    }\n    expect: {\n        g(3);\n    }\n}\n\nissue_1758: {\n    options = {\n        inline: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(c) {\n            var undefined = 42;\n            return function() {\n                c--;\n                c--, c.toString();\n                return;\n            }();\n        }());\n    }\n    expect: {\n        console.log(function(c) {\n            var undefined = 42;\n            return c--, c--, void c.toString();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\nwrap_iife: {\n    options = {\n        inline: true,\n        negate_iife: false,\n    }\n    beautify = {\n        wrap_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()();\n    }\n    expect_exact: 'void console.log(\"test\");'\n}\n\nwrap_iife_in_expression: {\n    options = {\n        inline: true,\n        negate_iife: false,\n    }\n    beautify = {\n        wrap_iife: true,\n    }\n    input: {\n        foo = (function() {\n            return bar();\n        })();\n    }\n    expect_exact: 'foo=bar();'\n}\n\nwrap_iife_in_return_call: {\n    options = {\n        inline: true,\n        negate_iife: false,\n    }\n    beautify = {\n        wrap_iife: true,\n    }\n    input: {\n        (function() {\n            return (function() {\n                console.log('test')\n            })();\n        })()();\n    }\n    expect_exact: '(void console.log(\"test\"))();'\n}\n\npure_annotation_1: {\n    options = {\n        annotations: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        /*@__PURE__*/(function() {\n            console.log(\"hello\");\n        }());\n    }\n    expect_exact: \"\"\n}\n\npure_annotation_2: {\n    options = {\n        annotations: true,\n        collapse_vars: true,\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        /*@__PURE__*/(function(n) {\n            console.log(\"hello\", n);\n        }(42));\n    }\n    expect_exact: \"\"\n}\n\ndrop_fargs: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        keep_fargs: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        !function(a_1) {\n            a++;\n        }(a++ + (a && console.log(a)));\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        ++a && console.log(a),\n        a++;\n        console.log(a);\n    }\n    expect_stdout: [\n        \"2\",\n        \"3\",\n    ]\n}\n\nkeep_fargs: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        keep_fargs: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        !function(a_1) {\n            a++;\n        }(a++ + (a && console.log(a)));\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        ++a && console.log(a),\n        a++;\n        console.log(a);\n    }\n    expect_stdout: [\n        \"2\",\n        \"3\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-2871.js",
    "content": "comparison_with_undefined: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        a == undefined;\n        a != undefined;\n        a === undefined;\n        a !== undefined;\n\n        undefined == a;\n        undefined != a;\n        undefined === a;\n        undefined !== a;\n\n        void 0 == a;\n        void 0 != a;\n        void 0 === a;\n        void 0 !== a;\n    }\n    expect: {\n        null == a;\n        null != a;\n        void 0 === a;\n        void 0 !== a;\n\n        null == a;\n        null != a;\n        void 0 === a;\n        void 0 !== a;\n\n        null == a;\n        null != a;\n        void 0 === a;\n        void 0 !== a;\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-2989.js",
    "content": "inline_script_off: {\n    beautify = {\n        inline_script: false,\n    }\n    input: {\n        console.log(\"</sCrIpT>\");\n    }\n    expect_exact: 'console.log(\"</sCrIpT>\");'\n    expect_stdout: \"</sCrIpT>\"\n}\n\ninline_script_on: {\n    beautify = {\n        inline_script: true,\n    }\n    input: {\n        console.log(\"</sCrIpT>\");\n    }\n    expect_exact: 'console.log(\"<\\\\/sCrIpT>\");'\n    expect_stdout: \"</sCrIpT>\"\n}\n"
  },
  {
    "path": "test/compress/issue-368.js",
    "content": "collapse: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var a;\n            a = typeof b === 'function' ? b() : b;\n            return a !== undefined && c();\n        }\n        function f2(b) {\n            var a;\n            b = c();\n            a = typeof b === 'function' ? b() : b;\n            return 'string' == typeof a && d();\n        }\n        function f3(c) {\n            var a;\n            a = b(a / 2);\n            if (a < 0) {\n                a++;\n                ++c;\n                return c / 2;\n            }\n        }\n        function f4(c) {\n            var a;\n            a = b(a / 2);\n            if (a < 0) {\n                a++;\n                c++;\n                return c / 2;\n            }\n        }\n    }\n    expect: {\n        function f1() {\n            return void 0 !== ('function' === typeof b ? b() : b) && c();\n        }\n        function f2(b) {\n            return 'string' == typeof ('function' === typeof (b = c()) ? b() : b) && d();\n        }\n        function f3(c) {\n            var a;\n            if ((a = b(a / 2)) < 0) return a++, ++c / 2;\n        }\n        function f4(c) {\n            var a;\n            if ((a = b(a / 2)) < 0) return a++, ++c / 2;\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-3768.js",
    "content": "mangle: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var e = eval, x = 42;\n        (function() {\n            console.log(e(\"typeof x\"));\n        })();\n    }\n    expect: {\n        var e = eval, x = 42;\n        (function() {\n            console.log(e(\"typeof x\"));\n        })();\n    }\n    expect_stdout: true\n}\n\ncompress: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 42;\n            return eval(\"typeof a\");\n        }(), function(e) {\n            var a = null;\n            return e(\"typeof a\");\n        }(eval), function(eval) {\n            var a = false;\n            return eval(\"typeof a\");\n        }(eval), function(f) {\n            var a = \"STRING\";\n            var eval = f;\n            return eval(\"typeof a\");\n        }(eval), function(g) {\n            var a = eval;\n            function eval() {\n                return g;\n            }\n            return eval()(\"typeof a\");\n        }(eval));\n    }\n    expect: {\n        console.log(function() {\n            var a = 42;\n            return eval(\"typeof a\");\n        }(), (0, eval)(\"typeof a\"), function(eval) {\n            var a = false;\n            return eval(\"typeof a\");\n        }(eval), function(f) {\n            var a = \"STRING\";\n            var eval = f;\n            return eval(\"typeof a\");\n        }(eval), function(g) {\n            var a = eval;\n            function eval() {\n                return g;\n            }\n            return eval()(\"typeof a\");\n        }(eval));\n    }\n    expect_stdout: \"number undefined boolean string undefined\"\n}\n\ncall_arg_1: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        var z = \"foo\";\n        (function() {\n            var z = false;\n            (function(e) {\n                var z = 42;\n                e(\"console.log(typeof z)\");\n            })(eval);\n        })();\n    }\n    expect: {\n        var z = \"foo\";\n        (function() {\n            var o = false;\n            (function(o) {\n                var a = 42;\n                o(\"console.log(typeof z)\");\n            })(eval);\n        })();\n    }\n    expect_stdout: true\n}\n\ncall_arg_2: {\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        function eval() {\n            console.log(\"PASS\");\n        }\n        var z = \"foo\";\n        (function() {\n            var z = false;\n            (function(e) {\n                var z = 42;\n                e(\"console.log(typeof z)\");\n            })(eval);\n        })();\n    }\n    expect: {\n        function n() {\n            console.log(\"PASS\");\n        }\n        var o = \"foo\";\n        (function() {\n            var o = false;\n            (function(o) {\n                var n = 42;\n                o(\"console.log(typeof z)\");\n            })(n);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/issue-44.js",
    "content": "issue_44_valid_ast_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function a(b) {\n            for (var i = 0, e = b.qoo(); ; i++) {}\n        }\n    }\n    expect: {\n        function a(b) {\n            var i = 0;\n            for (b.qoo(); ; i++);\n        }\n    }\n}\n\nissue_44_valid_ast_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function a(b) {\n            if (foo) for (var i = 0, e = b.qoo(); ; i++) {}\n        }\n    }\n    expect: {\n        function a(b) {\n            if (foo) {\n                var i = 0;\n                for (b.qoo(); ; i++);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-5614.js",
    "content": "record_update: {\n    options = {\n        loops: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var value = { a: 42, b: \"PASS\" };\n        var unused = _Utils_update(value, { b: \"FAIL\" });\n        function _Utils_update(oldRecord, updatedFields) {\n            var newRecord = {};\n            for (var key in oldRecord)\n                newRecord[key] = oldRecord[key];\n            for (var key in updatedFields)\n                newRecord[key] = updatedFields[key];\n            return newRecord;\n        }\n    }\n    expect: {}\n}\n\ncurrying: {\n    options = {\n        inline: true,\n        passes: 3,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function F(arity, fun, wrapper) {\n            wrapper.a = arity;\n            wrapper.f = fun;\n            return wrapper;\n        }\n        function F2(fun) {\n            return F(2, fun, function(a) {\n                return function(b) {\n                    return fun(a, b);\n                };\n            });\n        }\n        function _Utils_eq(x, y) {\n            var pair, stack = [], isEqual = _Utils_eqHelp(x, y, 0, stack);\n            while (isEqual && (pair = stack.pop()))\n                isEqual = _Utils_eqHelp(pair.a, pair.b, 0, stack);\n            return isEqual;\n        }\n        var _Utils_equal = F2(_Utils_eq);\n    }\n    expect: {}\n}\n\nconditional_property_write: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var o = {};\n            if (a)\n                o.p = console.log(\"foo\");\n            else\n                o.q = console.log(\"bar\");\n            o.r = console.log(\"baz\");\n        }\n        f(42);\n        f(null);\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                console.log(\"foo\");\n            else\n                console.log(\"bar\");\n            console.log(\"baz\");\n        }\n        f(42);\n        f(null);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nreassign_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\", b = \"FAIL\";\n        (b = a).toString();\n        console.log(b);\n    }\n    expect: {\n        var b = \"FAIL\";\n        (b = \"PASS\").toString();\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nreassign_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        if (false) {\n            a = null + 0;\n            a();\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        if (false) {\n            a = 0;\n            a();\n        }\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nreassign_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        (a = a || \"PASS\").toString();\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (a = (0, \"PASS\")).toString();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nretain_instance_write: {\n    options = {\n        pure_getters: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            return a;\n        }\n        function g() {\n            var o = {};\n            var b = new f(o);\n            if (console)\n                b.p = \"PASS\";\n            return o;\n        }\n        console.log(g().p);\n    }\n    expect: {\n        function f(a) {\n            return a;\n        }\n        function g() {\n            var o = {};\n            var b = new f(o);\n            if (console)\n                b.p = \"PASS\";\n            return o;\n        }\n        console.log(g().p);\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/issue-59.js",
    "content": "keep_continue: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n    }\n    input: {\n        while (a) {\n            if (b) {\n                switch (true) {\n                  case c():\n                    d();\n                }\n                continue;\n            }\n            f();\n        }\n    }\n    expect: {\n        while (a) {\n            if (b) {\n                switch (true) {\n                  case c():\n                    d();\n                }\n                continue;\n            }\n            f();\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-597.js",
    "content": "NaN_and_Infinity_must_have_parens: {\n    options = {}\n    input: {\n        Infinity.toString();\n        NaN.toString();\n    }\n    expect: {\n        (1/0).toString();\n        NaN.toString();\n    }\n}\n\nNaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {\n    options = {}\n    input: {\n        var Infinity, NaN;\n        Infinity.toString();\n        NaN.toString();\n    }\n    expect: {\n        var Infinity, NaN;\n        Infinity.toString();\n        NaN.toString();\n    }\n}\n\nNaN_and_Infinity_must_have_parens_evaluate: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        (123456789 / 0).toString();\n        (+\"foo\").toString();\n    }\n    expect: {\n        (1/0).toString();\n        NaN.toString();\n    }\n}\n\nNaN_and_Infinity_should_not_be_replaced_when_they_are_redefined_evaluate: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        var Infinity, NaN;\n        (123456789 / 0).toString();\n        (+\"foo\").toString();\n    }\n    expect: {\n        var Infinity, NaN;\n        (1/0).toString();\n        (0/0).toString();\n    }\n}\n\nbeautify_off_1: {\n    options = {\n        evaluate: true,\n    }\n    beautify = {\n        beautify: false,\n    }\n    input: {\n        var NaN;\n        console.log(\n            null,\n            undefined,\n            Infinity,\n            NaN,\n            Infinity * undefined,\n            Infinity.toString(),\n            NaN.toString(),\n            (Infinity * undefined).toString()\n        );\n    }\n    expect_exact: \"var NaN;console.log(null,void 0,1/0,NaN,0/0,(1/0).toString(),NaN.toString(),(0/0).toString());\"\n    expect_stdout: true\n}\n\nbeautify_off_2: {\n    options = {\n        evaluate: true,\n    }\n    beautify = {\n        beautify: false,\n    }\n    input: {\n        console.log(\n            null.toString(),\n            undefined.toString()\n        );\n    }\n    expect_exact: \"console.log(null.toString(),(void 0).toString());\"\n}\n\nbeautify_on_1: {\n    options = {\n        evaluate: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        var NaN;\n        console.log(\n            null,\n            undefined,\n            Infinity,\n            NaN,\n            Infinity * undefined,\n            Infinity.toString(),\n            NaN.toString(),\n            (Infinity * undefined).toString()\n        );\n    }\n    expect_exact: [\n        \"var NaN;\",\n        \"\",\n        \"console.log(null, void 0, 1 / 0, NaN, 0 / 0, (1 / 0).toString(), NaN.toString(), (0 / 0).toString());\",\n    ]\n    expect_stdout: true\n}\n\nbeautify_on_2: {\n    options = {\n        evaluate: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        console.log(\n            null.toString(),\n            undefined.toString()\n        );\n    }\n    expect_exact: \"console.log(null.toString(), (void 0).toString());\"\n}\n\nissue_1724: {\n    input: {\n        var a = 0;\n        ++a % Infinity | Infinity ? a++ : 0;\n        console.log(a);\n    }\n    expect_exact: \"var a=0;++a%(1/0)|1/0?a++:0;console.log(a);\"\n    expect_stdout: \"2\"\n}\n\nissue_1725: {\n    input: {\n        ([].length === 0) % Infinity ? console.log(\"PASS\") : console.log(\"FAIL\");\n    }\n    expect_exact: '(0===[].length)%(1/0)?console.log(\"PASS\"):console.log(\"FAIL\");'\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/issue-611.js",
    "content": "issue_611: {\n  options = {\n        sequences: true,\n        side_effects: true,\n    }\n  input: {\n    define(function() {\n      function fn() {}\n      if (fn()) {\n        fn();\n        return void 0;\n      }\n    });\n  }\n  expect: {\n    define(function() {\n      function fn(){}\n      if (fn()) return void fn();\n    });\n  }\n}\n"
  },
  {
    "path": "test/compress/issue-637.js",
    "content": "wrongly_optimized: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        function func() {\n            foo();\n        }\n        if (func() || true) {\n            bar();\n        }\n    }\n    expect: {\n        function func() {\n            foo();\n        }\n        func(), 1, bar();\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-640.js",
    "content": "cond_5: {\n    options = {\n        conditionals: true,\n        expression: true,\n    }\n    input: {\n        if (some_condition()) {\n            if (some_other_condition()) {\n                do_something();\n            } else {\n                alternate();\n            }\n        } else {\n            alternate();\n        }\n\n        if (some_condition()) {\n            if (some_other_condition()) {\n                do_something();\n            }\n        }\n    }\n    expect: {\n        (some_condition() && some_other_condition() ? do_something : alternate)();\n        if (some_condition() && some_other_condition()) do_something();\n    }\n}\n\ndead_code_const_annotation_regex: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        expression: true,\n        loops: true,\n    }\n    input: {\n        var unused;\n        // @constraint this shouldn't be a constant\n        var CONST_FOO_ANN = false;\n        if (CONST_FOO_ANN) {\n            console.log(\"reachable\");\n        }\n    }\n    expect: {\n        var unused;\n        var CONST_FOO_ANN = !1;\n        if (CONST_FOO_ANN) console.log('reachable');\n    }\n    expect_stdout: true\n}\n\ndrop_console_2: {\n    options = {\n        drop_console: true,\n        expression: true,\n    }\n    input: {\n        console.log('foo');\n        console.log.apply(console, arguments);\n    }\n    expect: {\n        // with regular compression these will be stripped out as well\n        void 0;\n        void 0;\n    }\n}\n\ndrop_value: {\n    expression = true\n    options = {\n        expression: true,\n        side_effects: true,\n    }\n    input: {\n        (1, [2, foo()], 3, {a:1, b:bar()});\n    }\n    expect: {\n        foo(), {a:1, b:bar()};\n    }\n}\n\nwrongly_optimized: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        expression: true,\n    }\n    input: {\n        function func() {\n            foo();\n        }\n        if (func() || true) {\n            bar();\n        }\n    }\n    expect: {\n        function func() {\n            foo();\n        }\n        func(), 1;\n        bar();\n    }\n}\n\nnegate_iife_1: {\n    expression = true\n    options = {\n        expression: true,\n        negate_iife: true,\n    }\n    input: {\n        (function(){ stuff() })();\n    }\n    expect: {\n        (function(){ stuff() })();\n    }\n}\n\nnegate_iife_3: {\n    expression = true\n    options = {\n        conditionals: true,\n        expression: true,\n        negate_iife: true,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n}\n\nnegate_iife_3_off: {\n    expression = true\n    options = {\n        conditionals: true,\n        expression: true,\n        negate_iife: false,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n}\n\nnegate_iife_4: {\n    options = {\n        conditionals: true,\n        expression: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function(){ return t }() ? console.log(false) : console.log(true), function(){\n            console.log(\"something\");\n        }();\n    }\n}\n\nnegate_iife_5: {\n    options = {\n        conditionals: true,\n        expression: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        if ((function(){ return t })()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function(){ return t }() ? bar(false) : foo(true), function(){\n            console.log(\"something\");\n        }();\n    }\n}\n\nnegate_iife_5_off: {\n    options = {\n        conditionals: true,\n        expression: true,\n        negate_iife: false,\n        sequences: true,\n    }\n    input: {\n        if ((function(){ return t })()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function(){ return t }() ? bar(false) : foo(true), function(){\n            console.log(\"something\");\n        }();\n    }\n}\n\nissue_1254_negate_iife_true: {\n    expression = true\n    options = {\n        expression: true,\n        negate_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()();\n    }\n    expect_exact: 'function(){return function(){console.log(\"test\")}}()()'\n    expect_stdout: true\n}\n\nissue_1254_negate_iife_nested: {\n    expression = true\n    options = {\n        expression: true,\n        negate_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()()()()();\n    }\n    expect_exact: 'function(){return function(){console.log(\"test\")}}()()()()()'\n    expect_stdout: true\n}\n\nconditional: {\n    options = {\n        expression: true,\n        pure_funcs: [\n            \"pure\"\n        ],\n        side_effects: true,\n    }\n    input: {\n        pure(1 | a() ? 2 & b() : 7 ^ c());\n        pure(1 | a() ? 2 & b() : 5);\n        pure(1 | a() ? 4 : 7 ^ c());\n        pure(1 | a() ? 4 : 5);\n        pure(3 ? 2 & b() : 7 ^ c());\n        pure(3 ? 2 & b() : 5);\n        pure(3 ? 4 : 7 ^ c());\n        pure(3 ? 4 : 5);\n    }\n    expect: {\n        1 | a() ? b() : c();\n        1 | a() && b();\n        1 | a() || c();\n        a();\n        3 ? b() : c();\n        3 && b();\n        3 || c();\n        pure(3 ? 4 : 5);\n    }\n}\n\nlimit_1: {\n    options = {\n        expression: true,\n        sequences: 3,\n    }\n    input: {\n        a;\n        b;\n        c;\n        d;\n        e;\n        f;\n        g;\n        h;\n        i;\n        j;\n        k;\n    }\n    expect: {\n        // Turned into a single return statement\n        // so it can no longer be split into lines\n        a,b,c,d,e,f,g,h,i,j,k;\n    }\n}\n\niife: {\n    options = {\n        expression: true,\n        sequences: true,\n    }\n    input: {\n        x = 42;\n        (function a() {})();\n        !function b() {}();\n        ~function c() {}();\n        +function d() {}();\n        -function e() {}();\n        void function f() {}();\n        typeof function g() {}();\n    }\n    expect: {\n        x = 42,\n        function a() {}(),\n        !function b() {}(),\n        ~function c() {}(),\n        +function d() {}(),\n        -function e() {}(),\n        void function f() {}(),\n        typeof function g() {}();\n    }\n}\n\niife_drop_side_effect_free: {\n    options = {\n        expression: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        x = 42;\n        (function a() {})();\n        !function b() {}();\n        ~function c() {}();\n        +function d() {}();\n        -function e() {}();\n        void function f() {}();\n        typeof function g() {}();\n    }\n    expect: {\n        x = 42,\n        typeof void 0;\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-747.js",
    "content": "dont_reuse_prop: {\n    mangle = {\n        properties: {\n            domprops: true,\n            regex: /asd/,\n        },\n    }\n    input: {\n        \"aaaaaaaaaabbbbb\";\n        var obj = {};\n        obj.a = 123;\n        obj.asd = 256;\n        console.log(obj.a);\n    }\n    expect: {\n        \"aaaaaaaaaabbbbb\";\n        var obj = {};\n        obj.a = 123;\n        obj.b = 256;\n        console.log(obj.a);\n    }\n    expect_stdout: \"123\"\n    expect_warnings: [\n        \"INFO: Preserving excluded property a\",\n        \"INFO: Mapping property asd to b\",\n        \"INFO: Preserving reserved property log\",\n    ]\n}\n\nunmangleable_props_should_always_be_reserved: {\n    mangle = {\n        properties: {\n            domprops: true,\n            regex: /asd/,\n        },\n    }\n    input: {\n        \"aaaaaaaaaabbbbb\";\n        var obj = {};\n        obj.asd = 256;\n        obj.a = 123;\n        console.log(obj.a);\n    }\n    expect: {\n        \"aaaaaaaaaabbbbb\";\n        var obj = {};\n        obj.b = 256;\n        obj.a = 123;\n        console.log(obj.a);\n    }\n    expect_stdout: \"123\"\n    expect_warnings: [\n        \"INFO: Preserving excluded property a\",\n        \"INFO: Mapping property asd to b\",\n        \"INFO: Preserving reserved property log\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-751.js",
    "content": "negate_booleans_1: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        var a = !a || !b || !c || !d || !e || !f;\n    }\n    expect: {\n        var a = !(a && b && c && d && e && f);\n    }\n}\n\nnegate_booleans_2: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        var match = !x &&       // should not touch this one\n            (!z || c) &&\n            (!k || d) &&\n            the_stuff();\n    }\n    expect: {\n        var match = !x &&\n            (!z || c) &&\n            (!k || d) &&\n            the_stuff();\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-782.js",
    "content": "remove_sequence: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (0, 1, eval)();\n        (0, 1, logThis)();\n        (0, 1, _decorators.logThis)();\n    }\n    expect: {\n        (0, eval)();\n        logThis();\n        (0, _decorators.logThis)();\n    }\n}\n\nremove_redundant_sequence_items: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (0, 1, eval)();\n        (0, 1, logThis)();\n        (0, 1, _decorators.logThis)();\n    }\n    expect: {\n        \"use strict\";\n        (0, eval)();\n        logThis();\n        (0, _decorators.logThis)();\n    }\n}\n\ndont_remove_this_binding_sequence: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (0, eval)();\n        (0, logThis)();\n        (0, _decorators.logThis)();\n    }\n    expect: {\n        \"use strict\";\n        (0, eval)();\n        logThis();\n        (0, _decorators.logThis)();\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-892.js",
    "content": "dont_mangle_arguments: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        drop_debugger: true,\n        evaluate: true,\n        hoist_funs: true,\n        hoist_vars: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        keep_fnames: false,\n        loops: true,\n        negate_iife: false,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        (function(){\n            var arguments = arguments, not_arguments = 9;\n            console.log(not_arguments, arguments);\n        })(5, 6, 7);\n    }\n    expect_exact: \"(function(){var arguments,o=9;console.log(o,arguments)})(5,6,7);\"\n    expect_stdout: true\n}\n"
  },
  {
    "path": "test/compress/issue-913.js",
    "content": "keep_var_for_in: {\n    options = {\n        hoist_vars: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(obj) {\n            var foo = 5;\n            for (var i in obj)\n                return foo;\n        })();\n    }\n    expect: {\n        (function(obj) {\n            var i, foo = 5;\n            for (i in obj)\n                return foo;\n        })();\n    }\n}\n"
  },
  {
    "path": "test/compress/issue-973.js",
    "content": "this_binding_conditionals: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        (1 && a)();\n        (0 || a)();\n        (0 || 1 && a)();\n        (1 ? a : 0)();\n\n        (1 && a.b)();\n        (0 || a.b)();\n        (0 || 1 && a.b)();\n        (1 ? a.b : 0)();\n\n        (1 && a[b])();\n        (0 || a[b])();\n        (0 || 1 && a[b])();\n        (1 ? a[b] : 0)();\n\n        (1 && eval)();\n        (0 || eval)();\n        (0 || 1 && eval)();\n        (1 ? eval : 0)();\n    }\n    expect: {\n        \"use strict\";\n        a();\n        a();\n        a();\n        a();\n\n        (0, a.b)();\n        (0, a.b)();\n        (0, a.b)();\n        (0, a.b)();\n\n        (0, a[b])();\n        (0, a[b])();\n        (0, a[b])();\n        (0, a[b])();\n\n        (0, eval)();\n        (0, eval)();\n        (0, eval)();\n        (0, eval)();\n    }\n}\n\nthis_binding_collapse_vars: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            \"use strict\";\n            var c = a; c();\n            var d = a.b; d();\n            var e = eval; e();\n        }\n    }\n    expect: {\n        function f() {\n            \"use strict\";\n            a();\n            (0, a.b)();\n            (0, eval)();\n        }\n    }\n}\n\nthis_binding_side_effects: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (function(foo) {\n            (0, foo)();\n            (0, foo.bar)();\n            (0, eval)(\"console.log(foo);\");\n        }());\n        (function(foo) {\n            \"use strict\";\n            (0, foo)();\n            (0, foo.bar)();\n            (0, eval)(\"console.log(foo);\");\n        }());\n        (function(foo) {\n            var eval = console;\n            (0, foo)();\n            (0, foo.bar)();\n            (0, eval)(\"console.log(foo);\");\n        }());\n    }\n    expect: {\n        (function(foo) {\n            foo();\n            (0, foo.bar)();\n            (0, eval)(\"console.log(foo);\");\n        }());\n        (function(foo) {\n            \"use strict\";\n            foo();\n            (0, foo.bar)();\n            (0, eval)(\"console.log(foo);\");\n        }());\n        (function(foo) {\n            var eval = console;\n            foo();\n            (0, foo.bar)();\n            eval(\"console.log(foo);\");\n        }());\n    }\n}\n\nthis_binding_sequences: {\n    options = {\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(typeof function() {\n            return eval(\"this\");\n        }());\n        console.log(typeof function() {\n            \"use strict\";\n            return eval(\"this\");\n        }());\n        console.log(typeof function() {\n            return (0, eval)(\"this\");\n        }());\n        console.log(typeof function() {\n            \"use strict\";\n            return (0, eval)(\"this\");\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            return eval(\"this\");\n        }()),\n        console.log(typeof function() {\n            \"use strict\";\n            return eval(\"this\");\n        }()),\n        console.log(typeof function() {\n            return (0, eval)(\"this\");\n        }()),\n        console.log(typeof function() {\n            \"use strict\";\n            return (0, eval)(\"this\");\n        }());\n    }\n    expect_stdout: [\n        \"object\",\n        \"undefined\",\n        \"object\",\n        \"object\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-976.js",
    "content": "eval_collapse_vars: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var e = 7;\n            var s = \"abcdef\";\n            var i = 2;\n            var eval = console.log.bind(console);\n            var x = s.charAt(i++);\n            var y = s.charAt(i++);\n            var z = s.charAt(i++);\n            eval(x, y, z, e);\n        }\n        function p1() { var a = foo(), b = bar(), eval = baz(); return a + b + eval; }\n        function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }\n        (function f2(eval) {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })(eval);\n    }\n    expect: {\n        function f1() {\n            var e = 7,\n                s = \"abcdef\",\n                i = 2,\n                eval = console.log.bind(console),\n                x = s.charAt(i++),\n                y = s.charAt(i++),\n                z = s.charAt(i++);\n            eval(x, y, z, e);\n        }\n        function p1() { return foo() + bar() + baz(); }\n        function p2() { var a = foo(), b = bar(), eval = baz; return a + b + eval(); }\n        (function f2(eval) {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })(eval);\n    }\n    expect_stdout: true\n}\n\neval_unused: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        function o(k) {\n            return { c: 14 }[k];\n        }\n        console.log(function f1(a, eval, c, d, e) {\n            return a(\"c\") + eval;\n        }(o, 28, true));\n        console.log(function f2(a, b, c, d, e) {\n            return a + eval(\"c\");\n        }(14, true, 28));\n        console.log(function f3(a, eval, c, d, e) {\n            return a + eval(\"c\");\n        }(28, o, true));\n    }\n    expect: {\n        function o(k) {\n            return { c: 14 }[k];\n        }\n        console.log(function(a, eval) {\n            return a(\"c\") + eval;\n        }(o, 28));\n        console.log(function f2(a, b, c, d, e) {\n            return a + eval(\"c\");\n        }(14, true, 28));\n        console.log(function f3(a, eval, c, d, e) {\n            return a + eval(\"c\");\n        }(28, o, true));\n    }\n    expect_stdout: [\n        \"42\",\n        \"42\",\n        \"42\",\n    ]\n}\n\neval_mangle: {\n    mangle = {}\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        function o(k) {\n            return { cc: 14 }[k + \"c\"];\n        }\n        console.log(function f1(a, eval, c, d, e) {\n            return a(\"c\") + eval;\n        }(o, 28, true));\n        console.log(function f2(a, b, c, d, e) {\n            return a + eval(\"c\");\n        }(14, true, 28));\n        console.log(function f3(a, eval, c, d, e) {\n            return a + eval(\"c\");\n        }(28, o, true));\n    }\n    expect_exact: [\n        \"function o(o) {\",\n        \"    return {\",\n        \"        cc: 14\",\n        '    }[o + \"c\"];',\n        \"}\",\n        \"\",\n        \"console.log(function o(c, e, n, r, t) {\",\n        '    return c(\"c\") + e;',\n        \"}(o, 28, true));\",\n        \"\",\n        \"console.log(function f2(a, b, c, d, e) {\",\n        '    return a + eval(\"c\");',\n        \"}(14, true, 28));\",\n        \"\",\n        \"console.log(function f3(a, eval, c, d, e) {\",\n        '    return a + eval(\"c\");',\n        \"}(28, o, true));\",\n    ]\n    expect_stdout: [\n        \"42\",\n        \"42\",\n        \"42\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/issue-979.js",
    "content": "reported: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            if (a == 1 || b == 2)\n                foo();\n        }\n        function f2() {\n            if (!(a == 1 || b == 2));\n            else\n                foo();\n        }\n    }\n    expect: {\n        function f1() {\n            1 != a && 2 != b || foo();\n        }\n        function f2() {\n            1 != a && 2 != b || foo();\n        }\n    }\n}\n\ntest_negated_is_best: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        properties: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f3() {\n            if (a == 1 | b == 2)\n                foo();\n        }\n        function f4() {\n            if (!(a == 1 | b == 2));\n            else\n                foo();\n        }\n        function f5() {\n            if (a == 1 && b == 2)\n                foo();\n        }\n        function f6() {\n            if (!(a == 1 && b == 2));\n            else\n                foo();\n        }\n        function f7() {\n            if (a == 1 || b == 2)\n                foo();\n            else\n                return bar();\n        }\n    }\n    expect: {\n        function f3() {\n            1 == a | 2 == b && foo();\n        }\n        function f4() {\n            1 == a | 2 == b && foo();\n        }\n        function f5() {\n            1 == a && 2 == b && foo();\n        }\n        function f6() {\n            1 == a && 2 == b && foo();\n        }\n        function f7() {\n            if (1 != a && 2 != b)\n                return bar();\n            foo();\n        }\n    }\n}\n\n"
  },
  {
    "path": "test/compress/join_vars.js",
    "content": "join_vars_assign: {\n    options = {\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        var y, x;\n        x = Object(\"PAS\");\n        y = Object(\"S\");\n        console.log(x + y);\n    }\n    expect: {\n        var x = Object(\"PAS\"), y = Object(\"S\");\n        console.log(x + y);\n    }\n    expect_stdout: \"PASS\"\n}\n\njoin_array_assignments_1: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        console.log(function () {\n            var a = [ \"foo\", , \"bar\" ];\n            a[1] = \"baz\";\n            a[7] = \"moo\";\n            a[0] = \"moz\";\n            return a;\n        }().join());\n    }\n    expect: {\n        console.log(function () {\n            var a = [ \"moz\", \"baz\", \"bar\", , , , , \"moo\" ];\n            return a;\n        }().join());\n    }\n    expect_stdout: \"moz,baz,bar,,,,,moo\"\n}\n\njoin_array_assignments_2: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        console.log(function () {\n            var a = [ \"foo\" ];\n            a[1] = \"bar\";\n            a[7] = \"baz\";\n            a[2] = \"moo\";\n            return a;\n        }().join());\n    }\n    expect: {\n        console.log(function () {\n            var a = [ \"foo\", \"bar\" ];\n            a[7] = \"baz\";\n            a[2] = \"moo\";\n            return a;\n        }().join());\n    }\n    expect_stdout: \"foo,bar,moo,,,,,baz\"\n}\n\njoin_array_assignments_3: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        console.log(function () {\n            var a = [ \"foo\" ];\n            a[1] = \"bar\";\n            a.b = \"baz\";\n            a[2] = \"moo\";\n            return a;\n        }().join());\n    }\n    expect: {\n        console.log(function () {\n            var a = [ \"foo\", \"bar\" ];\n            a.b = \"baz\";\n            a[2] = \"moo\";\n            return a;\n        }().join());\n    }\n    expect_stdout: true\n}\n\njoin_array_assignments_4: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function () {\n            var a = [ \"foo\" ];\n            a[0] = \"bar\";\n            a[1] = a;\n            a[2] = \"baz\";\n            return a;\n        }().join());\n    }\n    expect: {\n        console.log(function () {\n            var a = [ \"bar\" ];\n            a[1] = a;\n            a[2] = \"baz\";\n            return a;\n        }().join());\n    }\n    expect_stdout: true\n}\n\njoin_object_assignments_1: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var x = {\n                a: 1,\n                c: (console.log(\"c\"), \"C\"),\n            };\n            x.b = 2;\n            x[3] = function() {\n                console.log(x);\n            },\n            x[\"a\"] = /foo/,\n            x.bar = x;\n            return x;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var x = {\n                a: 1,\n                c: (console.log(\"c\"), \"C\"),\n                b: 2,\n                3: function() {\n                    console.log(x);\n                },\n                a: /foo/,\n            };\n            x.bar = x;\n            return x;\n        }());\n    }\n    expect_stdout: true\n}\n\njoin_object_assignments_2: {\n    options = {\n        evaluate: true,\n        hoist_props: true,\n        join_vars: true,\n        passes: 3,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            foo: 1,\n        };\n        o.bar = 2;\n        o.baz = 3;\n        console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);\n    }\n    expect: {\n        console.log(1, 4, 6);\n    }\n    expect_stdout: \"1 4 6\"\n}\n\njoin_object_assignments_3: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {\n                a: \"PASS\",\n            }, a = o.a;\n            o.a = \"FAIL\";\n            return a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var o = {\n                a: \"PASS\",\n            }, a = o.a;\n            o.a = \"FAIL\";\n            return a;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\njoin_object_assignments_4: {\n    options = {\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        var o;\n        console.log(o);\n        o = {};\n        o.a = \"foo\";\n        console.log(o.b);\n        o.b = \"bar\";\n        console.log(o.a);\n    }\n    expect: {\n        var o;\n        console.log(o),\n        o = {\n            a: \"foo\",\n        },\n        console.log(o.b),\n        o.b = \"bar\",\n        console.log(o.a);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"foo\",\n    ]\n}\n\njoin_object_assignments_return_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {\n                p: 3\n            };\n            return o.q = \"foo\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var o = {\n                p: 3,\n                q: \"foo\"\n            };\n            return o.q;\n        }());\n    }\n    expect_stdout: \"foo\"\n}\n\njoin_object_assignments_return_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {\n                p: 3\n            };\n            return o.q = /foo/,\n            o.r = \"bar\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var o = {\n                p: 3,\n                q: /foo/,\n                r: \"bar\"\n            };\n            return o.r;\n        }());\n    }\n    expect_stdout: \"bar\"\n}\n\njoin_object_assignments_return_3: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {\n                p: 3\n            };\n            return o.q = \"foo\",\n            o.p += \"\",\n            console.log(o.q),\n            o.p;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var o = {\n                p: 3,\n                q: \"foo\"\n            };\n            return o.p += \"\",\n            console.log(o.q),\n            o.p;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"3\",\n    ]\n}\n\njoin_object_assignments_for: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {\n                p: 3\n            };\n            for (o.q = \"foo\"; console.log(o.q););\n            return o.p;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            for (var o = {\n                p: 3,\n                q: \"foo\"\n            }; console.log(o.q););\n            return o.p;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"3\",\n    ]\n}\n\njoin_object_assignments_if: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {};\n            if (o.a = \"PASS\") return o.a;\n        }())\n    }\n    expect: {\n        console.log(function() {\n            var o = { a: \"PASS\" };\n            if (o.a) return o.a;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\njoin_object_assignments_forin: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        console.log(function() {\n            var o = {};\n            for (var a in o.a = \"PASS\", o)\n                return o[a];\n        }())\n    }\n    expect: {\n        console.log(function() {\n            var o = { a: \"PASS\" }, a;\n            for (a in o)\n                return o[a];\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\njoin_object_assignments_negative: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        properties: true,\n    }\n    input: {\n        var o = {};\n        o[0] = 0;\n        o[-0] = 1;\n        o[-1] = 2;\n        console.log(o[0], o[-0], o[-1]);\n    }\n    expect: {\n        var o = {\n            0: 0,\n            0: 1,\n            \"-1\": 2\n        };\n        console.log(o[0], o[-0], o[-1]);\n    }\n    expect_stdout: \"1 1 2\"\n}\n\njoin_object_assignments_NaN_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var o = {};\n        o[NaN] = 1;\n        o[0/0] = 2;\n        console.log(o[NaN], o[NaN]);\n    }\n    expect: {\n        var o = {};\n        o[NaN] = 1;\n        o[0/0] = 2;\n        console.log(o[NaN], o[NaN]);\n    }\n    expect_stdout: \"2 2\"\n}\n\njoin_object_assignments_NaN_2: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        properties: true,\n    }\n    input: {\n        var o = {};\n        o[NaN] = 1;\n        o[0/0] = 2;\n        console.log(o[NaN], o[NaN]);\n    }\n    expect: {\n        var o = {\n            NaN: 1,\n            NaN: 2\n        };\n        console.log(o.NaN, o.NaN);\n    }\n    expect_stdout: \"2 2\"\n}\n\njoin_object_assignments_null_0: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var o = {};\n        o[null] = 1;\n        console.log(o[null]);\n    }\n    expect: {\n        var o = {};\n        o[null] = 1;\n        console.log(o[null]);\n    }\n    expect_stdout: \"1\"\n}\n\njoin_object_assignments_null_1: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        properties: true,\n    }\n    input: {\n        var o = {};\n        o[null] = 1;\n        console.log(o[null]);\n    }\n    expect: {\n        var o = {\n            null: 1\n        };\n        console.log(o.null);\n    }\n    expect_stdout: \"1\"\n}\n\njoin_object_assignments_void_0: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        var o = {};\n        o[void 0] = 1;\n        console.log(o[void 0]);\n    }\n    expect: {\n        var o = {\n            undefined: 1\n        };\n        console.log(o[void 0]);\n    }\n    expect_stdout: \"1\"\n}\n\njoin_object_assignments_undefined_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var o = {};\n        o[undefined] = 1;\n        console.log(o[undefined]);\n    }\n    expect: {\n        var o = {};\n        o[void 0] = 1;\n        console.log(o[void 0]);\n    }\n    expect_stdout: \"1\"\n}\n\njoin_object_assignments_undefined_2: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        properties: true,\n    }\n    input: {\n        var o = {};\n        o[undefined] = 1;\n        console.log(o[undefined]);\n    }\n    expect: {\n        var o = {\n            undefined : 1\n        };\n        console.log(o[void 0]);\n    }\n    expect_stdout: \"1\"\n}\n\njoin_object_assignments_Infinity: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        properties: true,\n    }\n    input: {\n        var o = {};\n        o[Infinity] = 1;\n        o[1/0] = 2;\n        o[-Infinity] = 3;\n        o[-1/0] = 4;\n        console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);\n    }\n    expect: {\n        var o = {\n            Infinity: 1,\n            Infinity: 2,\n            \"-Infinity\": 3,\n            \"-Infinity\": 4\n        };\n        console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);\n    }\n    expect_stdout: \"2 2 4 4\"\n}\n\njoin_object_assignments_regex: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        properties: true,\n    }\n    input: {\n        var o = {};\n        o[/rx/] = 1;\n        console.log(o[/rx/]);\n    }\n    expect: {\n        var o = {\n            \"/rx/\": 1\n        };\n        console.log(o[/rx/]);\n    }\n    expect_stdout: \"1\"\n}\n\nchained_assignments: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a, b = a = {};\n        b.p = \"PASS\";\n        console.log(a.p);\n    }\n    expect: {\n        var a, b = a = {\n            p: \"PASS\",\n        };\n        console.log(a.p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nfolded_assignments_1: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        var a = {};\n        a[a.PASS = 42] = \"PASS\";\n        console.log(a[42], a.PASS);\n    }\n    expect: {\n        var a = {\n            PASS: 42,\n            42: \"PASS\",\n        };\n        console.log(a[42], a.PASS);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nfolded_assignments_2: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = {};\n        a[42] = \"FAIL\";\n        a[a.PASS = 42] = \"PASS\";\n        console.log(a[42], a.PASS);\n    }\n    expect: {\n        \"use strict\";\n        var a = {\n            42: \"FAIL\",\n            PASS: 42,\n        };\n        a[42] = \"PASS\";\n        console.log(a[42], a.PASS);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\ninlined_assignments: {\n    options = {\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (a = {}).p = \"PASS\";\n        console.log(a.p);\n    }\n    expect: {\n        var a = {\n            p: \"PASS\",\n        };\n        console.log(a.p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nsingle_use_for: {\n    options = {\n        inline: true,\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function() {\n            for (; console.log(\"PASS\"););\n        };\n        a();\n    }\n    expect: {\n        (function() {\n            for (; console.log(\"PASS\"););\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nsingle_use_for_inline: {\n    options = {\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function() {\n            for (; console.log(\"PASS\"););\n        };\n        a();\n    }\n    expect: {\n        for (; console.log(\"PASS\"););\n    }\n    expect_stdout: \"PASS\"\n}\n\nsingle_use_var: {\n    options = {\n        inline: true,\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a = function() {\n            var b = A;\n            for (b in console.log(b));\n        };\n        a();\n    }\n    expect: {\n        A = \"PASS\";\n        (function() {\n            var b = A;\n            for (b in console.log(b));\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nsingle_use_var_inline: {\n    options = {\n        inline: true,\n        join_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a = function() {\n            var b = A;\n            for (b in console.log(b));\n        };\n        a();\n    }\n    expect: {\n        A = \"PASS\";\n        var b = A;\n        for (b in console.log(b));\n    }\n    expect_stdout: \"PASS\"\n}\n\ntypescript_enum: {\n    rename = true\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        join_vars: true,\n        passes: 4,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var Enum;\n        (function (Enum) {\n            Enum[Enum.PASS = 42] = \"PASS\";\n        })(Enum || (Enum = {}));\n        console.log(Enum[42], Enum.PASS);\n    }\n    expect: {\n        console.log(\"PASS\", 42);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nissue_2816: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var o = {\n            a: 1\n        };\n        o.b = 2;\n        o.a = 3;\n        o.c = 4;\n        console.log(o.a, o.b, o.c);\n    }\n    expect: {\n        \"use strict\";\n        var o = {\n            a: 1,\n            b: 2\n        };\n        o.a = 3;\n        o.c = 4;\n        console.log(o.a, o.b, o.c);\n    }\n    expect_stdout: \"3 2 4\"\n}\n\nissue_2893_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var o = {\n            get a() {\n                return \"PASS\";\n            },\n        };\n        o.a = \"FAIL\";\n        console.log(o.a);\n    }\n    expect: {\n        var o = {\n            get a() {\n                return \"PASS\";\n            },\n        };\n        o.a = \"FAIL\";\n        console.log(o.a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2893_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var o = {\n            set a(v) {\n                this.b = v;\n            },\n            b: \"FAIL\",\n        };\n        o.a = \"PASS\";\n        console.log(o.b);\n    }\n    expect: {\n        var o = {\n            set a(v) {\n                this.b = v;\n            },\n            b: \"FAIL\",\n        };\n        o.a = \"PASS\";\n        console.log(o.b);\n    }\n    expect_stdout: \"PASS\"\n}\n\njoin_expr: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function() {\n            var a = 0;\n            switch ((a = {}) && (a.b = 0)) {\n              case 0:\n                c = \"PASS\";\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function() {\n            var a = 0, a = { b: 0 };\n            switch (a.b) {\n              case 0:\n                c = \"PASS\";\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3786: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        try {\n            var a = b;\n            b = 0;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            var a = b;\n            b = 0;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3788: {\n    options = {\n        inline: true,\n        join_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        function f() {\n            function g() {\n                function h() {\n                    a = 42;\n                    a = \"PASS\";\n                    return \"PASS\";\n                }\n                var b = h();\n                console.log(b);\n            }\n            g();\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        var b, a = \"FAIL\";\n        a = 42,\n        a = \"PASS\",\n        b = \"PASS\",\n        console.log(b),\n        console.log(a);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nissue_3789_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        try {\n            c;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        try {} catch (c) {\n            var a;\n            c = 0;\n        }\n    }\n    expect: {\n        try {\n            c;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        try {} catch (c) {\n            var a;\n            c = 0;\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3789_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        try {\n            c;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        try {} catch (c) {\n            try {} catch (c) {\n                var a;\n                c = 0;\n            }\n        }\n    }\n    expect: {\n        try {\n            c;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        try {} catch (c) {\n            try {} catch (c) {\n                var a;\n                c = 0;\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3791_1: {\n    options = {\n        collapse_vars: true,\n        join_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        switch (a) {\n          case console:\n        }\n        var a = a;\n        console.log(a);\n    }\n    expect: {\n        var a;\n        switch (a = \"PASS\") {\n          case console:\n        }\n        var a = a;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3791_2: {\n    options = {\n        collapse_vars: true,\n        join_vars: true,\n    }\n    input: {\n        function f(a) {\n            var b;\n            return b = a || g;\n            function g() {\n                return b;\n            }\n        }\n        console.log(typeof f()());\n    }\n    expect: {\n        function f(a) {\n            var b;\n            return b = a || g;\n            function g() {\n                return b;\n            }\n        }\n        console.log(typeof f()());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_3795: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        dead_code: true,\n        evaluate: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        function f(b, c) {\n            for (var i = 5; c && i; --i) return -1;\n            a = \"PASS\";\n        }\n        var d = f(a = 42, d);\n        console.log(a, d);\n    }\n    expect: {\n        var a = \"FAIL\", d = function() {\n            if (void 0) return -1;\n            a = \"PASS\";\n        }(a = 42);\n        console.log(a, d);\n    }\n    expect_stdout: \"PASS undefined\"\n}\n\nif_body: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a;\n        if (x)\n            var b;\n        else\n            var c;\n    }\n    expect: {\n        var a, b, c;\n        if (x);\n        else;\n    }\n}\n\nif_switch: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a;\n        if (x) switch (y) {\n          case 1:\n            var b;\n          default:\n            var c;\n        }\n    }\n    expect: {\n        var a, b, c;\n        if (x) switch (y) {\n          case 1:\n          default:\n        }\n    }\n}\n\nloop_body_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a;\n        for (;x;)\n            var b;\n    }\n    expect: {\n        for (var a, b; x;);\n    }\n}\n\nloop_body_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        for (var a; x;)\n            var b;\n    }\n    expect: {\n        for (var a, b; x;);\n    }\n}\n\nloop_body_3: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a;\n        for (var b; x;)\n            var c;\n    }\n    expect: {\n        for (var a, b, c; x;);\n    }\n}\n\nconditional_assignments_1: {\n    options = {\n        conditionals: true,\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        function f(b, c, d) {\n            var a = b;\n            if (c) a = d;\n            return a;\n        }\n        function g(b, c, d) {\n            var a = b;\n            if (c); else a = d;\n            return a;\n        }\n        console.log(f(\"FAIL\", 1, \"PASS\"), g(\"PASS\", 1, \"FAIL\"));\n    }\n    expect: {\n        function f(b, c, d) {\n            var a = c ? d : b;\n            return a;\n        }\n        function g(b, c, d) {\n            var a = c ? b : d;\n            return a;\n        }\n        console.log(f(\"FAIL\", 1, \"PASS\"), g(\"PASS\", 1, \"FAIL\"));\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nconditional_assignments_2: {\n    options = {\n        conditionals: true,\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        function f1(c, d) {\n            var a = b;\n            if (c) a = d;\n            return a;\n        }\n        function f2(b, d) {\n            var a = b;\n            if (c) a = d;\n            return a;\n        }\n        function f3(b, c) {\n            var a = b;\n            if (c) a = d;\n            return a;\n        }\n    }\n    expect: {\n        function f1(c, d) {\n            var a = b;\n            return c && (a = d), a;\n        }\n        function f2(b, d) {\n            var a = b;\n            return c && (a = d), a;\n        }\n        function f3(b, c) {\n            var a = b;\n            return c && (a = d), a;\n        }\n    }\n}\n\nconditional_assignments_3: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        console.log(function(b) {\n            var a = \"PASS\";\n            if (b) a = a;\n            return a;\n        }(0, 1));\n    }\n    expect: {\n        console.log(function(b) {\n            var a = \"PASS\";\n            return b && (a = a), a;\n        }(0, 1));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3856_1: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        console.log(function() {\n            (function() {\n                var a;\n                if (!a) {\n                    a = 0;\n                    for (var b; !console;);\n                    return 0;\n                }\n                if (a) return 1;\n            })();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            (function() {\n                var a, b;\n                if (a) a;\n                else {\n                    a = 0;\n                    for (; !console;);\n                }\n            })();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3856_2: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        join_vars: true,\n        passes: 2,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function() {\n            (function() {\n                var a;\n                if (!a) {\n                    a = 0;\n                    for (var b; !console;);\n                    return 0;\n                }\n                if (a) return 1;\n            })();\n        }());\n    }\n    expect: {\n        console.log(function() {\n            (function() {\n                var a, b;\n                if (!a)\n                    for (a = 0; !console;);\n            })();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3916_1: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var o = {};\n        o.p = \"PASS\";\n        o.__proto__ = 42;\n        o.q = \"FAIL\";\n        o.__proto__ = {\n            p: \"FAIL\",\n            q: \"PASS\",\n        };\n        o.__proto__ = \"foo\";\n        console.log(typeof o.__proto__, o.p, delete o.q, o.q);\n    }\n    expect: {\n        var o = {\n            p: \"PASS\",\n            __proto__: 42,\n        };\n        o.q = \"FAIL\";\n        o.__proto__ = {\n            p: \"FAIL\",\n            q: \"PASS\",\n        };\n        o.__proto__ = \"foo\";\n        console.log(typeof o.__proto__, o.p, delete o.q, o.q);\n    }\n    expect_stdout: \"object PASS true PASS\"\n}\n\nissue_3916_2: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var log = console.log, o = {};\n        o.p = \"FAIL 1\";\n        o.__proto__ = {\n            get p() {\n                return \"FAIL 2\";\n            },\n            set p(u) {\n                log(\"FAIL 3\");\n            },\n            set q(v) {\n                log(\"PASS 1\");\n            },\n            get q() {\n                return \"PASS 3\";\n            },\n        };\n        o.p = \"PASS 2\";\n        o.q = \"FAIL 4\";\n        log(o.p);\n        log(o.q);\n    }\n    expect: {\n        var log = console.log, o = {\n            p: \"FAIL 1\",\n            __proto__: {\n                get p() {\n                    return \"FAIL 2\";\n                },\n                set p(u) {\n                    log(\"FAIL 3\");\n                },\n                set q(v) {\n                    log(\"PASS 1\");\n                },\n                get q() {\n                    return \"PASS 3\";\n                },\n            },\n        };\n        o.p = \"PASS 2\";\n        o.q = \"FAIL 4\";\n        log(o.p);\n        log(o.q);\n    }\n    expect_stdout: [\n        \"PASS 1\",\n        \"PASS 2\",\n        \"PASS 3\",\n    ]\n}\n\nassign_var: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        b = \"foo\";\n        var a = [ , \"bar\" ];\n        console.log(b);\n        for (var b in a)\n            console.log(b, a[b]);\n    }\n    expect: {\n        var b = \"foo\", a = [ , \"bar\" ], b;\n        console.log(b);\n        for (b in a)\n            console.log(b, a[b]);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"1 bar\",\n    ]\n}\n\nassign_for_var: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        i = \"foo\",\n        a = new Array(i, \"bar\");\n        for (var i = 2; --i >= 0;) {\n            console.log(a[i]);\n            for (var a in i);\n        }\n    }\n    expect: {\n        for (var i = \"foo\", a = new Array(i, \"bar\"), i = 2; --i >= 0;) {\n            console.log(a[i]);\n            for (var a in i);\n        }\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nassign_sequence_var: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        console.log(a),\n        a++,\n        b = 2;\n        var c = 3;\n        console.log(a, b, c);\n    }\n    expect: {\n        var a = 0, b = 1, c = (console.log(a), a++, b = 2, 3);\n        console.log(a, b, c);\n    }\n    expect_stdout: [\n        \"0\",\n        \"1 2 3\",\n    ]\n}\n\nissue_5175: {\n    options = {\n        join_vars: true,\n    }\n    input: {\n        function log(f) {\n            console.log(f(), A.p);\n        }\n        log(function() {\n            return (A = {}).p = \"PASS\";\n        });\n    }\n    expect: {\n        function log(f) {\n            console.log(f(), A.p);\n        }\n        log(function() {\n            return (A = {}).p = \"PASS\";\n        });\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_5831: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n    }\n    input: {\n        var a = [ console.log(\"PASS\") ];\n        a[0] = 42;\n    }\n    expect: {\n        var a = [ (console.log(\"PASS\"), 42) ];\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5849: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        a = [ 42 ];\n        a[0] = \"PASS\";\n        console.log(a.join(\"\"));\n    }\n    expect: {\n        var a, a = [ \"PASS\" ];\n        console.log(a.join(\"\"));\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/keep_fargs.js",
    "content": "keep_fargs_false: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            return f.length;\n        }(), function g(b) {\n            return g;\n        }().length);\n        function h(c) {\n            return h.length;\n        }\n        function i(d) {\n            return i;\n        }\n        function j(e) {}\n        console.log(h(), i().length, j.length);\n    }\n    expect: {\n        console.log(function f(a) {\n            return f.length;\n        }(), function g(b) {\n            return g;\n        }().length);\n        function h(c) {\n            return h.length;\n        }\n        function i(d) {\n            return i;\n        }\n        function j(e) {}\n        console.log(h(), i().length, j.length);\n    }\n    expect_stdout: [\n        \"1 1\",\n        \"1 1 1\",\n    ]\n}\n\nkeep_fargs_true: {\n    options = {\n        keep_fargs: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            return f.length;\n        }(), function g(b) {\n            return g;\n        }().length);\n        function h(c) {\n            return h.length;\n        }\n        function i(d) {\n            return i;\n        }\n        function j(e) {}\n        console.log(h(), i().length, j.length);\n    }\n    expect: {\n        console.log(function f(a) {\n            return f.length;\n        }(), function g(b) {\n            return g;\n        }().length);\n        function h(c) {\n            return h.length;\n        }\n        function i(d) {\n            return i;\n        }\n        function j(e) {}\n        console.log(h(), i().length, j.length);\n    }\n    expect_stdout: [\n        \"1 1\",\n        \"1 1 1\",\n    ]\n}\n\nreplace_index_strict: {\n    options = {\n        arguments: true,\n        evaluate: true,\n        keep_fargs: false,\n        properties: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(arguments[1], arguments[\"1\"], arguments[\"foo\"]);\n        })(\"bar\", 42);\n    }\n    expect: {\n        \"use strict\";\n        (function(argument_0, argument_1) {\n            console.log(argument_1, argument_1, arguments.foo);\n        })(\"bar\", 42);\n        (function(a, b) {\n            console.log(b, b, arguments.foo);\n        })(\"bar\", 42);\n    }\n    expect_stdout: [\n        \"42 42 undefined\",\n        \"42 42 undefined\",\n    ]\n}\n\nissue_1858: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        pure_getters: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(x) {\n            var a = {}, b = a.b = x;\n            return a.b + b;\n        }(1));\n    }\n    expect: {\n        console.log(function() {\n            var a = {}, b = a.b = 1;\n            return a.b + b;\n        }());\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2187_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        console.log(function(a) {\n            return a && ++b;\n        }(b--));\n    }\n    expect: {\n        var b = 1;\n        console.log(function() {\n            return b-- && ++b;\n        }());\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2203_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        a = \"PASS\";\n        console.log({\n            a: \"FAIL\",\n            b: function() {\n                return function(c) {\n                    return c.a;\n                }((String, (Object, function() {\n                    return this;\n                }())));\n            }\n        }.b());\n    }\n    expect: {\n        a = \"PASS\";\n        console.log({\n            a: \"FAIL\",\n            b: function() {\n                return function() {\n                    return (Object, function() {\n                        return this;\n                    }()).a;\n                }(String);\n            }\n        }.b());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2298: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function f() {\n                var a = undefined;\n                var undefined = a++;\n                try {\n                    !function g(b) {\n                        b[1] = \"foo\";\n                    }();\n                    console.log(\"FAIL\");\n                } catch (e) {\n                    console.log(\"PASS\");\n                }\n            }\n            f();\n        }();\n    }\n    expect: {\n        !function() {\n            (function() {\n                try {\n                    !function() {\n                        (void 0)[1] = \"foo\";\n                    }();\n                    console.log(\"FAIL\");\n                } catch (e) {\n                    console.log(\"PASS\");\n                }\n            })();\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2319_1: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect: {\n        console.log(function() {\n            return !function() {\n                return this;\n            }();\n        }());\n    }\n    expect_stdout: \"false\"\n}\n\nissue_2319_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            \"use strict\";\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect: {\n        console.log(function(a) {\n            \"use strict\";\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect_stdout: \"false\"\n}\n\nissue_2319_3: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function(a) {\n            return a;\n        }(!function() {\n            return this;\n        }()));\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            return !function() {\n                return this;\n            }();\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_2425_1: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var a = 8;\n        (function(b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect: {\n        var a = 8;\n        (function(b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2425_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var a = 8;\n        (function(b, c) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect: {\n        var a = 8;\n        (function(b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2425_3: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var a = 8;\n        (function(b, b) {\n            b.toString();\n        })(--a, a |= 10);\n        console.log(a);\n    }\n    expect: {\n        var a = 8;\n        (function() {\n            (a |= 10).toString();\n        })(--a);\n        console.log(a);\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2436_13: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            function f(b) {\n                (function g(b) {\n                    var b = b && (b.null = \"FAIL\");\n                })(a);\n            }\n            f();\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            (function() {\n                (function() {\n                    a && (a.null = \"FAIL\");\n                })();\n            })();\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2506: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        function f0(bar) {\n            function f1(Infinity_2) {\n                function f13(NaN) {\n                    if (false <= NaN & this >> 1 >= 0) {\n                        c++;\n                    }\n                }\n                var b_2 = f13(NaN, c++);\n            }\n            var bar = f1(-3, -1);\n        }\n        f0(false);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        function f0(bar) {\n            (function() {\n                (function() {\n                    if (false <= 0/0 & this >> 1 >= 0)\n                        c++;\n                })(c++);\n            })();\n        }\n        f0(false);\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2226_1: {\n    options = {\n        keep_fargs: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var a = b;\n            a += c;\n        }\n        function f2(a) {\n            a <<= b;\n        }\n        function f3(a) {\n            --a;\n        }\n        function f4() {\n            var a = b;\n            return a *= c;\n        }\n        function f5(a) {\n            x(a /= b);\n        }\n    }\n    expect: {\n        function f1() {\n            b;\n            c;\n        }\n        function f2(a) {\n            b;\n        }\n        function f3(a) {\n            0;\n        }\n        function f4() {\n            var a = b;\n            return a *= c;\n        }\n        function f5(a) {\n            x(a /= b);\n        }\n    }\n}\n\nissue_2226_2: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            a += b;\n            return a;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(a) {\n            return a += 2;\n        }(1));\n    }\n    expect_stdout: \"3\"\n}\n\nissue_2226_3: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            a += b;\n            return a;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(a) {\n            return a += 2;\n        }(1));\n    }\n    expect_stdout: \"3\"\n}\n\nissue_3192: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n        (function(a) {\n            \"use strict\";\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n    }\n    expect: {\n        (function(a) {\n            console.log(a = \"foo\", arguments[0]);\n        })(\"bar\");\n        (function() {\n            \"use strict\";\n            console.log(\"foo\", arguments[0]);\n        })(\"bar\");\n    }\n    expect_stdout: [\n        \"foo foo\",\n        \"foo bar\",\n    ]\n}\n\nif_increment: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            if (console)\n                return ++a;\n        }(0));\n    }\n    expect: {\n        console.log(function() {\n            if (console)\n                return 1;\n        }());\n    }\n    expect_stdout: \"1\"\n}\n\ntry_increment: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            try {\n                return ++a;\n            } catch (e) {}\n        }(0));\n    }\n    expect: {\n        console.log(function() {\n            try {\n                return 1;\n            } catch (e) {}\n        }());\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2630_3: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var x = 2, a = 1;\n        (function() {\n            function f1(a) {\n                f2();\n                --x >= 0 && f1({});\n            }\n            f1(a++);\n            function f2() {\n                a++;\n            }\n        })();\n        console.log(a);\n    }\n    expect: {\n        var x = 2, a = 1;\n        (function() {\n            (function f1() {\n                f2();\n                --x >= 0 && f1();\n            })(a++);\n            function f2() {\n                a++;\n            }\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"5\"\n}\n\nissue_3364: {\n    options = {\n        functions: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var s = 2, a = 100, b = 10, c = 0;\n        function f(p, e, r) {\n            try {\n                for (var i = 1; i-- > 0;)\n                    var a = function(x) {\n                        function g(y) {\n                            y && y[a++];\n                        }\n                        var x = g(--s >= 0 && f(c++));\n                        for (var j = 1; --j > 0;);\n                    }();\n            } catch (e) {\n                try {\n                    return;\n                } catch (z) {\n                    for (var k = 1; --k > 0;) {\n                        for (var l = 1; l > 0; --l) {\n                            var n = function() {};\n                            for (var k in n)\n                                var o = (n, k);\n                        }\n                    }\n                }\n            }\n        }\n        var r = f();\n        console.log(c);\n    }\n    expect: {\n        var s = 2, c = 0;\n        (function o() {\n            try {\n                for (var r = 1; r-- > 0;)\n                    var n = function() {\n                        (function(r) {\n                            r && r[n++];\n                        })(--s >= 0 && o(c++));\n                        for (var r = 1; --r > 0;);\n                    }();\n            } catch (r) {\n                try {\n                    return;\n                } catch (r) {\n                    for (var a = 1; --a > 0;)\n                        for (var f = 1; f > 0; --f) {\n                            function t() {}\n                            for (var a in t);\n                        }\n                }\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\ndefun_label: {\n    options = {\n        keep_fargs: false,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function f(a) {\n                L: {\n                    if (a) break L;\n                    return 1;\n                }\n            }\n            console.log(f(2));\n        }();\n    }\n    expect: {\n        !function() {\n            console.log(function() {\n                L: {\n                    if (2) break L;\n                    return 1;\n                }\n            }());\n        }();\n    }\n    expect_stdout: true\n}\n\niife_func_side_effects: {\n    options = {\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function x() {\n            console.log(\"x\");\n        }\n        function y() {\n            console.log(\"y\");\n        }\n        function z() {\n            console.log(\"z\");\n        }\n        (function(a, b, c) {\n            function y() {\n                console.log(\"FAIL\");\n            }\n            return y + b();\n        })(x(), function() {\n            return y();\n        }, z());\n    }\n    expect: {\n        function x() {\n            console.log(\"x\");\n        }\n        function y() {\n            console.log(\"y\");\n        }\n        function z() {\n            console.log(\"z\");\n        }\n        (function(b) {\n            return function() {\n                console.log(\"FAIL\");\n            } + b();\n        })((x(), function() {\n            return y();\n        }), z());\n    }\n    expect_stdout: [\n        \"x\",\n        \"z\",\n        \"y\",\n    ]\n}\n\nissue_1595_1: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return f(a + 1);\n        })(2);\n    }\n    expect: {\n        (function f(a) {\n            return f(a + 1);\n        })(2);\n    }\n}\n\nissue_1595_2: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return g(a + 1);\n        })(2);\n    }\n    expect: {\n        (function(a) {\n            return g(a + 1);\n        })(2);\n    }\n}\n\nissue_1595_3: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return g(a + 1);\n        })(2);\n    }\n    expect: {\n        (function() {\n            return g(3);\n        })();\n    }\n}\n\nissue_1595_4: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function iife(a, b, c) {\n            console.log(a, b, c);\n            if (a) iife(a - 1, b, c);\n        })(3, 4, 5);\n    }\n    expect: {\n        (function iife(a, b, c) {\n            console.log(a, b, c);\n            if (a) iife(a - 1, b, c);\n        })(3, 4, 5);\n    }\n    expect_stdout: true\n}\n\nduplicate_lambda_defun_name_1: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function f(a) {\n            function f() {}\n            return f.length;\n        }());\n    }\n    expect: {\n        console.log(function f(a) {\n            function f() {}\n            return f.length;\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nduplicate_lambda_defun_name_2: {\n    options = {\n        keep_fargs: false,\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            function f() {}\n            return f.length;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return function() {}.length;\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nfunction_argument_mangle: {\n    mangle = {\n        keep_fargs: true,\n        toplevel: true,\n    }\n    input: {\n        A = \"PASS\";\n        var a = A;\n        (function(o) {\n            console.log(a);\n        })(\"FAIL\");\n    }\n    expect: {\n        A = \"PASS\";\n        var n = A;\n        (function(o) {\n            console.log(n);\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nfunction_name_mangle: {\n    options = {\n        keep_fargs: false,\n        keep_fnames: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        (function() {\n            function foo(bar) {}\n            console.log(typeof foo);\n        })();\n    }\n    expect_exact: \"(function(){console.log(typeof function o(){})})();\"\n    expect_stdout: \"function\"\n}\n\nfunction_name_mangle_ie8: {\n    options = {\n        keep_fargs: false,\n        keep_fnames: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            function foo(bar) {}\n            console.log(typeof foo);\n        })();\n    }\n    expect_exact: \"(function(){console.log(typeof function o(){})})();\"\n    expect_stdout: \"function\"\n}\n\nissue_3420_1: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return function(a, b, c, d) {\n                return a + b;\n            };\n        }().length);\n    }\n    expect: {\n        console.log(function() {\n            return function(a, b, c, d) {\n                return a + b;\n            };\n        }().length);\n    }\n    expect_stdout: \"4\"\n}\n\nissue_3420_2: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return function(a, b, c, d) {\n                return a + b;\n            };\n        }().length);\n    }\n    expect: {\n        console.log(function(a, b, c, d) {\n            return a + b;\n        }.length);\n    }\n    expect_stdout: \"4\"\n}\n\nissue_3420_3: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function f(a, b, c, d) {\n                return a + b;\n            }\n            return f;\n        }().length);\n    }\n    expect: {\n        console.log(function(a, b, c, d) {\n            return a + b;\n        }.length);\n    }\n    expect_stdout: \"4\"\n}\n\nissue_3423_1: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        function f(g) {\n            console.log(g.length);\n        }\n        f(function(a) {});\n    }\n    expect: {\n        function f(g) {\n            console.log(g.length);\n        }\n        f(function(a) {});\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3423_2: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        new function(a) {\n            console.log(this.constructor.length);\n        }();\n    }\n    expect: {\n        new function(a) {\n            console.log(this.constructor.length);\n        }();\n    }\n    expect_stdout: \"1\"\n}\n\ncollapse_vars_repeated: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        hoist_funs: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f1() {\n            var dummy = 3, a = 5, unused = 2, a = 1, a = 3;\n            return -a;\n        }\n        function f2(x) {\n            var a = 3, a = x;\n            return a;\n        }\n        (function(x) {\n             var a = \"GOOD\" + x, e = \"BAD\", k = \"!\", e = a;\n             console.log(e + k);\n        })(\"!\"),\n        (function(x) {\n            var a = \"GOOD\" + x, e = \"BAD\" + x, k = \"!\", e = a;\n            console.log(e + k);\n        })(\"!\");\n    }\n    expect: {\n        function f1() {\n            return -3;\n        }\n        function f2(x) {\n            return x;\n        }\n        (function() {\n             console.log(\"GOOD!!\");\n        })(),\n        (function() {\n             console.log(\"GOOD!!\");\n        })();\n    }\n    expect_stdout: true\n}\n\nchained_3: {\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            var c = a, c = b;\n            b++;\n            return c;\n        }(1, 2));\n    }\n    expect: {\n        console.log(function(b) {\n            var c = 1, c = b;\n            b++;\n            return c;\n        }(2));\n    }\n    expect_stdout: \"2\"\n}\n\nreplace_all_var_scope: {\n    rename = true\n    options = {\n        collapse_vars: true,\n        keep_fargs: false,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        var a = 100, b = 10;\n        (function(r, a) {\n            switch (~a) {\n              case (b += a):\n              case a++:\n            }\n        })(--b, a);\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        (function(c) {\n            switch (~a) {\n              case (b += a):\n              case c++:\n            }\n        })((--b, a));\n        console.log(a, b);\n    }\n    expect_stdout: \"100 109\"\n}\n\nissue_1583: {\n    options = {\n        keep_fargs: false,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function m(t) {\n            (function(e) {\n                t = e();\n            })(function() {\n                return (function(a) {\n                    return a;\n                })(function(a) {});\n            });\n        }\n    }\n    expect: {\n        function m(t) {\n            (function() {\n                (function() {\n                    return (function() {\n                        return function(a) {};\n                    })();\n                })();\n            })();\n        }\n    }\n}\n\nissues_3267_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        negate_iife: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(x) {\n            x();\n        })(function() {\n            (function(i) {\n                if (i)\n                    return console.log(\"PASS\");\n                throw \"FAIL\";\n            })(Object());\n        });\n    }\n    expect: {\n        !function() {\n            if (Object())\n                return console.log(\"PASS\");\n            throw \"FAIL\";\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\ntrailing_argument_side_effects: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return \"FAIL\";\n        }\n        console.log(function(a, b) {\n            return b || \"PASS\";\n        }(f()));\n    }\n    expect: {\n        function f() {\n            return \"FAIL\";\n        }\n        console.log(function(b) {\n            return b || \"PASS\";\n        }(void f()));\n    }\n    expect_stdout: \"PASS\"\n}\n\nrecursive_iife_1: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a, b) {\n            return b || f(\"FAIL\", \"PASS\");\n        }());\n    }\n    expect: {\n        console.log(function f(a, b) {\n            return b || f(0, \"PASS\");\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nrecursive_iife_2: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a, b) {\n            return b || f(\"FAIL\", \"PASS\");\n        }(null, 0));\n    }\n    expect: {\n        console.log(function f(a, b) {\n            return b || f(0, \"PASS\");\n        }(0, 0));\n    }\n    expect_stdout: \"PASS\"\n}\n\nrecursive_iife_3: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = 1, c = \"PASS\";\n        (function() {\n            function f(b, d, e) {\n                a-- && f(null, 42, 0);\n                e && (c = \"FAIL\");\n                d && d.p;\n            }\n            var a_1 = f();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var a = 1, c = \"PASS\";\n        (function() {\n            (function f(b, d, e) {\n                a-- && f(0, 42, 0);\n                e && (c = \"FAIL\");\n                d && d.p;\n            })();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3619: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var a = 1, b = \"FAIL\";\n        (function f(c, d) {\n            function g() {\n                d && (b = \"PASS\", 0 <= --a && g());\n                0 <= --a && f(0, \"function\");\n            }\n            g();\n        })();\n        console.log(b);\n    }\n    expect: {\n        var a = 1, b = \"FAIL\";\n        (function f(c, d) {\n            function g() {\n                d && (b = \"PASS\", 0 <= --a && g());\n                0 <= --a && f(0, \"function\");\n            }\n            g();\n        })();\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4353_1: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {}.length);\n    }\n    expect: {\n        console.log(function(a) {}.length);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4353_2: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            while (console.log(\"PASS\"));\n        })();\n    }\n    expect: {\n        (function() {\n            while (console.log(\"PASS\"));\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/labels.js",
    "content": "labels_1: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        out: {\n            if (foo) break out;\n            console.log(\"bar\");\n        }\n    };\n    expect: {\n        foo || console.log(\"bar\");\n    }\n    expect_stdout: true\n}\n\nlabels_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        out: {\n            if (foo) print(\"stuff\");\n            else break out;\n            console.log(\"here\");\n        }\n    };\n    expect: {\n        if (foo) {\n            print(\"stuff\");\n            console.log(\"here\");\n        }\n    }\n}\n\nlabels_3: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        for (var i = 0; i < 5; ++i) {\n            if (i < 3) continue;\n            console.log(i);\n        }\n    };\n    expect: {\n        for (var i = 0; i < 5; ++i)\n            i < 3 || console.log(i);\n    }\n    expect_stdout: true\n}\n\nlabels_4: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        out: for (var i = 0; i < 5; ++i) {\n            if (i < 3) continue out;\n            console.log(i);\n        }\n    };\n    expect: {\n        for (var i = 0; i < 5; ++i)\n            i < 3 || console.log(i);\n    }\n    expect_stdout: true\n}\n\nlabels_5: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        unused: true,\n    }\n    // should keep `break`s below\n    input: {\n        while (foo) {\n            if (bar) break;\n            console.log(\"foo\");\n        }\n        out: while (foo) {\n            if (bar) break out;\n            console.log(\"foo\");\n        }\n    };\n    expect: {\n        while (foo) {\n            if (bar) break;\n            console.log(\"foo\");\n        }\n        while (foo) {\n            if (bar) break;\n            console.log(\"foo\");\n        }\n    }\n}\n\nlabels_6: {\n    options = {\n        dead_code: true,\n        unused: true,\n    }\n    input: {\n        out: break out;\n    };\n    expect: {}\n}\n\nlabels_7: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        while (foo) {\n            x();\n            y();\n            continue;\n        }\n    };\n    expect: {\n        while (foo) {\n            x();\n            y();\n        }\n    }\n}\n\nlabels_8: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        while (foo) {\n            x();\n            y();\n            break;\n        }\n    };\n    expect: {\n        while (foo) {\n            x();\n            y();\n            break;\n        }\n    }\n}\n\nlabels_9: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        out: while (foo) {\n            x();\n            y();\n            continue out;\n            z();\n            k();\n        }\n    };\n    expect: {\n        while (foo) {\n            x();\n            y();\n        }\n    }\n}\n\nlabels_10: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        out: while (42) {\n            console.log(\"PASS\");\n            break out;\n            console.log(\"FAIL\");\n        }\n    };\n    expect: {\n        while (42) {\n            console.log(\"PASS\");\n            break;\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nlabels_11: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        unused: true,\n    }\n    input: {\n        L: if (console.log(\"PASS\"))\n            break L;\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nlabels_12: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        L: try {\n            if (console.log(\"foo\"))\n                break L;\n            throw \"bar\";\n        } catch (e) {\n            console.log(e);\n            break L;\n        } finally {\n            if (console.log(\"baz\"))\n                break L;\n        }\n    }\n    expect: {\n        L: try {\n            if (!console.log(\"foo\"))\n                throw \"bar\";\n        } catch (e) {\n            console.log(e);\n        } finally {\n            if (console.log(\"baz\"))\n                break L;\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nissue_4466_1: {\n    mangle = {\n        v8: false,\n    }\n    input: {\n        A: if (console.log(\"PASS\"))\n            B:;\n        else\n            C:;\n    }\n    expect: {\n        e: if (console.log(\"PASS\"))\n            l:;\n        else\n            l:;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_4466_1_v8: {\n    mangle = {\n        v8: true,\n    }\n    input: {\n        A: if (console.log(\"PASS\"))\n            B:;\n        else\n            C:;\n    }\n    expect: {\n        e: if (console.log(\"PASS\"))\n            l:;\n        else\n            o:;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=12\"\n}\n\nissue_4466_2: {\n    mangle = {\n        toplevel: false,\n        v8: false,\n    }\n    input: {\n        if (console.log(\"PASS\"))\n            A:;\n        else\n            B:;\n    }\n    expect: {\n        if (console.log(\"PASS\"))\n            e:;\n        else\n            e:;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4466_2_v8: {\n    mangle = {\n        toplevel: false,\n        v8: true,\n    }\n    input: {\n        if (console.log(\"PASS\"))\n            A:;\n        else\n            B:;\n    }\n    expect: {\n        if (console.log(\"PASS\"))\n            e:;\n        else\n            l:;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4466_2_toplevel: {\n    mangle = {\n        toplevel: true,\n        v8: false,\n    }\n    input: {\n        if (console.log(\"PASS\"))\n            A:;\n        else\n            B:;\n    }\n    expect: {\n        if (console.log(\"PASS\"))\n            e:;\n        else\n            e:;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4466_2_toplevel_v8: {\n    mangle = {\n        toplevel: true,\n        v8: true,\n    }\n    input: {\n        if (console.log(\"PASS\"))\n            A:;\n        else\n            B:;\n    }\n    expect: {\n        if (console.log(\"PASS\"))\n            e:;\n        else\n            e:;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5522: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function() {\n            L: try {\n                return \"FAIL\";\n            } finally {\n                break L;\n            }\n            return \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            L: try {\n                return \"FAIL\";\n            } finally {\n                break L;\n            }\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5524: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        L: try {\n            FAIL;\n        } finally {\n            break L;\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        L: try {\n            FAIL;\n        } finally {\n            break L;\n        }\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5878_1: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        console.log(\"PASS\");\n        L:;\n    }\n    expect_exact: 'console.log(\"PASS\")\\nL:;'\n    expect_stdout: \"PASS\"\n}\n\nissue_5878_2: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        L: ;\n        L: console.log(\"PASS\");\n    }\n    expect_exact: 'L:;L:console.log(\"PASS\")\\n'\n    expect_stdout: \"PASS\"\n}\n\nissue_5878_3: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        if (console.log(\"PASS\"))\n            A:;\n        else\n            B:;\n    }\n    expect_exact: 'if(console.log(\"PASS\"))A:;else B:;'\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/let.js",
    "content": "retain_block_1: {\n    options = {}\n    input: {\n        \"use strict\";\n        {\n            let a = \"FAIL\";\n        }\n        var a = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = \"FAIL\";\n        }\n        var a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nretain_block_2: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            var a;\n            let a;\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            var a;\n            let a;\n        }\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nretain_block_2_mangle: {\n    rename = true\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            var a;\n            let a;\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            var t;\n            let t;\n        }\n    }\n}\n\nretain_block_3: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a;\n            var a;\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a;\n            var a;\n        }\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nretain_block_3_mangle: {\n    rename = true\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a;\n            var a;\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let t;\n            var t;\n        }\n    }\n}\n\nretain_assignment: {\n    options = {\n        dead_code: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            return a = 0;\n            let a;\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            return a = 0;\n            let a;\n        }\n        try {\n            f();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nretain_catch: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        \"use strict\";\n        try {} catch (a) {\n            let a = \"aa\";\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {} catch (a) {\n            let a = \"aa\";\n        }\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nif_dead_branch: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function() {\n            if (0) {\n                let a = 0;\n            }\n            return typeof a;\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            0;\n            {\n                let a;\n            }\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nretain_tail_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                let b = \"bar\";\n                while (console.log(\"baz\"));\n                console.log(b);\n            } else {\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                let b = \"bar\";\n                while (console.log(\"baz\"));\n                console.log(b);\n            } else {\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nretain_tail_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                let b = \"baz\";\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            var b = \"foo\";\n            if (a) {\n                while (console.log(\"bar\"));\n                console.log(b);\n            } else {\n                let b = \"baz\";\n                while (console.log(\"moo\"));\n                console.log(b);\n            }\n        }\n        f();\n        f(42);\n    }\n    expect_stdout: [\n        \"moo\",\n        \"baz\",\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=4\"\n}\n\nmerge_vars_1: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        let a = console;\n        console.log(typeof a);\n        var b = typeof a;\n        console.log(b);\n    }\n    expect: {\n        \"use strict\";\n        let a = console;\n        console.log(typeof a);\n        var b = typeof a;\n        console.log(b);\n    }\n    expect_stdout: [\n        \"object\",\n        \"object\",\n    ]\n    node_version: \">=4\"\n}\n\nmerge_vars_2: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 0;\n        (function() {\n            var b = function f() {\n                let c = a && f;\n                c.var += 0;\n            }();\n            console.log(b);\n        })(1 && --a);\n    }\n    expect: {\n        \"use strict\";\n        var a = 0;\n        1 && --a,\n        b = function f() {\n            let c = a && f;\n            c.var += 0;\n        }(),\n        void console.log(b);\n        var b;\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nmerge_vars_3: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = 0;\n            var b = console;\n            console.log(typeof b);\n        }\n        var a = 1;\n        console.log(typeof a);\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = 0;\n            var b = console;\n            console.log(typeof b);\n        }\n        var b = 1;\n        console.log(typeof b);\n    }\n    expect_stdout: [\n        \"object\",\n        \"number\",\n    ]\n    node_version: \">=4\"\n}\n\nmerge_vars_4: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 1;\n        console.log(typeof a);\n        {\n            var b = console;\n            console.log(typeof b);\n            let a = 0;\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = 1;\n        console.log(typeof a);\n        {\n            var b = console;\n            console.log(typeof b);\n            let a = 0;\n        }\n    }\n    expect_stdout: [\n        \"number\",\n        \"object\",\n    ]\n    node_version: \">=4\"\n}\n\nuse_before_init_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        a = \"foo\";\n        let a = \"bar\";\n    }\n    expect: {\n        \"use strict\";\n        a = \"foo\";\n        let a = \"bar\";\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nuse_before_init_2: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            a = \"foo\";\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        let a = \"bar\";\n    }\n    expect: {\n        \"use strict\";\n        try {\n            a = \"foo\";\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        let a = \"bar\";\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nuse_before_init_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            a;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        let a = 42;\n    }\n    expect: {\n        \"use strict\";\n        try {\n            a;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        let a = 42;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nuse_before_init_4: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            console.log(a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        let a = \"FAIL\";\n    }\n    expect: {\n        \"use strict\";\n        try {\n            console.log(a);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        let a = \"FAIL\";\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ncollapse_block: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        unsafe: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n    }\n    expect_stdout: \"object\"\n    node_version: \">=4\"\n}\n\nreduce_block_1: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n    }\n    expect_stdout: \"object\"\n    node_version: \">=4\"\n}\n\nreduce_block_2: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: [\n        \"object\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_block_2_toplevel: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: [\n        \"object\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_vars_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        let a = \"PASS\";\n        console.log(a);\n        a = \"FAIL\";\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"PASS\");\n        \"FAIL\";\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nreduce_vars_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            function f() {\n                console.log(typeof a);\n            }\n            for (let a in [ 42 ])\n                f();\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            function f() {\n                console.log(typeof a);\n            }\n            for (let a in [ 42 ])\n                f();\n        })();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nreduce_vars_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            let i = 1;\n            function f() {\n                i = 0;\n            }\n            for (let i = 0, x = 0; i < a.length; i++, x++) {\n                if (x != i) {\n                    console.log(\"FAIL\");\n                    break;\n                }\n                f();\n                console.log(a[i]);\n            }\n            console.log(i);\n        })([ 4, 2 ]);\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            let i = 1;\n            function f() {\n                i = 0;\n            }\n            for (let i = 0, x = 0; i < a.length; i++, x++) {\n                if (x != i) {\n                    console.log(\"FAIL\");\n                    break;\n                }\n                f();\n                console.log(a[i]);\n            }\n            console.log(i);\n        })([ 4, 2 ]);\n    }\n    expect_stdout: [\n        \"4\",\n        \"2\",\n        \"0\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_lambda: {\n    options = {\n        evaluate: true,\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        let f = function() {\n            console.log(a, b);\n        };\n        let a = \"foo\", b = 42;\n        f();\n        b = \"bar\";\n        f();\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            console.log(\"foo\", b);\n        }\n        let b = 42;\n        f();\n        b = \"bar\";\n        f();\n    }\n    expect_stdout: [\n        \"foo 42\",\n        \"foo bar\",\n    ]\n    node_version: \">=4\"\n}\n\nhoist_props: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let o = {\n                p: \"PASS\",\n            };\n            console.log(o.p);\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let o = {\n                p: \"PASS\",\n            };\n            console.log(o.p);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nloop_block_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            let o = console;\n            console.log(typeof o.log);\n        } while (!console);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            let o = console;\n            console.log(typeof o.log);\n        } while (!console);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nloop_block_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            let o = {};\n            (function() {\n                console.log(typeof this, o.p++);\n            })();\n        } while (!console);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            let o = {};\n            (function() {\n                console.log(typeof this, o.p++);\n            })();\n        } while (!console);\n    }\n    expect_stdout: \"undefined NaN\"\n    node_version: \">=4\"\n}\n\ndo_break: {\n    options = {\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            do {\n                if (a)\n                    break;\n                let a;\n            } while (!console);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            do {\n                if (a)\n                    break;\n                let a;\n            } while (!console);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndo_continue: {\n    options = {\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            do {\n                {\n                    let a = 0;\n                    continue;\n                }\n            } while ([ A ]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            do {\n                let a = 0;\n                continue;\n            } while ([ A ]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndead_block_after_return: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            console.log(a);\n            return;\n            {\n                let a = \"FAIL\";\n            }\n        })(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            console.log(a);\n            return;\n            {\n                let a;\n            }\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nif_return_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            function g() {\n                return b = \"PASS\";\n            }\n            if (a)\n                return g();\n            let b;\n            return g();\n        };\n        console.log(f());\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            function g() {\n                return b = \"PASS\";\n            }\n            if (a)\n                return g();\n            let b;\n            return g();\n        };\n        console.log(f());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nif_return_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            function g() {\n                return b = \"FAIL\";\n            }\n            if (a)\n                return g();\n            let b;\n            return g();\n        };\n        try {\n            console.log(f(42));\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            function g() {\n                return b = \"FAIL\";\n            }\n            if (a)\n                return g();\n            let b;\n            return g();\n        };\n        try {\n            console.log(f(42));\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nif_return_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"PASS\";\n        function f(b) {\n            if (console) {\n                let b = a;\n                return b;\n            } else\n                while (console.log(\"FAIL 1\"));\n            return b;\n        }\n        console.log(f(\"FAIL 2\"));\n    }\n    expect: {\n        \"use strict\";\n        var a = \"PASS\";\n        function f(b) {\n            if (console) {\n                let b = a;\n                return b;\n            } else\n                while (console.log(\"FAIL 1\"));\n            return b;\n        }\n        console.log(f(\"FAIL 2\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndo_if_continue_1: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            if (console) {\n                console.log(\"PASS\");\n                {\n                    let a = 0;\n                    var b;\n                    continue;\n                }\n            }\n        } while (b);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            if (console) {\n                console.log(\"PASS\");\n                {\n                    let a = 0;\n                    var b;\n                }\n            }\n        } while (b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndo_if_continue_2: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            if (console) {\n                console.log(\"FAIL\");\n                {\n                    let a = 0;\n                    A = 0;\n                    continue;\n                }\n            }\n        } while (A);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            if (console) {\n                console.log(\"FAIL\");\n                {\n                    let a = 0;\n                    A = 0;\n                }\n            }\n        } while (A);\n    }\n    expect_stdout: ReferenceError(\"A is not defined\")\n    node_version: \">=4\"\n}\n\ndrop_unused: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            let b = a, c = b;\n            0 && c.p++;\n        }\n        console.log(f());\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            let b = a;\n            b;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\ndefault_init: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        let a;\n        a = \"PASS\";\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\njoin_let_var_1: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"foo\";\n        let b = \"bar\";\n        for (var c of [ a, b ])\n            console.log(c);\n    }\n    expect: {\n        \"use strict\";\n        let a = \"foo\", b = \"bar\";\n        for (var c of [ a, b ])\n            console.log(c);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\njoin_let_var_2: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        let a = \"foo\";\n        var b = \"bar\";\n        for (let c of [ a, b ])\n            console.log(c);\n    }\n    expect: {\n        \"use strict\";\n        let a = \"foo\", b = \"bar\";\n        for (let c of [ a, b ])\n            console.log(c);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nkeep_let_var_1: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"foo\";\n        let b = \"bar\";\n        for (var c of [ a, b ])\n            console.log(c);\n        function f() {\n            return a;\n        }\n        console.log(f(f));\n    }\n    expect: {\n        \"use strict\";\n        var a = \"foo\", c;\n        let b = \"bar\";\n        for (c of [ a, b ])\n            console.log(c);\n        function f() {\n            return a;\n        }\n        console.log(f(f));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=4\"\n}\n\nkeep_let_var_2: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        let a = \"foo\";\n        var b = \"bar\";\n        for (let c of [ a, b ])\n            console.log(c);\n        function f() {\n            return b;\n        }\n        console.log(f(f));\n    }\n    expect: {\n        \"use strict\";\n        let a = \"foo\";\n        var b = \"bar\";\n        for (let c of [ a, b ])\n            console.log(c);\n        function f() {\n            return b;\n        }\n        console.log(f(f));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4191: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = function() {};\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = function() {};\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_4197: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 0;\n        try {\n            let b = function() {\n                a = 1;\n                b[1];\n            }();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = 0;\n        try {\n            let b = function() {\n                a = 1;\n                b[1];\n            }();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"1\"\n    node_version: \">=4\"\n}\n\nissue_4202: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let o = {};\n            (function() {\n                function f() {\n                    o.p = 42;\n                }\n                f(f);\n            })();\n            console.log(o.p++);\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let o = {};\n            function f() {\n                o.p = 42;\n            }\n            f(f);\n            console.log(o.p++);\n        }\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nissue_4207: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = function() {};\n            console.log(a.length);\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a = function() {};\n            console.log(a.length);\n        }\n    }\n    expect_stdout: \"0\"\n    node_version: \">=4\"\n}\n\nissue_4218: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        {\n            let a = function() {};\n            var b = 0 * a;\n        }\n        console.log(typeof a, b);\n    }\n    expect: {\n        \"use strict\";\n        var b = 0 * function() {};\n        console.log(typeof void 0, b);\n    }\n    expect_stdout: \"undefined NaN\"\n    node_version: \">=4\"\n}\n\nissue_4210: {\n    options = {\n        reduce_vars: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        (function() {\n            try {\n                throw 42;\n            } catch (e) {\n                let a = typeof e;\n                console.log(a);\n            } finally {\n                return a = \"foo\";\n            }\n        })();\n        console.log(typeof a);\n    }\n    expect: {\n        \"use strict\";\n        var a;\n        (function() {\n            try {\n                throw 42;\n            } catch (e) {\n                let a = typeof e;\n                console.log(a);\n            } finally {\n                return a = \"foo\";\n            }\n        })();\n        console.log(typeof a);\n    }\n    expect_stdout: [\n        \"number\",\n        \"string\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4212_1: {\n    options = {\n        dead_code: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        console.log({\n            get b() {\n                let a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect: {\n        \"use strict\";\n        console.log({\n            get b() {\n                let a = 0;\n                return a / 0;\n            }\n        }.b);\n    }\n    expect_stdout: \"NaN\"\n    node_version: \">=4\"\n}\n\nissue_4212_2: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        console.log({\n            get b() {\n                let a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect: {\n        \"use strict\";\n        console.log({\n            get b() {\n                let a = 0;\n                return a /= 0;\n            }\n        }.b);\n    }\n    expect_stdout: \"NaN\"\n    node_version: \">=4\"\n}\n\nskip_braces: {\n    beautify = {\n        beautify: true,\n        braces: true,\n    }\n    input: {\n        \"use strict\";\n        if (console)\n            let a = console.log(typeof a);\n    }\n    expect_exact: [\n        '\"use strict\";',\n        \"\",\n        \"if (console) let a = console.log(typeof a);\",\n    ]\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_4225: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        let a = void typeof b;\n        let b = 42;\n        console.log(a, b);\n    }\n    expect: {\n        \"use strict\";\n        let a = void b;\n        let b = 42;\n        console.log(a, b);\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_4229: {\n    options = {\n        ie: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function f() {\n                f;\n                let f;\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function f() {\n                f;\n                let f;\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4231: {\n    options = {\n        ie: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        typeof a == 0;\n        console.log(typeof function a() {\n            let a;\n        });\n    }\n    expect: {\n        \"use strict\";\n        console.log(typeof function a() {\n            let a;\n        });\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_4245: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        \"use strict\";\n        let a = f();\n        function f() {\n            typeof a;\n        }\n    }\n    expect: {\n        \"use strict\";\n        let a = f();\n        function f() {\n            a,\n            1;\n        }\n    }\n    expect_stdout: ReferenceError(\"a is not defined\")\n    node_version: \">=4\"\n}\n\nissue_4248: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                \"use strict\";\n                a = \"PASS\";\n                b[a];\n                let b;\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            (function() {\n                \"use strict\";\n                a = \"PASS\";\n                b[a];\n                let b;\n            })();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4274_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        for (;;) {\n            if (console.log(\"PASS\")) {\n                let a;\n            } else {\n                break;\n                var a;\n            }\n        }\n    }\n    expect: {\n        \"use strict\";\n        for (; console.log(\"PASS\");) {\n            {\n                let a;\n            }\n            var a;\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4274_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        \"use strict\";\n        for (;;) {\n            if (!console.log(\"PASS\")) {\n                break;\n                var a;\n            } else {\n                let a;\n            }\n        }\n    }\n    expect: {\n        \"use strict\";\n        for (; console.log(\"PASS\");) {\n            {\n                let a;\n            }\n            var a;\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4276_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            let a = b, b;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            let a = b, b;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4276_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            let a = f(), b;\n            console.log(\"FAIL\");\n            function f() {\n                return b;\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            let a = f(), b;\n            console.log(\"FAIL\");\n            function f() {\n                return b;\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4290_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        let a;\n        var a;\n    }\n    expect: {\n        \"use strict\";\n        let a;\n        var a;\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_4290_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            console.log(function(a) {\n                a = c;\n                let c;\n                return a;\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            console.log(function(a) {\n                a = c;\n                let c;\n                return a;\n            }());\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4305_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            let arguments = function() {\n                while (console.log(\"PASS\"));\n            };\n            arguments();\n        })();\n    }\n    expect: {\n        (function() {\n            let arguments = function() {\n                while (console.log(\"PASS\"));\n            };\n            arguments();\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4305_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            let a = function() {\n                while (console.log(\"aaaaa\"));\n            };\n            a();\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            let a = function() {\n                while (console.log(\"aaaaa\"));\n            };\n            a();\n        })();\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nissue_4438: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            if (console) {\n                {\n                    let a = console.log;\n                    return void a(\"PASS\");\n                }\n            }\n        }\n        f();\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            if (console) {\n                let a = console.log;\n                a(\"PASS\");\n            }\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4531_1: {\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        var a;\n        console.log(function a() {\n            let a;\n            var b;\n        }());\n    }\n    expect: {\n        \"use strict\";\n        var o;\n        console.log(function o() {\n            let o;\n            var t;\n        }());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_4531_2: {\n    options = {\n        evaluate: true,\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = console;\n        console.log(typeof a, function a() {\n            let { [console]: a } = 0 && a;\n            var b = console;\n            while (!b);\n        }());\n    }\n    expect: {\n        var o = console;\n        console.log(typeof o, function o() {\n            let { [console]: o } = 0;\n            var e = console;\n            while (!e);\n        }());\n    }\n    expect_stdout: \"object undefined\"\n    node_version: \">=6\"\n}\n\nissue_4689: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"PASS\";\n        console.log(a);\n        for (let a in 42);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"PASS\";\n        console.log(a);\n        for (let a in 42);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4691: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        function A() {}\n        A.prototype.f = function() {\n            if (!this)\n                return;\n            let a = \"PA\";\n            function g(b) {\n                h(a + b);\n            }\n            [ \"SS\" ].forEach(function(c) {\n                g(c);\n            });\n        };\n        function h(d) {\n            console.log(d);\n        }\n        new A().f();\n    }\n    expect: {\n        \"use strict\";\n        function A() {}\n        A.prototype.f = function() {\n            if (this) {\n                let a = \"PA\";\n                [ \"SS\" ].forEach(function(c) {\n                    g(c);\n                });\n                function g(b) {\n                    h(a + b);\n                }\n            }\n        };\n        function h(d) {\n            console.log(d);\n        }\n        new A().f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4848: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            a(function() {\n                console.log(b);\n            });\n            if (!console)\n                return;\n            let b = \"PASS\";\n        }\n        var g;\n        f(function(h) {\n            g = h;\n        });\n        g();\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            a(function() {\n                console.log(b);\n            });\n            if (!console)\n                return;\n            let b = \"PASS\";\n        }\n        var g;\n        f(function(h) {\n            g = h;\n        });\n        g();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4985: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        let a = { p: 42 };\n        console.log(function() {\n            a;\n        }());\n    }\n    expect: {\n        \"use strict\";\n        let a = { p: 42 };\n        console.log(function() {\n            a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5240: {\n    options = {\n        inline: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            if (console) {\n                let g = function() {\n                    e;\n                }, e;\n                (function() {\n                    if (console) {\n                        console.log(e);\n                        var e = \"FAIL\";\n                    }\n                })(console.log(e));\n            }\n        }\n        f();\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            if (console) {\n                let g = function() {\n                    e;\n                }, e;\n                (function() {\n                    if (console) {\n                        console.log(e);\n                        var e = \"FAIL\";\n                    }\n                })(console.log(e));\n            }\n        }\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5254: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            (function() {\n                let a = console.log;\n                a && a(\"foo\");\n            })();\n        } while (console.log(\"bar\"));\n    }\n    expect: {\n        \"use strict\";\n        do {\n            let a = console.log;\n            a && a(\"foo\");\n        } while (console.log(\"bar\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5260: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var a = \"foo\", o;\n        while (console.log(\"bar\"));\n        o = {\n            baz: function(b) {\n                console.log(a, b);\n            },\n        };\n        for (let a in o)\n            o[a](a);\n    }\n    expect: {\n        \"use strict\";\n        var a = \"foo\", o;\n        while (console.log(\"bar\"));\n        o = {\n            baz: function(b) {\n                console.log(a, b);\n            },\n        };\n        for (let a in o)\n            o[a](a);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo baz\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5319: {\n    options = {\n        collapse_vars: true,\n        merge_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a, c) {\n            var b = a, c = b;\n            {\n                let a = c;\n                console.log(c());\n            }\n        })(function() {\n            return \"PASS\";\n        });\n    }\n    expect: {\n        \"use strict\";\n        (function(a, c) {\n            var b = a, c;\n            {\n                let a = c = b;\n                console.log(c());\n            }\n        })(function() {\n            return \"PASS\";\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5338: {\n    options = {\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        let a = a;\n    }\n    expect: {\n        \"use strict\";\n        a;\n        let a;\n    }\n    expect_stdout: ReferenceError(\"a is not defined\")\n    node_version: \">=4\"\n}\n\nissue_5476: {\n    mangle = {\n        keep_fargs: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function(n) {\n            let a;\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(function(n) {\n            let o;\n        }());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5591: {\n    options = {\n        dead_code: true,\n        if_return: true,\n    }\n    input: {\n        \"use strict\";\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console.log(\"baz\"))\n                    return;\n                else {\n                    let a;\n                    return;\n                }\n                break;\n              case null:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect: {\n        \"use strict\";\n        function f(a) {\n            switch (console.log(\"foo\")) {\n              case console.log(\"bar\"):\n                if (console.log(\"baz\"))\n                    return;\n                else {\n                    let a;\n                    return;\n                }\n              case null:\n                FAIL;\n            }\n        }\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5741: {\n    options = {\n        inline: true,\n        join_vars: true,\n        reduce_vars: true,\n    }\n    input: {\n        \"use strict\";\n        (function(a) {\n            let b = function() {\n                var c = a;\n                console.log(c);\n            }();\n            function g() {\n                a++;\n                b;\n            }\n        })(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        (function(a) {\n            let b = (c = a, void console.log(c));\n            var c;\n            function g() {\n                a++;\n                b;\n            }\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5745_1: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let f = function() {\n                return f && \"PASS\";\n            };\n            var a = f();\n        }\n        a;\n        console.log(a);\n    }\n    expect: {\n        \"use strict\";\n        {\n            let f = function() {\n                return f && \"PASS\";\n            };\n            var a = f();\n        }\n        a;\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5745_2: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let f = function() {\n                return f && \"PASS\";\n            };\n            var a = f();\n            a;\n            console.log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let f = function() {\n                return f && \"PASS\";\n            }, a = f();\n            a;\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5756_1: {\n    options = {\n        join_vars: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        do {\n            function f() {\n                return b;\n            }\n            var a = \"PASS\".toString();\n            let b;\n            console.log(a);\n        } while (!console);\n    }\n    expect: {\n        \"use strict\";\n        do {\n            function f() {\n                return b;\n            }\n            let a = \"PASS\".toString(), b;\n            console.log(a);\n        } while (!console);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5756_2: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            let a = console.log(\"PASS\");\n            {\n                var b;\n                for (var c in b) {\n                    b;\n                    var c = function() {\n                        a;\n                    };\n                }\n            }\n        }\n        f();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            let a = console.log(\"PASS\"), b;\n            for (c in b) {\n                b;\n                var c = function() {\n                    a;\n                };\n            }\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5756_3: {\n    options = {\n        module: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(f()());\n        function f() {\n            const a = \"PASS\";\n            return function() {\n                return a;\n            };\n        }\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            let a = \"PASS\";\n            return function() {\n                return a;\n            };\n        }()());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5759: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        join_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        function f() {\n            for (var a in [ true ]) {\n                let b;\n                (function() {\n                    var c = void 0;\n                    b;\n                    console.log(c);\n                    var d = null;\n                    console.log(c);\n                })();\n            }\n        }\n        f();\n    }\n    expect: {\n        \"use strict\";\n        function f() {\n            for (var a in [ true ]) {\n                let b;\n                var c = c = void 0;\n                b;\n                console.log(c);\n                console.log(c);\n            }\n        }\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5787: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            let a = 42;\n            switch (a) {\n              case 42:\n                // Node.js v4 (vm): SyntaxError: Identifier 'a' has already been declared\n                let a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            let a = 42;\n            switch (a) {\n              case 42:\n                let a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5950: {\n    options = {\n        conditionals: true,\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a;\n            if (console.log(\"PASS\")) {\n                var b = function() {\n                    a;\n                }, c = b;\n            }\n        }\n    }\n    expect: {\n        \"use strict\";\n        {\n            let a;\n            console.log(\"PASS\") && function() {\n                a;\n            };\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n"
  },
  {
    "path": "test/compress/loops.js",
    "content": "while_becomes_for: {\n    options = {\n        loops: true,\n    }\n    input: {\n        while (foo()) bar();\n    }\n    expect: {\n        for (;foo();) bar();\n    }\n}\n\ndrop_if_break_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;;)\n            if (foo()) break;\n    }\n    expect: {\n        for (;!foo(););\n    }\n}\n\ndrop_if_break_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;bar();)\n            if (foo()) break;\n    }\n    expect: {\n        for (;bar() && !foo(););\n    }\n}\n\ndrop_if_break_3: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;bar();) {\n            if (foo()) break;\n            stuff1();\n            stuff2();\n        }\n    }\n    expect: {\n        for (; bar() && !foo();) {\n            stuff1();\n            stuff2();\n        }\n    }\n}\n\ndrop_if_break_4: {\n    options = {\n        loops: true,\n        sequences: true,\n    }\n    input: {\n        for (;bar();) {\n            x();\n            y();\n            if (foo()) break;\n            z();\n            k();\n        }\n    }\n    expect: {\n        for (;bar() && (x(), y(), !foo());) z(), k();\n    }\n}\n\ndrop_if_else_break_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;;) if (foo()) bar(); else break;\n    }\n    expect: {\n        for (;foo();) bar();\n    }\n}\n\ndrop_if_else_break_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;bar();) {\n            if (foo()) baz();\n            else break;\n        }\n    }\n    expect: {\n        for (;bar() && foo();) baz();\n    }\n}\n\ndrop_if_else_break_3: {\n    options = {\n        loops: true,\n    }\n    input: {\n        for (;bar();) {\n            if (foo()) baz();\n            else break;\n            stuff1();\n            stuff2();\n        }\n    }\n    expect: {\n        for (;bar() && foo();) {\n            baz();\n            stuff1();\n            stuff2();\n        }\n    }\n}\n\ndrop_if_else_break_4: {\n    options = {\n        loops: true,\n        sequences: true,\n    }\n    input: {\n        for (;bar();) {\n            x();\n            y();\n            if (foo()) baz();\n            else break;\n            z();\n            k();\n        }\n    }\n    expect: {\n        for (;bar() && (x(), y(), foo());) baz(), z(), k();\n    }\n}\n\nparse_do_while_with_semicolon: {\n    options = {\n        loops: false,\n    }\n    input: {\n        do {\n            x();\n        } while (false);y()\n    }\n    expect: {\n        do x(); while (false);y();\n    }\n}\n\nparse_do_while_without_semicolon: {\n    options = {\n        loops: false,\n    }\n    input: {\n        do {\n            x();\n        } while (false)y()\n    }\n    expect: {\n        do x(); while (false);y();\n    }\n}\n\nevaluate: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        passes: 2,\n        side_effects: true,\n    }\n    input: {\n        while (true) {\n            a();\n        }\n        while (false) {\n            b();\n        }\n        do {\n            c();\n        } while (true);\n        do {\n            d();\n        } while (false);\n    }\n    expect: {\n        for (;;)\n            a();\n        for (;;)\n            c();\n        d();\n    }\n}\n\nissue_1532_1: {\n    options = {\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        function f(x, y) {\n            do {\n                if (x) break;\n                console.log(y);\n            } while (false);\n        }\n        f(null, \"PASS\");\n        f(42, \"FAIL\");\n    }\n    expect: {\n        function f(x, y) {\n            for (; !x && (console.log(y), false););\n        }\n        f(null, \"PASS\");\n        f(42, \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1532_2: {\n    options = {\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        function f(x, y) {\n            do {\n                if (x) {\n                    console.log(x);\n                    break;\n                }\n                console.log(y);\n            } while (false);\n        }\n        f(null, \"PASS\");\n        f(42, \"FAIL\");\n    }\n    expect: {\n        function f(x, y) {\n            do {\n                if (x) {\n                    console.log(x);\n                    break;\n                }\n            } while (console.log(y), false);\n        }\n        f(null, \"PASS\");\n        f(42, \"FAIL\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n}\n\nissue_186: {\n    beautify = {\n        beautify: false,\n        ie: false,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: 'var x=3;if(foo())do{do{alert(x)}while(--x)}while(x);else bar();'\n}\n\nissue_186_ie8: {\n    beautify = {\n        beautify: false,\n        ie: true,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else bar();'\n}\n\nissue_186_beautify: {\n    beautify = {\n        beautify: true,\n        ie: false,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: [\n        'var x = 3;',\n        '',\n        'if (foo()) do {',\n        '    do {',\n        '        alert(x);',\n        '    } while (--x);',\n        '} while (x); else bar();',\n    ]\n}\n\nissue_186_beautify_ie8: {\n    beautify = {\n        beautify: true,\n        ie: true,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: [\n        'var x = 3;',\n        '',\n        'if (foo()) {',\n        '    do {',\n        '        do {',\n        '            alert(x);',\n        '        } while (--x);',\n        '    } while (x);',\n        '} else bar();',\n    ]\n}\n\nissue_186_braces: {\n    beautify = {\n        beautify: false,\n        braces: true,\n        ie: false,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'\n}\n\nissue_186_braces_ie8: {\n    beautify = {\n        beautify: false,\n        braces: true,\n        ie: true,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: 'var x=3;if(foo()){do{do{alert(x)}while(--x)}while(x)}else{bar()}'\n}\n\nissue_186_beautify_braces: {\n    beautify = {\n        beautify: true,\n        braces: true,\n        ie: false,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: [\n        'var x = 3;',\n        '',\n        'if (foo()) {',\n        '    do {',\n        '        do {',\n        '            alert(x);',\n        '        } while (--x);',\n        '    } while (x);',\n        '} else {',\n        '    bar();',\n        '}',\n    ]\n}\n\nissue_186_beautify_braces_ie8: {\n    beautify = {\n        beautify: true,\n        braces: true,\n        ie: true,\n    }\n    input: {\n        var x = 3;\n        if (foo())\n            do\n                do\n                    alert(x);\n                while (--x);\n            while (x);\n        else\n            bar();\n    }\n    expect_exact: [\n        'var x = 3;',\n        '',\n        'if (foo()) {',\n        '    do {',\n        '        do {',\n        '            alert(x);',\n        '        } while (--x);',\n        '    } while (x);',\n        '} else {',\n        '    bar();',\n        '}',\n    ]\n}\n\nissue_1648: {\n    options = {\n        join_vars: true,\n        loops: true,\n        passes: 2,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            x();\n            var b = 1;\n            while (1);\n        }\n    }\n    expect_exact: \"function f(){for(x();1;);}\"\n}\n\ndo_switch: {\n    options = {\n        evaluate: true,\n        loops: true,\n    }\n    input: {\n        do {\n            switch (a) {\n              case b:\n                continue;\n            }\n        } while (false);\n    }\n    expect: {\n        do {\n            switch (a) {\n              case b:\n                continue;\n            }\n        } while (false);\n    }\n}\n\nin_parentheses_1: {\n    input: {\n        for ((\"foo\" in {});0;);\n    }\n    expect_exact: 'for((\"foo\"in{});0;);'\n}\n\nin_parentheses_2: {\n    input: {\n        for ((function(){ \"foo\" in {}; });0;);\n    }\n    expect_exact: 'for(function(){\"foo\"in{}};0;);'\n}\n\ninit_side_effects: {\n    options = {\n        loops: true,\n        side_effects: true,\n    }\n    input: {\n        for (function() {}(), i = 0; i < 5; i++) console.log(i);\n        for (function() {}(); i < 10; i++) console.log(i);\n    }\n    expect: {\n        for (i = 0; i < 5; i++) console.log(i);\n        for (; i < 10; i++) console.log(i);\n    }\n    expect_stdout: true\n}\n\ndead_code_condition: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        sequences: true,\n    }\n    input: {\n        for (var a = 0, b = 5; (a += 1, 3) - 3 && b > 0; b--) {\n            var c = function() {\n                b--;\n            }(a++);\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = 0, b = 5;\n        var c;\n        a += 1, 0,\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2740_1: {\n    options = {\n        dead_code: true,\n        loops: true,\n    }\n    input: {\n        for (;;) break;\n        for (a();;) break;\n        for (;b();) break;\n        for (c(); d();) break;\n        for (;;e()) break;\n        for (f();; g()) break;\n        for (;h(); i()) break;\n        for (j(); k(); l()) break;\n    }\n    expect: {\n        a();\n        b();\n        c();\n        d();\n        f();\n        h();\n        j();\n        k();\n    }\n}\n\nissue_2740_2: {\n    options = {\n        dead_code: true,\n        loops: true,\n        passes: 2,\n        unused: true,\n    }\n    input: {\n        L1: while (x()) {\n            break L1;\n        }\n    }\n    expect: {\n        x();\n    }\n}\n\nissue_2740_3: {\n    options = {\n        dead_code: true,\n        loops: true,\n        unused: true,\n    }\n    input: {\n        L1: for (var x = 0; x < 3; x++) {\n            L2: for (var y = 0; y < 2; y++) {\n                break L1;\n            }\n        }\n        console.log(x, y);\n    }\n    expect: {\n        L1: for (var x = 0; x < 3; x++) {\n            var y = 0;\n            if (y < 2)\n                break L1;\n        }\n        console.log(x, y);\n    }\n    expect_stdout: \"0 0\"\n}\n\nissue_2740_4: {\n    options = {\n        dead_code: true,\n        loops: true,\n        passes: 2,\n        unused: true,\n    }\n    input: {\n        L1: for (var x = 0; x < 3; x++) {\n            L2: for (var y = 0; y < 2; y++) {\n                break L2;\n            }\n        }\n        console.log(x, y);\n    }\n    expect: {\n        for (var x = 0; x < 3; x++) {\n            var y = 0;\n            y < 2;\n        }\n        console.log(x, y);\n    }\n    expect_stdout: \"3 0\"\n}\n\nissue_2740_5: {\n    options = {\n        dead_code: true,\n        loops: true,\n        passes: 2,\n        unused: true,\n    }\n    input: {\n        L1: for (var x = 0; x < 3; x++) {\n            break L1;\n            L2: for (var y = 0; y < 2; y++) {\n                break L2;\n            }\n        }\n        console.log(x, y);\n    }\n    expect: {\n        var x = 0;\n        x < 3;\n        var y;\n        console.log(x,y);\n    }\n    expect_stdout: \"0 undefined\"\n}\n\nissue_2904: {\n    options = {\n        join_vars: true,\n        loops: true,\n    }\n    input: {\n        var a = 1;\n        do {\n            console.log(a);\n        } while (--a);\n    }\n    expect: {\n        for (var a = 1; console.log(a), --a;);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3371: {\n    options = {\n        functions: true,\n        join_vars: true,\n        loops: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = function() {\n                console.log(\"PASS\");\n            };\n            while (a());\n        })();\n    }\n    expect: {\n        (function() {\n            function a() {\n                console.log(\"PASS\");\n            }\n            for (;a(););\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nstep: {\n    options = {\n        loops: true,\n        side_effects: true,\n    }\n    input: {\n        for (var i = 0; i < 42; \"foo\", i++, \"bar\");\n        console.log(i);\n    }\n    expect: {\n        for (var i = 0; i < 42; i++);\n        console.log(i);\n    }\n    expect_stdout: \"42\"\n}\n\nempty_for_in: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var a in [ 1, 2, 3 ]) {\n            var b = a + 1;\n        }\n    }\n    expect: {}\n    expect_warnings: [\n        \"WARN: Dropping unused variable b [test/compress/loops.js:2,16]\",\n        \"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]\",\n    ]\n}\n\nempty_for_in_used: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var a in [ 1, 2, 3 ]) {\n            var b = a + 1;\n        }\n        console.log(a);\n    }\n    expect: {\n        for (var a in [ 1, 2, 3 ]);\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n    expect_warnings: [\n        \"WARN: Dropping unused variable b [test/compress/loops.js:2,16]\",\n    ]\n}\n\nempty_for_in_side_effects: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var a in {\n            foo: console.log(\"PASS\")\n        }) {\n            var b = a + \"bar\";\n        }\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    expect_warnings: [\n        \"WARN: Dropping unused variable b [test/compress/loops.js:4,16]\",\n        \"INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]\",\n        \"WARN: Side effects in object of for-in loop [test/compress/loops.js:2,17]\",\n    ]\n}\n\nempty_for_in_prop_init: {\n    options = {\n        loops: true,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        console.log(function f() {\n            var a = \"bar\";\n            for ((a, f)[a] in console.log(\"foo\"));\n            return a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a = \"bar\";\n            console.log(\"foo\");\n            return a;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    expect_warnings: [\n        \"INFO: Dropping unused loop variable f [test/compress/loops.js:3,21]\",\n        \"WARN: Side effects in object of for-in loop [test/compress/loops.js:3,30]\",\n    ]\n}\n\nfor_of: {\n    input: {\n        var a = [ \"PASS\", 42 ];\n        a.p = \"FAIL\";\n        for (a of (null, a))\n            console.log(a);\n    }\n    expect_exact: 'var a=[\"PASS\",42];a.p=\"FAIL\";for(a of(null,a))console.log(a);'\n    expect_stdout: true\n    node_version: \">=0.12\"\n}\n\nfor_async_of: {\n    input: {\n        var async = [ \"PASS\", 42 ];\n        async.p = \"FAIL\";\n        for (async of (null, async))\n            console.log(async);\n    }\n    expect_exact: 'var async=[\"PASS\",42];async.p=\"FAIL\";for(async of(null,async))console.log(async);'\n    expect_stdout: true\n    node_version: \">=0.12 <16\"\n}\n\nfor_of_regexp: {\n    input: {\n        for (var a of /foo/);\n    }\n    expect_exact: \"for(var a of/foo/);\"\n}\n\nfor_await_of_regexp: {\n    input: {\n        for await (var a of /foo/);\n    }\n    expect_exact: \"for await(var a of/foo/);\"\n}\n\nissue_3631_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        L: do {\n            for (;;) continue L;\n            var b = 1;\n        } while (b && c++);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        do {\n            var b;\n        } while (b && c++);\n        console.log(c);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_3631_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        L: for (var a = 1; a--; console.log(b)) {\n            for (;;) continue L;\n            var b = \"FAIL\";\n        }\n    }\n    expect: {\n        for (var a = 1; a--; console.log(b))\n            var b;\n    }\n    expect_stdout: \"undefined\"\n}\n\nloop_if_break: {\n    options = {\n        dead_code: true,\n        loops: true,\n    }\n    input: {\n        function f(a, b) {\n            try {\n                while (a) {\n                    if (b) {\n                        break;\n                        var c = 42;\n                        console.log(c);\n                    } else {\n                        var d = false;\n                        throw d;\n                    }\n                }\n            } catch (e) {\n                console.log(\"E:\", e);\n            }\n            console.log(a, b, c, d);\n        }\n        f(0, 0);\n        f(0, 1);\n        f(1, 0);\n        f(1, 1);\n    }\n    expect: {\n        function f(a, b) {\n            try {\n                for (;a && !b;) {\n                    var d = false;\n                    throw d;\n                    var c;\n                }\n            } catch (e) {\n                console.log(\"E:\", e);\n            }\n            console.log(a, b, c, d);\n        }\n        f(0, 0);\n        f(0, 1);\n        f(1, 0);\n        f(1, 1);\n    }\n    expect_stdout: [\n        \"0 0 undefined undefined\",\n        \"0 1 undefined undefined\",\n        \"E: false\",\n        \"1 0 undefined false\",\n        \"1 1 undefined undefined\",\n    ]\n}\n\nloop_return: {\n    options = {\n        dead_code: true,\n        loops: true,\n    }\n    input: {\n        function f(a) {\n            while (a) return 42;\n            return \"foo\";\n        }\n        console.log(f(0), f(1));\n    }\n    expect: {\n        function f(a) {\n            if (a) return 42;\n            return \"foo\";\n        }\n        console.log(f(0), f(1));\n    }\n    expect_stdout: \"foo 42\"\n}\n\nissue_3634_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        var b = 0;\n        L: while (++b < 2)\n            while (1)\n                if (b) break L;\n        console.log(b);\n    }\n    expect: {\n        var b = 0;\n        L: for (;++b < 2;)\n            for (;1;)\n                if (b) break L;\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3634_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        var b = 0;\n        L: while (++b < 2)\n            while (1)\n                if (!b)\n                    continue L;\n                else\n                    break L;\n        console.log(b);\n    }\n    expect: {\n        var b = 0;\n        L: for (;++b < 2;)\n            for (;1;)\n                if (!b)\n                    continue L;\n                else\n                    break L;\n        console.log(b);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_4075: {\n    options = {\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function() {\n            for (a in { PASS: 0 });\n        })()\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function() {\n            for (a in { PASS: 0 });\n        })()\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4082: {\n    options = {\n        keep_fargs: false,\n        loops: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function(a) {\n            for (a in \"foo\")\n                var b;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function(a) {\n            for (a in \"foo\");\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4084: {\n    options = {\n        keep_fargs: false,\n        loops: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function f(a) {\n                var b = a++;\n                for (a in \"foo\");\n            }\n            f();\n            return typeof a;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            (function() {\n                0;\n            })();\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4091_1: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw \"FAIL\";\n        } catch (e) {\n            for (var e in 42);\n        }\n        console.log(e && e);\n    }\n    expect: {\n        try {\n            throw \"FAIL\";\n        } catch (e) {\n            var e;\n        }\n        console.log(e && e);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4091_2: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw \"FAIL\";\n        } catch (e) {\n            for (e in 42);\n            var e;\n        }\n        console.log(e && e);\n    }\n    expect: {\n        try {\n            throw \"FAIL\";\n        } catch (e) {\n            var e;\n        }\n        console.log(e && e);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4182_1: {\n    options = {\n        loops: true,\n    }\n    input: {\n        (function() {\n            do {\n                try {\n                    return;\n                } finally {\n                    continue;\n                }\n                console.log(\"FAIL\");\n            } while (0);\n            console.log(\"PASS\");\n        })();\n    }\n    expect: {\n        (function() {\n            do {\n                try {\n                    return;\n                } finally {\n                    continue;\n                }\n                console.log(\"FAIL\");\n            } while (0);\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4182_2: {\n    options = {\n        loops: true,\n    }\n    input: {\n        (function() {\n            L: do {\n                do {\n                    try {\n                        return;\n                    } finally {\n                        continue L;\n                    }\n                    console.log(\"FAIL\");\n                } while (0);\n                console.log(\"FAIL\");\n            } while (0);\n            console.log(\"PASS\");\n        })();\n    }\n    expect: {\n        (function() {\n            L: do {\n                do {\n                    try {\n                        return;\n                    } finally {\n                        continue L;\n                    }\n                } while (console.log(\"FAIL\"), 0);\n                console.log(\"FAIL\");\n            } while (0);\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\ndo_continue: {\n    options = {\n        loops: true,\n    }\n    input: {\n        try {\n            do {\n                continue;\n            } while ([ A ]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            do {\n                continue;\n            } while ([ A ]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4240: {\n    options = {\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            function f() {\n                var o = { PASS: 42 };\n                for (a in o);\n            }\n            (function() {\n                if (f());\n            })();\n            console.log(a);\n        })();\n    }\n    expect: {\n        (function(a) {\n            (function() {\n                if (function() {\n                    for (a in { PASS: 42 });\n                }());\n            })();\n            console.log(a);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4355: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        passes: 2,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        while (function() {\n            var a;\n            for (a in console.log(\"PASS\"))\n                var b = 0;\n        }())\n            var c;\n    }\n    expect: {\n        (function() {\n            console.log(\"PASS\");\n        })();\n        var c;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4564: {\n    options = {\n        loops: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw null;\n        } catch (a) {\n            var a;\n            (function() {\n                for (a in \"foo\");\n            })();\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            throw null;\n        } catch (a) {\n            var a;\n            (function() {\n                for (a in \"foo\");\n            })();\n            console.log(a);\n        }\n    }\n    expect_stdout: \"2\"\n}\n"
  },
  {
    "path": "test/compress/max_line_len.js",
    "content": "too_short: {\n    beautify = {\n        max_line_len: 10,\n    }\n    input: {\n        function f(a) {\n            return { c: 42, d: a(), e: \"foo\"};\n        }\n    }\n    expect_exact: [\n        \"function f(\",\n        \"a){return{\",\n        \"c:42,d:a(\",\n        '),e:\"foo\"}',\n        \"}\",\n    ]\n    expect_warnings: [\n        \"WARN: Output exceeds 10 characters\",\n    ]\n}\n\njust_enough: {\n    beautify = {\n        max_line_len: 14,\n    }\n    input: {\n        function f(a) {\n            return { c: 42, d: a(), e: \"foo\"};\n        }\n    }\n    expect_exact: [\n        \"function f(a){\",\n        \"return{c:42,\",\n        'd:a(),e:\"foo\"}',\n        \"}\",\n    ]\n    expect_warnings: []\n}\n\ndrop_semicolon: {\n    beautify = {\n        max_line_len: 5,\n        semicolons: true,\n    }\n    input: {\n        var a;\n        console.log(a || 42);\n    }\n    expect_exact: [\n        \"var a\",\n        \"console.log(\",\n        \"a||42\",\n        \");\",\n    ]\n    expect_stdout: \"42\"\n    expect_warnings: [\n        \"WARN: Output exceeds 5 characters\",\n    ]\n}\n\ntemplate_newline: {\n    beautify = {\n        max_line_len: 2,\n    }\n    input: {\n        console.log(`foo\nbar`);\n    }\n    expect_exact: [\n        \"console.log(\",\n        \"`foo\",\n        \"bar`\",\n        \");\",\n    ]\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    expect_warnings: [\n        \"WARN: Output exceeds 2 characters\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_304: {\n    beautify = {\n        max_line_len: 10,\n    }\n    input: {\n        var a = 0, b = 0, c = 0, d = 0, e = 0;\n    }\n    expect_exact: [\n        \"var a=0,\",\n        \"b=0,c=0,\",\n        \"d=0,e=0;\",\n    ]\n    expect_warnings: []\n}\n"
  },
  {
    "path": "test/compress/merge_vars.js",
    "content": "merge: {\n    options = {\n        merge_vars: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"foo\";\n        console.log(a);\n        function f(b) {\n            var c;\n            console.log(b);\n            c = \"bar\";\n            console.log(c);\n        }\n        f(\"baz\");\n        var d = \"moo\";\n        console.log(d);\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(a);\n        function f(b) {\n            var b;\n            console.log(b);\n            b = \"bar\";\n            console.log(b);\n        }\n        f(\"baz\");\n        var d = \"moo\";\n        console.log(d);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n        \"moo\",\n    ]\n}\n\nmerge_toplevel: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"foo\";\n        console.log(a);\n        function f(b) {\n            var c;\n            console.log(b);\n            c = \"bar\";\n            console.log(c);\n        }\n        f(\"baz\");\n        var d = \"moo\";\n        console.log(d);\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(a);\n        function f(b) {\n            var b;\n            console.log(b);\n            b = \"bar\";\n            console.log(b);\n        }\n        f(\"baz\");\n        var a = \"moo\";\n        console.log(a);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n        \"moo\",\n    ]\n}\n\nsegment: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"foo\";\n        console.log(a);\n        for (var c, i = 0; i < 1; i++) {\n            var b = \"bar\";\n            console.log(b);\n            c = \"baz\";\n            console.log(c);\n        }\n        var d = \"moo\";\n        console.log(d);\n    }\n    expect: {\n        var a = \"foo\";\n        console.log(a);\n        for (var b, i = 0; i < 1; i++) {\n            var b = \"bar\";\n            console.log(b);\n            b = \"baz\";\n            console.log(b);\n        }\n        var a = \"moo\";\n        console.log(a);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"moo\",\n    ]\n}\n\ninit_scope_vars: {\n    options = {\n        merge_vars: true,\n        unsafe_proto: true,\n    }\n    input: {\n        Function.prototype.call();\n    }\n    expect: {\n        (function() {}).call();\n    }\n    expect_stdout: true\n}\n\nbinary_branch: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            a && (c = b);\n            return c || \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            a && (c = b);\n            return c || \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nconditional_branch: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            a ? (c = b) : void 0;\n            return c || \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            a ? (c = b) : void 0;\n            return c || \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nconditional_chain_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            var c, d;\n            if (a && (c = a))\n                console.log(c);\n            else\n                b || (d = b) ? console.log(\"foo\") : console.log(d);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect: {\n        function f(a, b) {\n            var a, a;\n            if (a && (a = a))\n                console.log(a);\n            else\n                b || (a = b) ? console.log(\"foo\") : console.log(a);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect_stdout: [\n        \"null\",\n        \"foo\",\n        \"42\",\n        \"42\",\n    ]\n}\n\nconditional_chain_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            var c, d;\n            if (a && (c = a))\n                console.log(c);\n            else\n                b || (d = b) ? console.log(c) : console.log(d);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect: {\n        function f(a, b) {\n            var c, a;\n            if (a && (c = a))\n                console.log(c);\n            else\n                b || (a = b) ? console.log(c) : console.log(a);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect_stdout: [\n        \"null\",\n        \"undefined\",\n        \"42\",\n        \"42\",\n    ]\n}\n\nconditional_chain_3: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            var c, d;\n            if (a && (c = a) || b || (d = b))\n                console.log(c);\n            else\n                console.log(d);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect: {\n        function f(a, b) {\n            var c, a;\n            if (a && (c = a) || b || (a = b))\n                console.log(c);\n            else\n                console.log(a);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect_stdout: [\n        \"null\",\n        \"undefined\",\n        \"42\",\n        \"42\",\n    ]\n}\n\nconditional_chain_4: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a, b) {\n            var c, d;\n            if (a && b ? c = a : d = b)\n                console.log(c);\n            else\n                console.log(d);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect: {\n        function f(a, b) {\n            var c, d;\n            if (a && b ? c = a : d = b)\n                console.log(c);\n            else\n                console.log(d);\n        }\n        f(\"\", null);\n        f(\"\", true);\n        f(42, null);\n        f(42, true);\n    }\n    expect_stdout: [\n        \"null\",\n        \"undefined\",\n        \"null\",\n        \"42\",\n    ]\n}\n\nif_branch: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            if (a) c = b;\n            return c || \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            if (a) c = b;\n            return c || \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nswitch_branch: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            switch (a) {\n              case 1:\n                c = b;\n                break;\n            }\n            return c || \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            switch (a) {\n              case 1:\n                c = b;\n                break;\n            }\n            return c || \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\ntry_branch: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            try {\n                a && F();\n            } catch (e) {\n                c = b;\n            }\n            return c || \"PASS\";\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            var b = \"FAIL\", c;\n            try {\n                a && F();\n            } catch (e) {\n                c = b;\n            }\n            return c || \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nread_before_assign_1: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var c = 0;\n        c = 0;\n        (function() {\n            var a = console.log(++a);\n            a;\n        })();\n        c;\n    }\n    expect: {\n        var c = 0;\n        var a;\n        c = 0,\n        a = console.log(++a);\n    }\n    expect_stdout: \"NaN\"\n}\n\nread_before_assign_2: {\n    options = {\n        dead_code: true,\n        loops: true,\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a, a) {\n            while (b)\n                return \"FAIL\";\n            var b = 1;\n            return \"PASS\";\n        }(0, []));\n    }\n    expect: {\n        console.log(function(a, a) {\n            if (b)\n                return \"FAIL\";\n            var b = 1;\n            return \"PASS\";\n        }(0, []));\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_vars_1: {\n    options = {\n        collapse_vars: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = a && a.p;\n        var b = \"PASS\";\n        var b = b && console.log(b);\n    }\n    expect: {\n        var a = a && a.p;\n        var a;\n        var a = (a = \"PASS\") && console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_vars_2: {\n    options = {\n        collapse_vars: true,\n        merge_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var log = console.log;\n        (function g(a) {\n            var b = a;\n            var c = Math.random();\n            var c = b;\n            log(c);\n            return c;\n        })(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        var log = console.log;\n        (function g(a) {\n            var a = a;\n            var c = Math.random();\n            var c;\n            log(c = a);\n            return c;\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nnot_redefined: {\n    options = {\n        inline: true,\n        join_vars: true,\n        merge_vars: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        var log = console.log;\n        (function() {\n            return f(\"PASS\");\n            function f(a) {\n                const b = a;\n                const c = log(b);\n                const d = log;\n                c && log(d);\n            }\n        })();\n    }\n    expect: {\n        var log = console.log;\n        (function() {\n            return a = \"PASS\",\n                a = log(a),\n                d = log,\n                void (a && log(d));\n            var a, d;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4103: {\n    options = {\n        merge_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a) {\n            console.log(a);\n        }\n        var b = 0;\n        var c = f(b++ + (c %= 1 >> console.log(c = 0)));\n        b;\n    }\n    expect: {\n        function f(a) {\n            console.log(a);\n        }\n        var b = 0;\n        var c = f(b++ + (c %= 1 >> console.log(c = 0)));\n    }\n    expect_stdout: [\n        \"0\",\n        \"NaN\",\n    ]\n}\n\nissue_4107_1: {\n    options = {\n        keep_fargs: false,\n        merge_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f(b, b, c) {\n                var d = 1 && a, a = console || c;\n                console.log(typeof a);\n            }\n            f();\n        })();\n        console.log(typeof a);\n    }\n    expect: {\n        (function() {\n            (function(c) {\n                c = console || c;\n                console.log(typeof c);\n            })();\n        })();\n        console.log(typeof a);\n    }\n    expect_stdout: [\n        \"object\",\n        \"undefined\",\n    ]\n}\n\nissue_4107_2: {\n    options = {\n        keep_fargs: false,\n        merge_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f(b, b, a) {\n                var d = 1 && c, c = console || a;\n                console.log(typeof c);\n            }\n            f();\n        })();\n        console.log(typeof a);\n    }\n    expect: {\n        (function() {\n            (function(a) {\n                a = console || a;\n                console.log(typeof a);\n            })();\n        })();\n        console.log(typeof a);\n    }\n    expect_stdout: [\n        \"object\",\n        \"undefined\",\n    ]\n}\n\nissue_4109: {\n    options = {\n        ie: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"foo\";\n        try {\n            throw \"bar\";\n        } catch (e) {\n            console.log(e);\n        } finally {\n            var o = a;\n            for (var k in o);\n            (function() {\n                a++;\n            });\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"foo\";\n        try {\n            throw \"bar\";\n        } catch (e) {\n            console.log(e);\n        } finally {\n            var o = a;\n            for (var k in o);\n            (function() {\n                a++;\n            });\n        }\n        console.log(a);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nissue_4110: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        while (a)\n            var c;\n        var b, a = c += b = a;\n        console.log(b);\n    }\n    expect: {\n        while (a)\n            var c;\n        var b, a = c += b = a;\n        console.log(b);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4111: {\n    options = {\n        join_vars: true,\n        loops: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        if (a)\n            a = 0;\n        else\n            for (var b = 0; --b && ++a < 2;) {\n                var o = console, k;\n                for (k in o);\n            }\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        if (a)\n            a = 0;\n        else\n            for (var b = 0; --b && ++a < 2;) {\n                var o = console, k;\n                for (k in o);\n            }\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_4112: {\n    options = {\n        functions: true,\n        merge_vars: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            try {\n                throw 42;\n            } catch (e) {\n                var o = e;\n                for (e in o);\n                var a = function() {};\n                console.log(typeof a);\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            try {\n                throw 42;\n            } catch (e) {\n                var o = e;\n                for (e in o);\n                function a() {}\n                console.log(typeof a);\n                return a;\n            }\n        }());\n    }\n    expect_stdout: [\n        \"function\",\n        \"function\",\n    ]\n}\n\nissue_4115: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        L: {\n            var o = typeof console;\n            for (var k in o)\n                break L;\n            var a = 0;\n        }\n        console.log(typeof a);\n    }\n    expect: {\n        L: {\n            var o = typeof console;\n            for (var k in o)\n                break L;\n            var a = 0;\n        }\n        console.log(typeof a);\n    }\n    expect_stdout: \"undefined\"\n}\n\ncross_branch_1_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            y = \"bar\";\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            x = \"bar\";\n            console.log(x);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            y = \"bar\";\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            x = \"bar\";\n            console.log(x);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_3: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n                x = \"bar\";\n            }\n            console.log(x);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_4: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            y = \"bar\";\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            x = \"bar\";\n            console.log(x);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_5: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_6: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_7: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_8: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a) {\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            console.log(x);\n            if (a) {\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_1_9: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            y = \"bar\";\n            if (a)\n                console.log(y);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect: {\n        var a;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            console.log(x);\n            x = \"bar\";\n            if (a)\n                console.log(x);\n        }\n        a = 0;\n        f();\n        a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                if (b)\n                    x = \"foo\";\n                console.log(x);\n            }\n            y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                if (b)\n                    x = \"foo\";\n                console.log(x);\n            }\n            x = \"bar\";\n            console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"undefined\",\n        \"bar\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                if (b)\n                    console.log(x);\n            }\n            y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                if (b)\n                    console.log(x);\n            }\n            x = \"bar\";\n            console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"bar\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_3: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                if (b)\n                    x = \"foo\";\n                console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                if (b)\n                    x = \"foo\";\n                console.log(x);\n                x = \"bar\";\n            }\n            console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"bar\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_4: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                if (b) {\n                    x = \"foo\";\n                    console.log(x);\n                }\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                if (b) {\n                    x = \"foo\";\n                    console.log(x);\n                }\n                x = \"bar\";\n            }\n            console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"bar\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_5: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                if (b)\n                    console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                if (b)\n                    console.log(x);\n                x = \"bar\";\n            }\n            console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"bar\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_6: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                if (b) {\n                    console.log(x);\n                    y = \"bar\";\n                }\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                if (b) {\n                    console.log(x);\n                    y = \"bar\";\n                }\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_7: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n                if (b)\n                    y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n                if (b)\n                    y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_8: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                if (b)\n                    console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                if (b)\n                    console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"bar\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_9: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                if (b)\n                    y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                if (b)\n                    y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_10: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                if (b)\n                    console.log(x);\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a) {\n                if (b)\n                    console.log(x);\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_11: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                if (b) {\n                    console.log(x);\n                    y = \"bar\";\n                }\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                if (b) {\n                    console.log(x);\n                    y = \"bar\";\n                }\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_12: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                if (b)\n                    y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                if (b)\n                    y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_13: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                if (b) {\n                    y = \"bar\";\n                    console.log(y);\n                }\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                if (b) {\n                    x = \"bar\";\n                    console.log(x);\n                }\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_14: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                y = \"bar\";\n                if (b)\n                    console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                x = \"bar\";\n                if (b)\n                    console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_15: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a) {\n                if (b)\n                    y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a) {\n                if (b)\n                    y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2a_16: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a) {\n                y = \"bar\";\n                if (b)\n                    console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            console.log(x);\n            if (a) {\n                x = \"bar\";\n                if (b)\n                    console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"foo\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            if (b)\n                console.log(x);\n            y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a)\n                x = \"foo\";\n            if (b)\n                console.log(x);\n            x = \"bar\";\n            console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"bar\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            if (b) {\n                console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            if (b) {\n                console.log(x);\n                y = \"bar\";\n            }\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_3: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            if (b) {\n                console.log(x);\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a)\n                x = \"foo\";\n            if (b) {\n                console.log(x);\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_4: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            if (b)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            if (b)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_5: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            if (b) {\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            if (b) {\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_6: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            if (b)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            if (b)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_7: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            if (b) {\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            if (b) {\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_8: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            y = \"bar\";\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a)\n                x = \"foo\";\n            console.log(x);\n            x = \"bar\";\n            if (b)\n                console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_9: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            y = \"bar\";\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n            }\n            x = \"bar\";\n            if (b)\n                console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_10: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n                y = \"bar\";\n            }\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            if (a) {\n                x = \"foo\";\n                console.log(x);\n                x = \"bar\";\n            }\n            if (b)\n                console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_11: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            if (b)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            if (b)\n                y = \"bar\";\n            console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"foo\",\n        \"undefined\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_12: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            if (b) {\n                y = \"bar\";\n                console.log(y);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            if (b) {\n                x = \"bar\";\n                console.log(x);\n            }\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_13: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            y = \"bar\";\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, x;\n            x = \"foo\";\n            if (a)\n                console.log(x);\n            x = \"bar\";\n            if (b)\n                console.log(x);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_14: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                y = \"bar\";\n            }\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            if (a) {\n                console.log(x);\n                y = \"bar\";\n            }\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\ncross_branch_2b_15: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a)\n                y = \"bar\";\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect: {\n        var a, b;\n        function f() {\n            var x, y;\n            x = \"foo\";\n            console.log(x);\n            if (a)\n                y = \"bar\";\n            if (b)\n                console.log(y);\n        }\n        a = 0, b = 0;\n        f();\n        a = 1, b = 0;\n        f();\n        a = 0, b = 1;\n        f();\n        a = 1, b = 1;\n        f();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n        \"foo\",\n        \"undefined\",\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_4126_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            try {\n                console.log(\"PASS\");\n            } catch (e) {\n                var b = a;\n            } finally {\n                var c = b;\n            }\n            console.log(c);\n        }\n        f(\"FAIL\");\n    }\n    expect: {\n        function f(a) {\n            try {\n                console.log(\"PASS\");\n            } catch (e) {\n                var b = a;\n            } finally {\n                var a = b;\n            }\n            console.log(a);\n        }\n        f(\"FAIL\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n}\n\nissue_4126_2: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            var a = function() {\n                var b = 0;\n                function f() {\n                    b;\n                }\n                THROW(b);\n            }();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            var a = (b = 0, void THROW(b));\n        } catch (e) {\n            console.log(a);\n        }\n        function f() {}\n        var b;\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4130: {\n    options = {\n        merge_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 2;\n        while (a)\n            try {\n                console.log(a);\n            } catch (e) {\n                var b = 0;\n            } finally {\n                b && console.log(\"FAIL\");\n                var c = --a;\n                for (var k in c)\n                    c;\n            }\n    }\n    expect: {\n        var a = 2;\n        while (a)\n            try {\n                console.log(a);\n            } catch (e) {\n                var b = 0;\n            } finally {\n                b && console.log(\"FAIL\");\n                var c = --a;\n                for (var k in c);\n            }\n    }\n    expect_stdout: [\n        \"2\",\n        \"1\",\n    ]\n}\n\nissue_4135: {\n    options = {\n        evaluate: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        --b;\n        a++;\n        if (!a)\n            var c = function() {\n                var d = 0;\n                function f() {\n                    d && d.p;\n                }\n                f();\n                this;\n            }(a++);\n        console.log(a, b, c);\n    }\n    expect: {\n        var a = 0;\n        0;\n        a++;\n        if (!a)\n            var c = void a++;\n        console.log(a, -1, c);\n    }\n    expect_stdout: \"1 -1 undefined\"\n}\n\nissue_4139: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            console.log;\n        } catch (e) {\n            var a, arguments = 0;\n        } finally {\n            a = typeof arguments;\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            console.log;\n        } catch (e) {\n            var a, arguments = 0;\n        } finally {\n            a = typeof arguments;\n            console.log(a);\n        }\n    }\n    expect_stdout: \"object\"\n}\n\nlambda_reuse: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b, f = function() {\n            console.log(a);\n        };\n        f();\n        a = \"PASS\";\n        b = \"FAIL\";\n        f();\n        if (console.log(typeof b))\n            console.log(b);\n    }\n    expect: {\n        var a, b, f = function() {\n            console.log(a);\n        };\n        f();\n        a = \"PASS\";\n        b = \"FAIL\";\n        f();\n        if (console.log(typeof b))\n            console.log(b);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"PASS\",\n        \"string\",\n    ]\n}\n\nconditional_write: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\", b;\n        if (console)\n            a = \"PASS\";\n        b = [a, 42].join();\n        console.log(b);\n    }\n    expect: {\n        var a = \"FAIL\", a;\n        if (console)\n            a = \"PASS\";\n        a = [a, 42].join();\n        console.log(a);\n    }\n    expect_stdout: \"PASS,42\"\n}\n\nissue_4155: {\n    options = {\n        inline: true,\n        merge_vars: true,\n    }\n    input: {\n        (function() {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                var a;\n                (function() {\n                    console.log(e, a);\n                })(a = NaN);\n            }\n            var e = function() {};\n            e && console.log(typeof e);\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                throw \"PASS\";\n            } catch (e) {\n                var a;\n                a = NaN,\n                void console.log(e, a);\n            }\n            var e = function() {};\n            e && console.log(typeof e);\n        })();\n    }\n    expect_stdout: [\n        \"PASS NaN\",\n        \"function\",\n    ]\n}\n\nissue_4157_1: {\n    options = {\n        dead_code: true,\n        loops: true,\n        merge_vars: true,\n    }\n    input: {\n        (function() {\n            try {\n                for (var a = \"FAIL\"; a; a++)\n                    return;\n                var b = 0;\n            } finally {\n                console.log(b);\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                var a = \"FAIL\";\n                if (a)\n                    return;\n                var b = 0;\n            } finally {\n                console.log(b);\n            }\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4157_2: {\n    options = {\n        dead_code: true,\n        loops: true,\n        merge_vars: true,\n    }\n    input: {\n        (function() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                for (var a = e; a; a++)\n                    return;\n                var b = 0;\n            } finally {\n                console.log(b);\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                throw \"FAIL\";\n            } catch (e) {\n                var a = e;\n                if (a)\n                    return;\n                var b = 0;\n            } finally {\n                console.log(b);\n            }\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4168: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        var o = {\n            f: function(a, b, c) {\n                var d = a.d;\n                var e = b.e;\n                var f = c.f;\n                this.g(arguments);\n                if (d)\n                    console.log(e, f);\n            },\n            g: function(args) {\n                console.log(args[0], args[1], args[2]);\n            },\n        };\n        o.f(\"PASS\", true, 42);\n    }\n    expect: {\n        var o = {\n            f: function(a, b, c) {\n                var d = a.d;\n                var e = b.e;\n                var f = c.f;\n                this.g(arguments);\n                if (d)\n                    console.log(e, f);\n            },\n            g: function(args) {\n                console.log(args[0], args[1], args[2]);\n            },\n        };\n        o.f(\"PASS\", true, 42);\n    }\n    expect_stdout: \"PASS true 42\"\n}\n\nissue_4168_use_strict: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        \"use strict\";\n        var o = {\n            f: function(a, b, c) {\n                var d = a.d;\n                var e = b.e;\n                var f = c.f;\n                this.g(arguments);\n                if (d)\n                    console.log(e, f);\n            },\n            g: function(args) {\n                console.log(args[0], args[1], args[2]);\n            },\n        };\n        o.f(\"PASS\", true, 42);\n    }\n    expect: {\n        \"use strict\";\n        var o = {\n            f: function(a, b, c) {\n                var a = a.d;\n                var b = b.e;\n                var c = c.f;\n                this.g(arguments);\n                if (a)\n                    console.log(b, c);\n            },\n            g: function(args) {\n                console.log(args[0], args[1], args[2]);\n            },\n        };\n        o.f(\"PASS\", true, 42);\n    }\n    expect_stdout: \"PASS true 42\"\n}\n\nissue_4237_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            do {\n                var b = a++;\n                if (b)\n                    return \"FAIL\";\n                continue;\n                var c = 42;\n            } while (\"undefined\" != typeof c);\n            return \"PASS\";\n        }(0));\n    }\n    expect: {\n        console.log(function(a) {\n            do {\n                var b = a++;\n                if (b)\n                    return \"FAIL\";\n                continue;\n                var c = 42;\n            } while (\"undefined\" != typeof c);\n            return \"PASS\";\n        }(0));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4237_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        merge_vars: true,\n        switches: true,\n    }\n    input: {\n        console.log(function(a) {\n            do {\n                switch (0) {\n                  case 0:\n                    var b = a++;\n                  default:\n                    while (b)\n                        return \"FAIL\";\n                }\n                try {\n                    var c = 0;\n                } finally {\n                    continue;\n                }\n                var d = 0;\n            } while (\"undefined\" != typeof d);\n            return \"PASS\";\n        }(0));\n    }\n    expect: {\n        console.log(function(a) {\n            do {\n                switch (0) {\n                  default:\n                    var b = a++;\n                    if (b)\n                        return \"FAIL\";\n                }\n                try {\n                    var c = 0;\n                } finally {\n                    continue;\n                }\n                var d = 0;\n            } while (\"undefined\" != typeof d);\n            return \"PASS\";\n        }(0));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4253: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        switch (0) {\n          default:\n            var a = \"FAIL\";\n            a = a && a;\n            try {\n                break;\n            } catch (e) {}\n            var b = 42;\n        }\n        console.log(b);\n    }\n    expect: {\n        switch (0) {\n          default:\n            var a = \"FAIL\";\n            a = a && a;\n            try {\n                break;\n            } catch (e) {}\n            var b = 42;\n        }\n        console.log(b);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4255: {\n    options = {\n        dead_code: true,\n        loops: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        L: for (var a = 2; --a;)\n            for (var b = 0; console.log(b); --b)\n                break L;\n    }\n    expect: {\n        L: for (var a = 2; --a;) {\n            var b = 0;\n            if (console.log(b))\n                break L;\n        }\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4257: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        for (var i = 0; i < 2; i++)\n            switch (--a) {\n              case 0:\n                var b = 0;\n                break;\n              case 0:\n              default:\n                var c = 1 + (0 | (b && A));\n                console.log(c);\n            }\n    }\n    expect: {\n        var a = 0;\n        for (var i = 0; i < 2; i++)\n            switch (--a) {\n              case 0:\n                var b = 0;\n                break;\n              case 0:\n              default:\n                var c = 1 + (0 | (b && A));\n                console.log(c);\n            }\n    }\n    expect_stdout: [\n        \"1\",\n        \"1\",\n    ]\n}\n\nissue_4628: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function() {\n            try {\n                console;\n            } finally {\n                var b = a;\n            }\n            for (var a in \"foo\");\n            console.log(b);\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                console;\n            } finally {\n                var b = a;\n            }\n            for (var a in \"foo\");\n            console.log(b);\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4653: {\n    options = {\n        evaluate: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1, b;\n        function f(c, d) {\n            c || console.log(d);\n        }\n        f(a++ + (b = b), b |= console.log(a));\n    }\n    expect: {\n        var b, a = 1;\n        (function(c, d) {\n            c || console.log(d);\n        })(+a + (b = b), b |= console.log(2));\n    }\n    expect_stdout: [\n        \"2\",\n        \"0\",\n    ]\n}\n\nissue_4759: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var i = 2, a = 1, b, c, d;\n        while (i--) {\n            try {\n                if (1 != b) {\n                    d = [];\n                    null.p;\n                    c = d;\n                } else {\n                    b = 0;\n                    a = c;\n                }\n            } catch (e) {}\n            b = a;\n        }\n        console.log(a);\n    }\n    expect: {\n        var i = 2, a = 1, b, c, d;\n        while (i--) {\n            try {\n                if (1 != b) {\n                    d = [];\n                    null.p;\n                    c = d;\n                } else {\n                    b = 0;\n                    a = c;\n                }\n            } catch (e) {}\n            b = a;\n        }\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4761: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\", b;\n        try {\n            !a && --a && (b = 0)[console] || console.log(b);\n        } catch (e) {}\n    }\n    expect: {\n        var a = \"FAIL\", b;\n        try {\n            !a && --a && (b = 0)[console] || console.log(b);\n        } catch (e) {}\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4956_1: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b;\n        function f(c) {\n            switch (c) {\n              case 0:\n                a = { p: 42 };\n\n              case 1:\n                b = a.p;\n                console.log(b);\n            }\n        }\n        f(0);\n        f(1);\n    }\n    expect: {\n        var a, b;\n        function f(c) {\n            switch (c) {\n              case 0:\n                a = { p: 42 };\n\n              case 1:\n                b = a.p;\n                console.log(b);\n            }\n        }\n        f(0);\n        f(1);\n    }\n    expect_stdout: [\n        \"42\",\n        \"42\",\n    ]\n}\n\nissue_4956_2: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b;\n        function f(c) {\n            if (0 == c) {\n                console;\n                a = { p: 42 };\n            }\n            b = a.p;\n            if (1 == c)\n                console.log(b);\n        }\n        f(0);\n        f(1);\n    }\n    expect: {\n        var a, b;\n        function f(c) {\n            if (0 == c) {\n                console;\n                a = { p: 42 };\n            }\n            b = a.p;\n            if (1 == c)\n                console.log(b);\n        }\n        f(0);\n        f(1);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5182: {\n    options = {\n        arrows: true,\n        collapse_vars: true,\n        evaluate: true,\n        hoist_props: true,\n        inline: true,\n        merge_vars: true,\n        passes: 4,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            var con = console;\n        } catch (x) {}\n        global.log = con.log;\n        var jump = function(x) {\n            console.log(\"JUMP:\", x * 10);\n            return x + x;\n        };\n        var jump2 = jump;\n        var run = function(x) {\n            console.log(\"RUN:\", x * -10);\n            return x * x;\n        };\n        var run2 = run;\n        var bar = (x, y) => {\n            console.log(\"BAR:\", x + y);\n            return x - y;\n        };\n        var bar2 = bar;\n        var obj = {\n            foo: bar2,\n            go: run2,\n            not_used: jump2,\n        };\n        console.log(obj.foo(1, 2), global.log(\"PASS\"));\n    }\n    expect: {\n        try {\n            var con = console;\n        } catch (x) {}\n        global.log = con.log,\n        console.log((console.log(\"BAR:\", 3), -1), global.log(\"PASS\"));\n    }\n    expect_stdout: [\n        \"BAR: 3\",\n        \"PASS\",\n        \"-1 undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5420: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        do {\n            var a = \"FAIL 1\";\n            a && a.p;\n            a = \"FAIL 2\";\n            try {\n                continue;\n            } catch (e) {}\n            var b = \"FAIL 3\";\n        } while (console.log(b || \"PASS\"));\n    }\n    expect: {\n        do {\n            var a = \"FAIL 1\";\n            a && a.p;\n            a = \"FAIL 2\";\n            try {\n                continue;\n            } catch (e) {}\n            var b = \"FAIL 3\";\n        } while (console.log(b || \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5451: {\n    options = {\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        A = 1;\n        var a = 1, b;\n        console.log(function f() {\n            return a-- && f(b = A, b);\n        }());\n    }\n    expect: {\n        A = 1;\n        var a = 1, b;\n        console.log(function f() {\n            return a-- && f(b = A, b);\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nissue_5471_1: {\n    options = {\n        conditionals: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL 1\";\n        function f(b, c) {\n            function g() {\n                if (console)\n                    return 42;\n                else\n                    c = \"FAIL 2\";\n            }\n            var d = g();\n            console.log(c || \"PASS\");\n            var e = function h() {\n                while (b && e);\n            }();\n        }\n        f(a++) && a;\n    }\n    expect: {\n        var a = \"FAIL 1\";\n        var b, c, e;\n        b = +a,\n        function() {\n            if (console)\n                return;\n            c = \"FAIL 2\";\n        }(),\n        console.log(c || \"PASS\"),\n        e = function() {\n            while (b && e);\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5471_2: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL 1\";\n        function f(b, c) {\n            function g() {\n                if (console)\n                    return 42;\n                else\n                    c = \"FAIL 2\";\n            }\n            var d = g();\n            console.log(c || \"PASS\");\n            var e = function h() {\n                while (b && e);\n            }();\n        }\n        f(a++) && a;\n    }\n    expect: {\n        var a = \"FAIL 1\";\n        var b, c, e;\n        b = +a,\n        function() {\n            if (console)\n                return;\n            c = \"FAIL 2\";\n        }(),\n        console.log(c || \"PASS\"),\n        e = function() {\n            while (b && e);\n        }(),\n        void 0;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5714: {\n    options = {\n        inline: true,\n        join_vars: true,\n        loops: true,\n        merge_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function() {\n            var i = 1;\n            while (i--) {\n                var a = function f(b) {\n                    console.log(b);\n                    var c = function(d) {\n                        console.log(typeof d);\n                    }(console);\n                }();\n                var e = 42;\n            }\n            return e;\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            for (var i = 1; i--;) {\n                var b = void 0;\n                console.log(b);\n                b = console,\n                console.log(typeof b);\n                var e = 42;\n            }\n            return e;\n        }());\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"object\",\n        \"42\",\n    ]\n}\n\nissue_5770_1: {\n    options = {\n        dead_code: true,\n        loops: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        L: do {\n            if (console)\n                for (var a = \"FAIL 1\"; a; a--)\n                    continue L;\n            var b = \"FAIL 2\";\n        } while (console.log(b || \"PASS\"));\n    }\n    expect: {\n        L: do {\n            if (console) {\n                var a = \"FAIL 1\";\n                if (a)\n                    continue L;\n            }\n            var b = \"FAIL 2\";\n        } while (console.log(b || \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5770_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        if_return: true,\n        loops: true,\n        merge_vars: true,\n        toplevel: true,\n    }\n    input: {\n        L: do {\n            for (var a = \"FAIL 1\"; a; a--)\n                continue L;\n            var b = \"FAIL 2\";\n        } while (console.log(b || \"PASS\"));\n    }\n    expect: {\n        L: do {\n            var a = \"FAIL 1\";\n            var b;\n        } while (a || (b = \"FAIL 2\"), console.log(b || \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5772_1: {\n    options = {\n        dead_code: true,\n        merge_vars: true,\n        loops: true,\n    }\n    input: {\n        (function(a) {\n            while (--a)\n                return;\n            var b = console.log(\"foo\") && (c = 42) ? 0 : console.log(c);\n            var c = b;\n        })();\n    }\n    expect: {\n        (function(a) {\n            if (--a)\n                return;\n            var a = console.log(\"foo\") && (c = 42) ? 0 : console.log(c);\n            var c = a;\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n}\n\nissue_5772_2: {\n    options = {\n        dead_code: true,\n        merge_vars: true,\n        loops: true,\n    }\n    input: {\n        (function(a) {\n            while (--a)\n                return;\n            var b;\n            var c = console.log(\"foo\") && (b = 1) ? 2 : 3;\n            console.log(b, c);\n        })();\n    }\n    expect: {\n        (function(a) {\n            if (--a)\n                return;\n            var b;\n            var a = console.log(\"foo\") && (b = 1) ? 2 : 3;\n            console.log(b, a);\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined 3\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/negate-iife.js",
    "content": "negate_iife_1: {\n    options = {\n        negate_iife: true,\n    }\n    input: {\n        (function(){ stuff() })();\n    }\n    expect: {\n        !function(){ stuff() }();\n    }\n}\n\nnegate_iife_1_off: {\n    options = {\n        negate_iife: false,\n    }\n    input: {\n        (function(){ stuff() })();\n    }\n    expect_exact: '(function(){stuff()})();'\n}\n\nnegate_iife_2: {\n    options = {\n        inline: true,\n        negate_iife: true,\n    }\n    input: {\n        (function(){ return {} })().x = 10;\n    }\n    expect_exact: \"({}).x=10;\"\n}\n\nnegate_iife_2_side_effects: {\n    options = {\n        inline: true,\n        negate_iife: true,\n        side_effects: true,\n    }\n    input: {\n        (function(){ return {} })().x = 10;\n    }\n    expect_exact: \"({}).x=10;\"\n}\n\nnegate_iife_3: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        !function(){ return t }() ? console.log(false) : console.log(true);\n    }\n}\n\nnegate_iife_3_evaluate: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        negate_iife: true,\n    }\n    input: {\n        (function(){ return true })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        true, console.log(true);\n    }\n    expect_stdout: true\n}\n\nnegate_iife_3_side_effects: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        side_effects: true,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        !function(){ return t }() ? console.log(false) : console.log(true);\n    }\n}\n\nnegate_iife_3_off: {\n    options = {\n        conditionals: true,\n        negate_iife: false,\n    }\n    input: {\n        (function(){ return t })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        !function(){ return t }() ? console.log(false) : console.log(true);\n    }\n}\n\nnegate_iife_3_off_evaluate: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        negate_iife: false,\n    }\n    input: {\n        (function(){ return true })() ? console.log(true) : console.log(false);\n    }\n    expect: {\n        true, console.log(true);\n    }\n    expect_stdout: true\n}\n\nnegate_iife_4: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        (function() {\n            return t;\n        })() ? console.log(true) : console.log(false);\n        (function() {\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function() {\n            return t;\n        }() ? console.log(false) : console.log(true), !function() {\n            console.log(\"something\");\n        }();\n    }\n}\n\nnegate_iife_4_drop_side_effect_free: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            return t;\n        })() ? console.log(true) : console.log(false);\n        (function() {\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function() {\n            return t;\n        }() ? console.log(false) : console.log(true), function() {\n            console.log(\"something\");\n        }();\n    }\n}\n\nsequence_off: {\n    options = {\n        conditionals: true,\n        negate_iife: false,\n        passes: 2,\n        sequences: true,\n    }\n    input: {\n        function f() {\n            (function(){ return t })() ? console.log(true) : console.log(false);\n            (function(){\n                console.log(\"something\");\n            })();\n        }\n        function g() {\n            (function(){\n                console.log(\"something\");\n            })();\n            (function(){ return t })() ? console.log(true) : console.log(false);\n        }\n    }\n    expect: {\n        function f() {\n            !function(){ return t }() ? console.log(false) : console.log(true), function(){\n                console.log(\"something\");\n            }();\n        }\n        function g() {\n            (function(){\n                console.log(\"something\");\n            })(), function(){ return t }() ? console.log(true) : console.log(false);\n        }\n    }\n}\n\nnegate_iife_5: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        if (function() {\n            return t;\n        }()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function() {\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function() {\n            return t;\n        }() ? bar(false) : foo(true), !function() {\n            console.log(\"something\");\n        }();\n    }\n}\n\nnegate_iife_5_drop_side_effect_free: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        if (function() {\n            return t;\n        }()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function() {\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function() {\n            return t;\n        }() ? bar(false) : foo(true), function() {\n            console.log(\"something\");\n        }();\n    }\n}\n\nnegate_iife_5_off: {\n    options = {\n        conditionals: true,\n        negate_iife: false,\n        sequences: true,\n    }\n    input: {\n        if ((function(){ return t })()) {\n            foo(true);\n        } else {\n            bar(false);\n        }\n        (function(){\n            console.log(\"something\");\n        })();\n    }\n    expect: {\n        !function(){ return t }() ? bar(false) : foo(true), function(){\n            console.log(\"something\");\n        }();\n    }\n}\n\nnegate_iife_nested: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        function Foo(f) {\n            this.f = f;\n        }\n        new Foo(function() {\n            (function(x) {\n                (function(y) {\n                    console.log(y);\n                })(x);\n            })(7);\n        }).f();\n    }\n    expect: {\n        function Foo(f) {\n            this.f = f;\n        }\n        new Foo(function() {\n            !function(x) {\n                !function(y) {\n                    console.log(y);\n                }(x);\n            }(7);\n        }).f();\n    }\n    expect_stdout: true\n}\n\nnegate_iife_nested_off: {\n    options = {\n        conditionals: true,\n        negate_iife: false,\n        sequences: true,\n    }\n    input: {\n        function Foo(f) {\n            this.f = f;\n        }\n        new Foo(function() {\n            (function(x) {\n                (function(y) {\n                    console.log(y);\n                })(x);\n            })(7);\n        }).f();\n    }\n    expect: {\n        function Foo(f) {\n            this.f = f;\n        }\n        new Foo(function() {\n            (function(x) {\n                (function(y) {\n                    console.log(y);\n                })(x);\n            })(7);\n        }).f();\n    }\n    expect_stdout: true\n}\n\nnegate_iife_issue_1073: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        new (function(a) {\n            return function Foo() {\n                this.x = a;\n                console.log(this);\n            };\n        }(7))();\n    }\n    expect: {\n        new (function(a) {\n            return function Foo() {\n                this.x = a,\n                console.log(this);\n            };\n        }(7))();\n    }\n    expect_stdout: true\n}\n\nissue_1254_negate_iife_false: {\n    options = {\n        negate_iife: false,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()();\n    }\n    expect_exact: '(function(){return function(){console.log(\"test\")}})()();'\n    expect_stdout: true\n}\n\nissue_1254_negate_iife_true: {\n    options = {\n        negate_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()();\n    }\n    expect_exact: '!function(){return function(){console.log(\"test\")}}()();'\n    expect_stdout: true\n}\n\nissue_1254_negate_iife_nested: {\n    options = {\n        negate_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()()()()();\n    }\n    expect_exact: '!function(){return function(){console.log(\"test\")}}()()()()();'\n    expect_stdout: true\n}\n\nissue_1288: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        side_effects: false,\n    }\n    input: {\n        if (w) ;\n        else {\n            (function f() {})();\n        }\n        if (!x) {\n            (function() {\n                x = {};\n            })();\n        }\n        if (y)\n            (function() {})();\n        else\n            (function(z) {\n                return z;\n            })(0);\n    }\n    expect: {\n        w || !function f() {}();\n        x || !function() {\n            x = {};\n        }();\n        y ? !function() {}() : !function(z) {\n            return z;\n        }(0);\n    }\n}\n\nissue_1288_side_effects: {\n    options = {\n        conditionals: true,\n        negate_iife: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        if (w) ;\n        else {\n            (function f() {})();\n        }\n        if (!x) {\n            (function() {\n                x = {};\n            })();\n        }\n        if (y)\n            (function() {})();\n        else\n            (function(z) {\n                return z;\n            })(0);\n    }\n    expect: {\n        w,\n        x || function() {\n            x = {};\n        }(),\n        y;\n    }\n}\n"
  },
  {
    "path": "test/compress/new.js",
    "content": "new_statement: {\n    input: {\n        new x(1);\n        new x(1)(2);\n        new x(1)(2)(3);\n        new new x(1);\n        new new x(1)(2);\n        new (new x(1))(2);\n        (new new x(1))(2);\n    }\n    expect_exact: \"new x(1);new x(1)(2);new x(1)(2)(3);new new x(1);new new x(1)(2);new new x(1)(2);(new new x(1))(2);\"\n}\n\nnew_statements_2: {\n    input: {\n        new x;\n        new new x;\n        new new new x;\n        new true;\n        new (0);\n        new (!0);\n        new (bar = function(foo) {this.foo=foo;})(123);\n        new (bar = function(foo) {this.foo=foo;})();\n    }\n    expect_exact: \"new x;new(new x);new(new(new x));new true;new 0;new(!0);new(bar=function(foo){this.foo=foo})(123);new(bar=function(foo){this.foo=foo});\"\n}\n\nnew_statements_3: {\n    input: {\n        new (function(foo){this.foo=foo;})(1);\n        new (function(foo){this.foo=foo;})();\n        new (function test(foo){this.foo=foo;})(1);\n        new (function test(foo){this.foo=foo;})();\n    }\n    expect_exact: \"new function(foo){this.foo=foo}(1);new function(foo){this.foo=foo};new function test(foo){this.foo=foo}(1);new function test(foo){this.foo=foo};\"\n}\n\nnew_with_rewritten_true_value: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        new true;\n    }\n    expect_exact: \"new(!0);\"\n}\n\nnew_with_many_parameters: {\n    input: {\n        new foo.bar(\"baz\");\n        new x(/123/, 456);\n    }\n    expect_exact: 'new foo.bar(\"baz\");new x(/123/,456);'\n}\n\nnew_constructor_with_unary_arguments: {\n    input: {\n        new x();\n        new x(-1);\n        new x(-1, -2);\n        new x(void 1, +2, -3, ~4, !5, --a, ++b, c--, d++, typeof e, delete f);\n        new (-1);     // should parse despite being invalid at runtime.\n        new (-1)();   // should parse despite being invalid at runtime.\n        new (-1)(-2); // should parse despite being invalid at runtime.\n    }\n    expect_exact: \"new x;new x(-1);new x(-1,-2);new x(void 1,+2,-3,~4,!5,--a,++b,c--,d++,typeof e,delete f);new(-1);new(-1);new(-1)(-2);\"\n}\n\ncall_with_unary_arguments: {\n    input: {\n        x();\n        x(-1);\n        x(-1, -2);\n        x(void 1, +2, -3, ~4, !5, --a, ++b, c--, d++, typeof e, delete f);\n        (-1)();   // should parse despite being invalid at runtime.\n        (-1)(-2); // should parse despite being invalid at runtime.\n    }\n    expect_exact: \"x();x(-1);x(-1,-2);x(void 1,+2,-3,~4,!5,--a,++b,c--,d++,typeof e,delete f);(-1)();(-1)(-2);\"\n}\n\nnew_with_unary_prefix: {\n    input: {\n        var bar = (+new Date()).toString(32);\n    }\n    expect_exact: 'var bar=(+new Date).toString(32);';\n}\n\ndot_parentheses_1: {\n    input: {\n        console.log(new (Math.random().constructor) instanceof Number);\n    }\n    expect_exact: \"console.log(new(Math.random().constructor)instanceof Number);\"\n    expect_stdout: \"true\"\n}\n\ndot_parentheses_2: {\n    input: {\n        console.log(typeof new function(){Math.random()}.constructor);\n    }\n    expect_exact: \"console.log(typeof new function(){Math.random()}.constructor);\"\n    expect_stdout: \"function\"\n}\n"
  },
  {
    "path": "test/compress/node_version.js",
    "content": "eval_let_6: {\n    input: {\n        eval(\"let a;\");\n        console.log();\n    }\n    expect: {\n        eval(\"let a;\");\n        console.log();\n    }\n    expect_stdout: \"\"\n    node_version: \">=6\"\n}\n\neval_let_4: {\n    input: {\n        eval(\"let a;\");\n        console.log();\n    }\n    expect: {\n        eval(\"let a;\");\n        console.log();\n    }\n    expect_stdout: SyntaxError(\"Block-scoped declarations (let, const, function, class) not yet supported outside strict mode\")\n    node_version: \"4\"\n}\n\neval_let_0: {\n    input: {\n        eval(\"let a;\");\n        console.log();\n    }\n    expect: {\n        eval(\"let a;\");\n        console.log();\n    }\n    expect_stdout: SyntaxError(\"Unexpected identifier\")\n    node_version: \"<=0.12\"\n}\n"
  },
  {
    "path": "test/compress/nullish.js",
    "content": "parentheses: {\n    input: {\n        (console.log(\"foo\") || console.log(\"bar\") ?? console.log(\"baz\")) && console.log(\"moo\");\n    }\n    expect_exact:'((console.log(\"foo\")||console.log(\"bar\"))??console.log(\"baz\"))&&console.log(\"moo\");'\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=14\"\n}\n\nevaluate: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        void console.log(\"foo\" ?? \"bar\") ?? console.log(\"baz\");\n    }\n    expect: {\n        console.log(\"foo\"),\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n    ]\n    node_version: \">=14\"\n}\n\nconditional_assignment_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        console.log(function(a, b) {\n            b ?? (a = \"FAIL\");\n            return a;\n        }(\"PASS\", !console));\n    }\n    expect: {\n        console.log(function(a, b) {\n            b ?? (a = \"FAIL\");\n            return a;\n        }(\"PASS\", !console));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nconditional_assignment_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a, b = false;\n        a = \"PASS\",\n        b ?? (a = \"FAIL\"),\n        console.log(a);\n    }\n    expect: {\n        var a, b = false;\n        a = \"PASS\",\n        b ?? (a = \"FAIL\"),\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nconditional_assignment_3: {\n    options = {\n        conditionals: true,\n        join_vars: true,\n    }\n    input: {\n        var a, b = false;\n        a = \"PASS\",\n        b ?? (a = \"FAIL\"),\n        console.log(a);\n    }\n    expect: {\n        var a, b = false, a = \"PASS\";\n        b ?? (a = \"FAIL\"),\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nconditional_assignment_4: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console.log(function(a) {\n            !console ?? (a = \"FAIL\");\n            return a;\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(function(a) {\n            !console ?? (a = \"FAIL\");\n            return a;\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nde_morgan_1: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        function f(a) {\n            return a ?? a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect: {\n        function f(a) {\n            return a;\n        }\n        console.log(f(null), f(42));\n    }\n    expect_stdout: \"null 42\"\n    node_version: \">=14\"\n}\n\nde_morgan_2a: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b) {\n            return a || (a ?? b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a || (a ?? b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"undefined {}\",\n        \"42 42\",\n    ]\n    node_version: \">=14\"\n}\n\nde_morgan_2b: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b) {\n            return a && (a ?? b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"null null\",\n        \"42 42\",\n    ]\n    node_version: \">=14\"\n}\n\nde_morgan_2c: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            return a ?? (a || b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a ?? b;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"undefined {}\",\n        \"42 42\",\n    ]\n    node_version: \">=14\"\n}\n\nde_morgan_2d: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        function f(a, b) {\n            return a ?? (a && b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"null null\",\n        \"42 42\",\n    ]\n    node_version: \">=14\"\n}\n\nde_morgan_2e: {\n    options = {\n        booleans: true,\n        conditionals: true,\n    }\n    input: {\n        function f(a, b) {\n            return a ?? (a ?? b);\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect: {\n        function f(a, b) {\n            return a ?? b;\n        }\n        console.log(f(null), f(null, {}));\n        console.log(f(42), f(42, {}));\n    }\n    expect_stdout: [\n        \"undefined {}\",\n        \"42 42\",\n    ]\n    node_version: \">=14\"\n}\n\ninline_binary_nullish: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function() {\n            while (console.log(\"foo\"));\n        })() ?? (function() {\n            while (console.log(\"bar\"));\n        })();\n    }\n    expect: {\n        if (null == function() {\n            while (console.log(\"foo\"));\n        }())\n            while (console.log(\"bar\"));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=14\"\n}\n\nissue_4679: {\n    options = {\n        comparisons: true,\n        ie: true,\n    }\n    input: {\n        var a;\n        if (void 0 === (undefined ?? a))\n            console.log(\"PASS\");\n    }\n    expect: {\n        var a;\n        if (void 0 === (undefined ?? a))\n            console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5266: {\n    options = {\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        [\n            42,\n            null,\n            false,\n            void 0,\n            \"FAIL\",\n        ].forEach(function (a) {\n            a ?? function() {\n                while (console.log(a));\n            }();\n        });\n    }\n    expect: {\n        [\n            42,\n            null,\n            false,\n            void 0,\n            \"FAIL\",\n        ].forEach(function (a) {\n            if (null == a) {\n                while (console.log(a));\n                return;\n            } else\n                return;\n        });\n    }\n    expect_stdout: [\n        \"null\",\n        \"undefined\",\n    ]\n    node_version: \">=14\"\n}\n\nissue_5829_1: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function f(a) {\n            var b;\n            (!a ?? (b = 0)) || console.log(b || \"PASS\");\n        })(\"FAIL\");\n    }\n    expect: {\n        (function f(a) {\n            var b;\n            (!a ?? (b = 0)) || console.log(b || \"PASS\");\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5829_2: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function f(a) {\n            var b;\n            (a ?? (b = 0)) && console.log(b || \"PASS\");\n        })(\"FAIL\");\n    }\n    expect: {\n        (function f(a) {\n            var b;\n            (a ?? (b = 0)) && console.log(b || \"PASS\");\n        })(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n"
  },
  {
    "path": "test/compress/numbers.js",
    "content": "literal_infinity: {\n    input: {\n        console.log(2e308, -1e2345);\n    }\n    expect_exact: \"console.log(1/0,-(1/0));\"\n}\n\nparentheses_for_prototype_functions: {\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        (function() {\n            console.log((-2));\n            console.log((-2).toFixed(0));\n\n            console.log((2));\n            console.log((2).toFixed(0));\n\n            console.log((0.2));\n            console.log((0.2).toFixed(0));\n\n            console.log((2.34e20));\n            console.log((2.34e20).toFixed(0));\n\n            console.log((0.00000002));\n            console.log((0.00000002).toFixed(0));\n\n            console.log((1000000000000000128));\n            console.log((1000000000000000128).toFixed(0));\n\n            console.log((-1000000000000000128));\n            console.log((-1000000000000000128).toFixed(0));\n        })();\n    }\n    expect_exact: [\n        \"(function() {\",\n        \"    console.log(-2);\",\n        \"    console.log((-2).toFixed(0));\",\n        \"    console.log(2);\",\n        \"    console.log(2..toFixed(0));\",\n        \"    console.log(.2);\",\n        \"    console.log(.2.toFixed(0));\",\n        \"    console.log(234e18);\",\n        \"    console.log(234e18.toFixed(0));\",\n        \"    console.log(2e-8);\",\n        \"    console.log(2e-8.toFixed(0));\",\n        \"    console.log(0xde0b6b3a7640080);\",\n        \"    console.log(0xde0b6b3a7640080.toFixed(0));\",\n        \"    console.log(-0xde0b6b3a7640080);\",\n        \"    console.log((-0xde0b6b3a7640080).toFixed(0));\",\n        \"})();\",\n    ]\n    expect_stdout: true\n}\n\nparentheses_for_prototype_functions_galio: {\n    beautify = {\n        beautify: true,\n        galio: true,\n    }\n    input: {\n        (function() {\n            console.log((-2));\n            console.log((-2).toFixed(0));\n\n            console.log((2));\n            console.log((2).toFixed(0));\n\n            console.log((0.2));\n            console.log((0.2).toFixed(0));\n\n            console.log((2.34e20));\n            console.log((2.34e20).toFixed(0));\n\n            console.log((0.00000002));\n            console.log((0.00000002).toFixed(0));\n\n            console.log((1000000000000000128));\n            console.log((1000000000000000128).toFixed(0));\n\n            console.log((-1000000000000000128));\n            console.log((-1000000000000000128).toFixed(0));\n        })();\n    }\n    expect_exact: [\n        \"(function() {\",\n        \"    console.log(-2);\",\n        \"    console.log((-2).toFixed(0));\",\n        \"    console.log(2);\",\n        \"    console.log(2..toFixed(0));\",\n        \"    console.log(.2);\",\n        \"    console.log(.2.toFixed(0));\",\n        \"    console.log(234e18);\",\n        \"    console.log(234e18.toFixed(0));\",\n        \"    console.log(2e-8);\",\n        \"    console.log(2e-8.toFixed(0));\",\n        \"    console.log(0xde0b6b3a7640080);\",\n        \"    console.log((0xde0b6b3a7640080).toFixed(0));\",\n        \"    console.log(-0xde0b6b3a7640080);\",\n        \"    console.log((-0xde0b6b3a7640080).toFixed(0));\",\n        \"})();\",\n    ]\n    expect_stdout: true\n}\n\noctal: {\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        (function() {\n            console.log(052);\n            console.log(-052);\n\n            console.log(018);\n            console.log(-018);\n\n            console.log(052.toFixed(0));\n            console.log(-052.toFixed(0));\n\n            console.log(018..toFixed(0));\n            console.log(-018..toFixed(0));\n        })();\n    }\n    expect_exact: [\n        \"(function() {\",\n        \"    console.log(42);\",\n        \"    console.log(-42);\",\n        \"    console.log(18);\",\n        \"    console.log(-18);\",\n        \"    console.log(42..toFixed(0));\",\n        \"    console.log(-42..toFixed(0));\",\n        \"    console.log(18..toFixed(0));\",\n        \"    console.log(-18..toFixed(0));\",\n        \"})();\",\n    ]\n    expect_stdout: true\n}\n\ncomparisons: {\n    options = {\n        comparisons: true,\n    }\n    input: {\n        var x = \"42\", y = \"0x30\";\n        console.log(\n            ~x === 42,\n            x % y === 42\n        );\n    }\n    expect: {\n        var x = \"42\", y = \"0x30\";\n        console.log(\n            42 == ~x,\n            x % y == 42\n        );\n    }\n    expect_stdout: \"false true\"\n}\n\nevaluate_1: {\n    options = {\n        evaluate: true,\n        unsafe_math: false,\n    }\n    input: {\n        console.log(\n            x + 1 + 2,\n            x * 1 * 2,\n            +x + 1 + 2,\n            1 + x + 2 + 3,\n            1 | x | 2 | 3,\n            1 + x-- + 2 + 3,\n            1 + (x*y + 2) + 3,\n            1 + (2 + x + 3),\n            1 + (2 + ~x + 3),\n            -y + (2 + ~x + 3),\n            1 & (2 & x & 3),\n            1 + (2 + (x |= 0) + 3)\n        );\n    }\n    expect: {\n        console.log(\n            x + 1 + 2,\n            2 * +x,\n            +x + 1 + 2,\n            1 + x + 2 + 3,\n            3 | x,\n            1 + x-- + 2 + 3,\n            x*y + 2 + 1 + 3,\n            1 + (2 + x + 3),\n            2 + ~x + 3 + 1,\n            -y + (2 + ~x + 3),\n            0 & x,\n            2 + (x |= 0) + 3 + 1\n        );\n    }\n}\n\nevaluate_1_unsafe_math: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(\n            x + 1 + 2,\n            x * 1 * 2,\n            +x + 1 + 2,\n            1 + x + 2 + 3,\n            1 | x | 2 | 3,\n            1 + x-- + 2 + 3,\n            1 + (x*y + 2) + 3,\n            1 + (2 + x + 3),\n            1 + (2 + ~x + 3),\n            -y + (2 + ~x + 3),\n            1 & (2 & x & 3),\n            1 + (2 + (x |= 0) + 3)\n        );\n    }\n    expect: {\n        console.log(\n            x + 1 + 2,\n            2 * +x,\n            +x + 3,\n            1 + x + 2 + 3,\n            3 | x,\n            6 + x--,\n            x*y + 6,\n            1 + (2 + x + 3),\n            6 + ~x,\n            5 - y + ~x,\n            0 & x,\n            6 + (x |= 0)\n        );\n    }\n}\n\nevaluate_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe_math: false,\n    }\n    input: {\n        function f(num) {\n            var x = \"\" + num, y = null;\n            [\n                x + 1 + 2,\n                x * 1 * 2,\n                +x + 1 + 2,\n                1 + x + 2 + 3,\n                1 | x | 2 | 3,\n                1 + x-- + 2 + 3,\n                1 + (x*y + 2) + 3,\n                1 + (2 + x + 3),\n                1 + (2 + ~x + 3),\n                -y + (2 + ~x + 3),\n                1 & (2 & x & 3),\n                1 + (2 + (x |= 0) + 3),\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect: {\n        function f(num) {\n            var x = \"\" + num, y = null;\n            [\n                x + \"12\",\n                2 * x,\n                +x + 1 + 2,\n                1 + x + \"23\",\n                3 | x,\n                1 + x-- + 2 + 3,\n                x*y + 2 + 1 + 3,\n                2 + x + 3 + 1,\n                2 + ~x + 3 + 1,\n                2 + ~x + 3,\n                0 & x,\n                2 + (x |= 0) + 3 + 1,\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect_stdout: [\n        \"string 4212\",\n        \"number 84\",\n        \"number 45\",\n        \"string 14223\",\n        \"number 43\",\n        \"number 48\",\n        \"number 6\",\n        \"number 47\",\n        \"number -36\",\n        \"number -37\",\n        \"number 0\",\n        \"number 47\",\n    ]\n}\n\nevaluate_2_unsafe_math: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe_math: true,\n    }\n    input: {\n        function f(num) {\n            var x = \"\" + num, y = null;\n            [\n                x + 1 + 2,\n                x * 1 * 2,\n                +x + 1 + 2,\n                1 + x + 2 + 3,\n                1 | x | 2 | 3,\n                1 + x-- + 2 + 3,\n                1 + (x*y + 2) + 3,\n                1 + (2 + x + 3),\n                1 + (2 + ~x + 3),\n                -y + (2 + ~x + 3),\n                1 & (2 & x & 3),\n                1 + (2 + (x |= 0) + 3),\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect: {\n        function f(num) {\n            var x = \"\" + num, y = null;\n            [\n                x + \"12\",\n                2 * x,\n                +x + 3,\n                1 + x + \"23\",\n                3 | x,\n                6 + x--,\n                x*y + 6,\n                6 + x,\n                6 + ~x,\n                5 + ~x,\n                0 & x,\n                6 + (x |= 0),\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect_stdout: [\n        \"string 4212\",\n        \"number 84\",\n        \"number 45\",\n        \"string 14223\",\n        \"number 43\",\n        \"number 48\",\n        \"number 6\",\n        \"number 47\",\n        \"number -36\",\n        \"number -37\",\n        \"number 0\",\n        \"number 47\",\n    ]\n}\n\nevaluate_3: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(1 + Number(x) + 2);\n    }\n    expect: {\n        console.log(+(\"\" + x) + 3);\n    }\n}\n\nevaluate_4: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\n            1+ +a,\n            +a+1,\n            1+-a,\n            -a+1,\n            +a+ +b,\n            +a+-b,\n            -a+ +b,\n            -a+-b\n        );\n    }\n    expect: {\n        console.log(\n            +a+1,\n            +a+1,\n            1-a,\n            1-a,\n            +a+ +b,\n            +a-b,\n            -a+ +b,\n            -a-b\n        );\n    }\n}\n\nevaluate_5: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe_math: false,\n    }\n    input: {\n        function f(num) {\n            var a = \"\" + num;\n            [\n                +a + 2 + 3,\n                +a + 2 - 3,\n                +a - 2 + 3,\n                +a - 2 - 3,\n                2 + +a + 3,\n                2 + +a - 3,\n                2 - +a + 3,\n                2 - +a - 3,\n                2 + 3 + +a,\n                2 + 3 - +a,\n                2 - 3 + +a,\n                2 - 3 - +a,\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(1);\n    }\n    expect: {\n        function f(num) {\n            var a = \"\" + num;\n            [\n                +a + 2 + 3,\n                +a + 2 - 3,\n                a - 2 + 3,\n                a - 2 - 3,\n                +a + 2 + 3,\n                +a + 2 - 3,\n                2 - a + 3,\n                2 - a - 3,\n                +a + 5,\n                5 - a,\n                +a - 1,\n                -1 - a,\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(1);\n    }\n    expect_stdout: [\n        \"number 6\",\n        \"number 0\",\n        \"number 2\",\n        \"number -4\",\n        \"number 6\",\n        \"number 0\",\n        \"number 4\",\n        \"number -2\",\n        \"number 6\",\n        \"number 4\",\n        \"number 0\",\n        \"number -2\",\n    ]\n}\n\nevaluate_5_unsafe_math: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe_math: true,\n    }\n    input: {\n        function f(num) {\n            var a = \"\" + num;\n            [\n                +a + 2 + 3,\n                +a + 2 - 3,\n                +a - 2 + 3,\n                +a - 2 - 3,\n                2 + +a + 3,\n                2 + +a - 3,\n                2 - +a + 3,\n                2 - +a - 3,\n                2 + 3 + +a,\n                2 + 3 - +a,\n                2 - 3 + +a,\n                2 - 3 - +a,\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(1);\n    }\n    expect: {\n        function f(num) {\n            var a = \"\" + num;\n            [\n                +a + 5,\n                +a + -1,\n                a - -1,\n                a - 5,\n                +a + 5,\n                +a + -1,\n                5 - a,\n                -1 - a,\n                +a + 5,\n                5 - a,\n                +a - 1,\n                -1 - a,\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(1);\n    }\n    expect_stdout: [\n        \"number 6\",\n        \"number 0\",\n        \"number 2\",\n        \"number -4\",\n        \"number 6\",\n        \"number 0\",\n        \"number 4\",\n        \"number -2\",\n        \"number 6\",\n        \"number 4\",\n        \"number 0\",\n        \"number -2\",\n    ]\n}\n\nevaluate_6: {\n    options = {\n        evaluate: true,\n        unsafe_math: false,\n    }\n    input: {\n        var a = \"1\";\n        [\n            -a + 2 + 3,\n            -a + 2 - 3,\n            -a - 2 + 3,\n            -a - 2 - 3,\n            2 + -a + 3,\n            2 + -a - 3,\n            2 - -a + 3,\n            2 - -a - 3,\n            2 + 3 + -a,\n            2 + 3 - -a,\n            2 - 3 + -a,\n            2 - 3 - -a,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect: {\n        var a = \"1\";\n        [\n            2 - a + 3,\n            2 - a - 3,\n            -a - 2 + 3,\n            -a - 2 - 3,\n            2 - a + 3,\n            2 - a - 3,\n            2 - -a + 3,\n            2 - -a - 3,\n            5 - a,\n            5 - -a,\n            -1 - a,\n            -1 - -a,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect_stdout: [\n        \"number 4\",\n        \"number -2\",\n        \"number 0\",\n        \"number -6\",\n        \"number 4\",\n        \"number -2\",\n        \"number 6\",\n        \"number 0\",\n        \"number 4\",\n        \"number 6\",\n        \"number -2\",\n        \"number 0\",\n    ]\n}\n\nevaluate_6_unsafe_math: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = \"1\";\n        [\n            -a + 2 + 3,\n            -a + 2 - 3,\n            -a - 2 + 3,\n            -a - 2 - 3,\n            2 + -a + 3,\n            2 + -a - 3,\n            2 - -a + 3,\n            2 - -a - 3,\n            2 + 3 + -a,\n            2 + 3 - -a,\n            2 - 3 + -a,\n            2 - 3 - -a,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect: {\n        var a = \"1\";\n        [\n            5 - a,\n            -1 - a,\n            -a - -1,\n            -a - 5,\n            5 - a,\n            -1 - a,\n            5 - -a,\n            -1 - -a,\n            5 - a,\n            5 - -a,\n            -1 - a,\n            -1 - -a,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect_stdout: [\n        \"number 4\",\n        \"number -2\",\n        \"number 0\",\n        \"number -6\",\n        \"number 4\",\n        \"number -2\",\n        \"number 6\",\n        \"number 0\",\n        \"number 4\",\n        \"number 6\",\n        \"number -2\",\n        \"number 0\",\n    ]\n}\n\nevaluate_7: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe_math: false,\n    }\n    input: {\n        function f(num, y) {\n            var x = \"\" + num;\n            [\n                +x + 2 + (3 + !y),\n                +x + 2 + (3 - !y),\n                +x + 2 - (3 + !y),\n                +x + 2 - (3 - !y),\n                +x - 2 + (3 + !y),\n                +x - 2 + (3 - !y),\n                +x - 2 - (3 + !y),\n                +x - 2 - (3 - !y),\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect: {\n        function f(num, y) {\n            var x = \"\" + num;\n            [\n                +x + 2 + (3 + !y),\n                +x + 2 + (3 - !y),\n                +x + 2 - (3 + !y),\n                +x + 2 - (3 - !y),\n                x - 2 + (3 + !y),\n                x - 2 + (3 - !y),\n                x - 2 - (3 + !y),\n                x - 2 - (3 - !y),\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect_stdout: [\n        \"number 48\",\n        \"number 46\",\n        \"number 40\",\n        \"number 42\",\n        \"number 44\",\n        \"number 42\",\n        \"number 36\",\n        \"number 38\",\n    ]\n}\n\nevaluate_7_unsafe_math: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe_math: true,\n    }\n    input: {\n        function f(num, y) {\n            var x = \"\" + num;\n            [\n                +x + 2 + (3 + !y),\n                +x + 2 + (3 - !y),\n                +x + 2 - (3 + !y),\n                +x + 2 - (3 - !y),\n                +x - 2 + (3 + !y),\n                +x - 2 + (3 - !y),\n                +x - 2 - (3 + !y),\n                +x - 2 - (3 - !y),\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect: {\n        function f(num, y) {\n            var x = \"\" + num;\n            [\n                +x + 5 + !y,\n                +x + 5 - !y,\n                +x + -1 - !y,\n                +x + -1 + !y,\n                x - -1 + !y,\n                x - -1 - !y,\n                x - 5 - !y,\n                x - 5 + !y,\n            ].forEach(function(n) {\n                console.log(typeof n, n);\n            });\n        }\n        f(42);\n    }\n    expect_stdout: [\n        \"number 48\",\n        \"number 46\",\n        \"number 40\",\n        \"number 42\",\n        \"number 44\",\n        \"number 42\",\n        \"number 36\",\n        \"number 38\",\n    ]\n}\n\nevaluate_8_unsafe_math: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = [ \"42\" ];\n        console.log(a * (1 / 7));\n    }\n    expect: {\n        var a = [ \"42\" ];\n        console.log(+a / 7);\n    }\n    expect_stdout: \"6\"\n}\n\nNaN_redefined: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var NaN;\n        console.log(1 / (0 / 0));\n    }\n    expect: {\n        var NaN;\n        console.log(0 / 0);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_1710: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        var x = {};\n        console.log((x += 1) + -x);\n    }\n    expect: {\n        var x = {};\n        console.log((x += 1) + -x);\n    }\n    expect_stdout: true\n}\n\nunary_binary_parentheses: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        var v = [ 0, 1, NaN, Infinity, null, undefined, true, false, \"\", \"foo\", /foo/ ];\n        v.forEach(function(x) {\n            v.forEach(function(y) {\n                console.log(\n                    +(x*y),\n                    +(x/y),\n                    +(x%y),\n                    -(x*y),\n                    -(x/y),\n                    -(x%y)\n                );\n            });\n        });\n    }\n    expect: {\n        var v = [ 0, 1, NaN, 1/0, null, void 0, true, false, \"\", \"foo\", /foo/ ];\n        v.forEach(function(x) {\n            v.forEach(function(y) {\n                console.log(\n                    x*y,\n                    x/y,\n                    x%y,\n                    -x*y,\n                    -x/y,\n                    -x%y\n                );\n            });\n        });\n    }\n    expect_stdout: true\n}\n\nissue_3531_1: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = \"1\";\n        console.log(typeof (a + 1 - .1 - .1 - .1));\n    }\n    expect: {\n        var a = \"1\";\n        console.log(typeof (a + 1 - .3));\n    }\n    expect_stdout: \"number\"\n}\n\nissue_3531_2: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(1 - (2 - {}));\n    }\n    expect: {\n        console.log(-1 + +{});\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_3531_3: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = \"3\";\n        console.log(1 - (2 + a));\n    }\n    expect: {\n        var a = \"3\";\n        console.log(1 - (2 + a));\n    }\n    expect_stdout: \"-22\"\n}\n\nissue_3536: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        var c = --a + (\"23\" - (b++, 1));\n        console.log(typeof c, a, b, c);\n    }\n    expect: {\n        var a = 100, b = 10;\n        var c = --a + (\"23\" - (b++, 1));\n        console.log(typeof c, a, b, c);\n    }\n    expect_stdout: \"number 99 11 121\"\n}\n\nissue_3539: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = -0 + -\"\";\n        console.log(0/a, 1/a, -1/a);\n    }\n    expect: {\n        var a = -0;\n        console.log(0/a, 1/a, -1/a);\n    }\n    expect_stdout: \"NaN -Infinity Infinity\"\n}\n\nissue_3547_1: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        [\n            1/0 + \"1\" + 0,\n            1/0 + \"1\" - 0,\n            1/0 - \"1\" + 0,\n            1/0 - \"1\" - 0,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect: {\n        [\n            1/0 + \"10\",\n            NaN,\n            1/0,\n            1/0,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect_stdout: [\n        \"string Infinity10\",\n        \"number NaN\",\n        \"number Infinity\",\n        \"number Infinity\",\n    ]\n}\n\nissue_3547_2: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        [\n            \"1\" + 1/0 + 0,\n            \"1\" + 1/0 - 0,\n            \"1\" - 1/0 + 0,\n            \"1\" - 1/0 - 0,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect: {\n        [\n            \"1\" + 1/0 + 0,\n            NaN,\n            -1/0,\n            -1/0,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect_stdout: [\n        \"string 1Infinity0\",\n        \"number NaN\",\n        \"number -Infinity\",\n        \"number -Infinity\",\n    ]\n}\n\nissue_3547_3: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = \"3\";\n        [\n            a + \"2\" + 1,\n            a + \"2\" - 1,\n            a - \"2\" + 1,\n            a - \"2\" - 1,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect: {\n        var a = \"3\";\n        [\n            a + \"21\",\n            a + \"2\" - 1,\n            a - 1,\n            a - 3,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect_stdout: [\n        \"string 321\",\n        \"number 31\",\n        \"number 2\",\n        \"number 0\",\n    ]\n}\n\nissue_3547_4: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = \"2\";\n        [\n            \"3\" + a + 1,\n            \"3\" + a - 1,\n            \"3\" - a + 1,\n            \"3\" - a - 1,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect: {\n        var a = \"2\";\n        [\n            \"3\" + a + 1,\n            \"3\" + a - 1,\n            4 - a,\n            2 - a,\n        ].forEach(function(n) {\n            console.log(typeof n, n);\n        });\n    }\n    expect_stdout: [\n        \"string 321\",\n        \"number 31\",\n        \"number 2\",\n        \"number 0\",\n    ]\n}\n\nunsafe_math_rounding: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(4 / -3 + 1 === 1 / -3);\n    }\n    expect: {\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n}\n\nissue_3593: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log((0 === this) - 1 - \"1\");\n    }\n    expect: {\n        console.log((0 === this) - 2);\n    }\n    expect_stdout: \"-2\"\n}\n\nunsafe_math_swap_constant: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = 1, b = 2;\n        console.log(\n            a++ + b-- + 3,\n            a++ + b + 3,\n            a + b-- + 3,\n            a + b + 3,\n            a++ - b-- + 3,\n            a++ - b + 3,\n            a - b-- + 3,\n            a - b + 3\n        );\n    }\n    expect: {\n        var a = 1, b = 2;\n        console.log(\n            3 + a++ + b--,\n            a++ + b + 3,\n            a + b-- + 3,\n            a + b + 3,\n            3 + a++ - b--,\n            3 + a++ - b,\n            a - b-- + 3,\n            a - b + 3\n        );\n    }\n    expect_stdout: \"6 6 7 6 6 8 9 10\"\n}\n\nidentity_1: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        0 + a;\n        a + 0;\n        0 - a;\n        a - 0;\n        1 * a;\n        a * 1;\n        1 / a;\n        a / 1;\n    }\n    expect: {\n        0 + a;\n        a + 0;\n        0 - a;\n        +a;\n        +a;\n        +a;\n        1 / a;\n        +a;\n    }\n}\n\nidentity_2: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        0 + !a;\n        !a + 0;\n        0 - !a;\n        !a - 0;\n        1 * !a;\n        !a * 1;\n        1 / !a;\n        !a / 1;\n    }\n    expect: {\n        +!a;\n        +!a;\n        0 - !a;\n        +!a;\n        +!a;\n        +!a;\n        1 / !a;\n        +!a;\n    }\n}\n\nidentity_3: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        0 + --a;\n        --a + 0;\n        0 - --a;\n        --a - 0;\n        1 * --a;\n        --a * 1;\n        1 / --a;\n        --a / 1;\n    }\n    expect: {\n        --a;\n        --a;\n        0 - --a;\n        --a;\n        --a;\n        --a;\n        1 / --a;\n        --a;\n    }\n}\n\nissue_3653: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(0 - (console && 0));\n        console.log(0 + (0 - (console && 0)));\n        console.log(0 - (0 - (console && 0)));\n        console.log(1 * (0 - (console && 0)));\n        console.log(1 / (0 - (console && 0)));\n        console.log((0 - (console && 0)) + 0);\n        console.log((0 - (console && 0)) - 0);\n        console.log((0 - (console && 0)) * 1);\n        console.log((0 - (console && 0)) / 1);\n    }\n    expect: {\n        console.log(0 - (console && 0));\n        console.log(0 - (console && 0));\n        console.log(0 - (0 - (console && 0)));\n        console.log(0 - (console && 0));\n        console.log(1 / (0 - (console && 0)));\n        console.log(0 - (console && 0));\n        console.log(0 - (console && 0));\n        console.log(0 - (console && 0));\n        console.log(0 - (console && 0));\n    }\n    expect_stdout: [\n        \"0\",\n        \"0\",\n        \"0\",\n        \"0\",\n        \"Infinity\",\n        \"0\",\n        \"0\",\n        \"0\",\n        \"0\",\n    ]\n}\n\nissue_3655: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(0 + 0 * -[].length);\n        console.log(0 + (0 + 0 * -[].length));\n        console.log(0 - (0 + 0 * -[].length));\n        console.log(1 * (0 + 0 * -[].length));\n        console.log(1 / (0 + 0 * -[].length));\n        console.log((0 + 0 * -[].length) + 0);\n        console.log((0 + 0 * -[].length) - 0);\n        console.log((0 + 0 * -[].length) * 1);\n        console.log((0 + 0 * -[].length) / 1);\n    }\n    expect: {\n        console.log(0 + 0 * -[].length);\n        console.log(0 + 0 * -[].length);\n        console.log(0 - (0 + 0 * -[].length));\n        console.log(0 + 0 * -[].length);\n        console.log(1 / (0 + 0 * -[].length));\n        console.log(0 + 0 * -[].length);\n        console.log(0 + 0 * -[].length);\n        console.log(0 + 0 * -[].length);\n        console.log(0 + 0 * -[].length);\n    }\n    expect_stdout: [\n        \"0\",\n        \"0\",\n        \"0\",\n        \"0\",\n        \"Infinity\",\n        \"0\",\n        \"0\",\n        \"0\",\n        \"0\",\n    ]\n}\n\nissue_3676_1: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = [];\n        console.log(false - (a - (a[1] = 42)));\n    }\n    expect: {\n        var a = [];\n        console.log(false - (a - (a[1] = 42)));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_3676_2: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a;\n        console.log(false - ((a = []) - (a[1] = 42)));\n    }\n    expect: {\n        var a;\n        console.log(false - ((a = []) - (a[1] = 42)));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_3682_1: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = -0;\n        console.log(1 / (a - 1 + 1));\n    }\n    expect: {\n        var a = -0;\n        console.log(1 / (a - 1 + 1));\n    }\n    expect_stdout: \"Infinity\"\n}\n\nissue_3682_2: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = -0, b = 1;\n        console.log(1 / (a - (b - b)));\n    }\n    expect: {\n        var a = -0, b = 1;\n        console.log(1 / (a - (b - b)));\n    }\n    expect_stdout: \"-Infinity\"\n}\n\nissue_3682_3: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        var a = -0, b = 1, c = -1;\n        console.log(1 / (a - (+b + +c)));\n    }\n    expect: {\n        var a = -0, b = 1, c = -1;\n        console.log(1 / (a - (+b + +c)));\n    }\n    expect_stdout: \"-Infinity\"\n}\n\nissue_3684: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(1 / (-1 * (0 & console) + 0));\n        console.log(1 / ((0 & console) / -1 + 0));\n    }\n    expect: {\n        console.log(1 / (-1 * (0 & console) + 0));\n        console.log(1 / ((0 & console) / -1 + 0));\n    }\n    expect_stdout: [\n        \"Infinity\",\n        \"Infinity\",\n    ]\n}\n\nissue_3695: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        var a = [];\n        console.log(+(a * (a[0] = false)));\n    }\n    expect: {\n        var a = [];\n        console.log(a * (a[0] = false));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4137: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(+(A = []) * (A[0] = 1));\n    }\n    expect: {\n        console.log(+(A = []) * (A[0] = 1));\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4142: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\"\" + +(0 === console));\n    }\n    expect: {\n        console.log(\"\" + +(0 === console));\n    }\n    expect_stdout: \"0\"\n}\n\nissue_4542_1: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a / (1 / (a[0] = 2));\n        }([ 3 ]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a / (1 / (a[0] = 2));\n        }([ 3 ]));\n    }\n    expect_stdout: \"4\"\n}\n\nissue_4542_2: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a / (1 / --a[0]);\n        }([ 3 ]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a / (1 / --a[0]);\n        }([ 3 ]));\n    }\n    expect_stdout: \"4\"\n}\n\nissue_4542_3: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a / (0 / (a[0] = 0, 1));\n        }([ 1 ]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a / (0 / (a[0] = 0, 1));\n        }([ 1 ]));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_4542_4: {\n    options = {\n        evaluate: true,\n        unsafe_math: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a / (1 / (a.length = 1));\n        }([ 2, 3 ]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a / (1 / (a.length = 1));\n        }([ 2, 3 ]));\n    }\n    expect_stdout: \"2\"\n}\n"
  },
  {
    "path": "test/compress/objects.js",
    "content": "duplicate_key: {\n    options = {\n        objects: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            a: 3,\n            b: 2,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"a 3\",\n        \"b 2\",\n    ]\n}\n\nduplicate_key_strict: {\n    options = {\n        objects: true,\n        side_effects: true,\n    }\n    input: {\n        \"use strict\";\n        var o = {\n            a: 1,\n            b: 2,\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        \"use strict\";\n        var o = {\n            a: 1,\n            a: 3,\n            b: 2,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: true\n}\n\nduplicate_key_side_effect: {\n    options = {\n        objects: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: o = 2,\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            a: 1,\n            b: o = 2,\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"a 3\",\n        \"b 2\",\n    ]\n}\n\nduplicate_key_with_accessor: {\n    options = {\n        objects: true,\n        side_effects: true,\n    }\n    input: {\n        [\n            {\n                a: 0,\n                b: 1,\n                a: 2,\n                set b(v) {},\n            },\n            {\n                a: 3,\n                b: 4,\n                get a() {\n                    return 5;\n                },\n                a: 6,\n                b: 7,\n                a: 8,\n                b: 9,\n            },\n        ].forEach(function(o) {\n            for (var k in o)\n                console.log(k, o[k]);\n        });\n    }\n    expect: {\n        [\n            {\n                a: 2,\n                b: 1,\n                set b(v) {},\n            },\n            {\n                a: 3,\n                b: 4,\n                get a() {\n                    return 5;\n                },\n                a: 8,\n                b: 9,\n            },\n        ].forEach(function(o) {\n            for (var k in o)\n                console.log(k, o[k]);\n        });\n    }\n    expect_stdout: true\n}\n\nunsafe_object_repeated: {\n    options = {\n        evaluate: true,\n        objects: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o = { a: { b: 1 }, a: 1 };\n        console.log(\n            o + 1,\n            o.a + 1,\n            o.b + 1,\n            o.a.b + 1\n        );\n    }\n    expect: {\n        var o = { a: 1 };\n        console.log(\n            o + 1,\n            2,\n            o.b + 1,\n            NaN\n        );\n    }\n    expect_stdout: true\n}\n\nnumeric_literal: {\n    options = {\n        objects: true,\n        side_effects: true,\n    }\n    mangle = {\n        properties: {\n            domprops: true,\n        },\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        var obj = {\n            0: 0,\n            \"-0\": 1,\n            42: 2,\n            \"42\": 3,\n            0x25: 4,\n            \"0x25\": 5,\n            1E42: 6,\n            \"1E42\": 7,\n            \"1e+42\": 8,\n        };\n        console.log(obj[-0], obj[-\"\"], obj[\"-0\"]);\n        console.log(obj[42], obj[\"42\"]);\n        console.log(obj[0x25], obj[\"0x25\"], obj[37], obj[\"37\"]);\n        console.log(obj[1E42], obj[\"1E42\"], obj[\"1e+42\"]);\n    }\n    expect_exact: [\n        'var obj = {',\n        '    0: 0,',\n        '    \"-0\": 1,',\n        '    42: 3,',\n        '    37: 4,',\n        '    o: 5,',\n        '    1e42: 8,',\n        '    b: 7',\n        '};',\n        '',\n        'console.log(obj[-0], obj[-\"\"], obj[\"-0\"]);',\n        '',\n        'console.log(obj[42], obj[\"42\"]);',\n        '',\n        'console.log(obj[37], obj[\"o\"], obj[37], obj[\"37\"]);',\n        '',\n        'console.log(obj[1e42], obj[\"b\"], obj[\"1e+42\"]);',\n    ]\n    expect_stdout: [\n        \"0 0 1\",\n        \"3 3\",\n        \"4 5 4 4\",\n        \"8 7 8\",\n    ]\n}\n\nevaluate_computed_key: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            [\"foo\" + \"bar\"]: \"PASS\",\n        }.foobar);\n    }\n    expect: {\n        console.log({\n            foobar: \"PASS\",\n        }.foobar);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_computed_key: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            [console.log(\"PASS\")]: 42,\n        });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nshorthand_keywords: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var async = 1, get = 2, set = 3, o = {\n            async,\n            get,\n            set,\n        };\n        console.log(o.async, o.get, o.set);\n    }\n    expect: {\n        console.log(1, 2, 3);\n    }\n    expect_stdout: \"1 2 3\"\n    node_version: \">=6\"\n}\n\nobject_super: {\n    input: {\n        var o = {\n            f() {\n                return super.p;\n            },\n            p: \"FAIL\",\n        };\n        Object.setPrototypeOf(o, { p: \"PASS\" });\n        console.log(o.f());\n    }\n    expect_exact: 'var o={f(){return super.p},p:\"FAIL\"};Object.setPrototypeOf(o,{p:\"PASS\"});console.log(o.f());'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nobject_super_async: {\n    input: {\n        var o = {\n            async f() {\n                return super.p;\n            },\n            p: \"FAIL\",\n        };\n        Object.setPrototypeOf(o, { p: \"PASS\" });\n        o.f().then(console.log);\n    }\n    expect_exact: 'var o={async f(){return super.p},p:\"FAIL\"};Object.setPrototypeOf(o,{p:\"PASS\"});o.f().then(console.log);'\n    expect_stdout: \"PASS\"\n    node_version: \">=8\"\n}\n\nobject_super_generator: {\n    input: {\n        var o = {\n            *f() {\n                yield super.p;\n            },\n            p: \"FAIL\",\n        };\n        Object.setPrototypeOf(o, { p: \"PASS\" });\n        console.log(o.f().next().value);\n    }\n    expect_exact: 'var o={*f(){yield super.p},p:\"FAIL\"};Object.setPrototypeOf(o,{p:\"PASS\"});console.log(o.f().next().value);'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nobject_super_async_generator: {\n    input: {\n        var o = {\n            async *f() {\n                return super.p;\n            },\n            p: \"FAIL\",\n        };\n        Object.setPrototypeOf(o, { p: \"PASS\" });\n        o.f().next().then(function(v) {\n            console.log(v.value, v.done);\n        });\n    }\n    expect_exact: 'var o={async*f(){return super.p},p:\"FAIL\"};Object.setPrototypeOf(o,{p:\"PASS\"});o.f().next().then(function(v){console.log(v.value,v.done)});'\n    expect_stdout: \"PASS true\"\n    node_version: \">=10\"\n}\n\nissue_4269_1: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            get 0() {\n                return \"FAIL\";\n            },\n            [0]: \"PASS\",\n        }[0]);\n    }\n    expect: {\n        console.log({\n            get 0() {\n                return \"FAIL\";\n            },\n            [0]: \"PASS\",\n        }[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4269_2: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            get [0]() {\n                return \"FAIL\";\n            },\n            0: \"PASS\",\n        }[0]);\n    }\n    expect: {\n        console.log({\n            get [0]() {\n                return \"FAIL\";\n            },\n            0: \"PASS\",\n        }[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4269_3: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            [\"foo\"]: \"bar\",\n            get 42() {\n                return \"FAIL\";\n            },\n            42: \"PASS\",\n        }[42]);\n    }\n    expect: {\n        console.log({\n            foo: \"bar\",\n            get [42]() {\n                return \"FAIL\";\n            },\n            42: \"PASS\",\n        }[42]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4269_4: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            get 42() {\n                return \"FAIL\";\n            },\n            [\"foo\"]: \"bar\",\n            42: \"PASS\",\n        }[42]);\n    }\n    expect: {\n        console.log({\n            get 42() {\n                return \"FAIL\";\n            },\n            foo: \"bar\",\n            [42]: \"PASS\",\n        }[42]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4269_5: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            get 42() {\n                return \"FAIL\";\n            },\n            [console]: \"bar\",\n            42: \"PASS\",\n        }[42]);\n    }\n    expect: {\n        console.log({\n            get 42() {\n                return \"FAIL\";\n            },\n            [console]: \"bar\",\n            42: \"PASS\",\n        }[42]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4380: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            get 0() {\n                return \"FAIL 1\";\n            },\n            0: \"FAIL 2\",\n            [0]: \"PASS\",\n        }[0]);\n    }\n    expect: {\n        console.log({\n            get 0() {\n                return \"FAIL 1\";\n            },\n            [0]: (\"FAIL 2\", \"PASS\"),\n        }[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4415: {\n    options = {\n        evaluate: true,\n        objects: true,\n    }\n    input: {\n        console.log({\n            [\"00\"]: \"FAIL\",\n        }[0] || \"PASS\");\n    }\n    expect: {\n        console.log({\n            \"00\": \"FAIL\",\n        }[0] || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5213: {\n    options = {\n        objects: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        console.log({\n            p: a = \"PASS\",\n            0: a,\n            p: null,\n        }[0]);\n    }\n    expect: {\n        var a = \"FAIL\";\n        console.log({\n            p: (a = \"PASS\", null),\n            0: a,\n        }[0]);\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/optional-chains.js",
    "content": "call: {\n    input: {\n        console.log?.(undefined?.(console.log(\"FAIL\")));\n    }\n    expect_exact: 'console.log?.((void 0)?.(console.log(\"FAIL\")));'\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\ndot: {\n    input: {\n        console?.log((void 0)?.p);\n    }\n    expect_exact: \"console?.log((void 0)?.p);\"\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\ndot_in: {\n    input: {\n        var o = { in: 42 };\n        console.log(o.in, o?.in);\n    }\n    expect_exact: \"var o={in:42};console.log(o.in,o?.in);\"\n    expect_stdout: \"42 42\"\n    node_version: \">=14\"\n}\n\nsub: {\n    input: {\n        console?.[\"log\"](null?.[console.log(\"FAIL\")]);\n    }\n    expect_exact: 'console?.[\"log\"](null?.[console.log(\"FAIL\")]);'\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\nternary_decimal: {\n    input: {\n        null ? .42 : console.log(\"PASS\");\n    }\n    expect_exact: 'null?.42:console.log(\"PASS\");'\n    expect_stdout: \"PASS\"\n}\n\nassign_parentheses_call: {\n    input: {\n        var o = {};\n        ((() => o)?.()).p = \"PASS\";\n        console.log(o.p);\n    }\n    expect_exact: 'var o={};((()=>o)?.()).p=\"PASS\";console.log(o.p);'\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nassign_parentheses_dot: {\n    input: {\n        (console?.log).name.p = console.log(\"PASS\");\n    }\n    expect_exact: '(console?.log).name.p=console.log(\"PASS\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nassign_no_parentheses: {\n    input: {\n        console[console.log?.(\"PASS\")] = 42;\n    }\n    expect_exact: 'console[console.log?.(\"PASS\")]=42;'\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\ncall_parentheses: {\n    input: {\n        (function(o) {\n            console.log(o.f(\"FAIL\"), (o.f)(\"FAIL\"), (0, o.f)(42));\n            console.log(o?.f(\"FAIL\"), (o?.f)(\"FAIL\"), (0, o?.f)(42));\n        })({\n            a: \"PASS\",\n            f(b) {\n                return this.a || b;\n            },\n        });\n    }\n    expect_exact: '(function(o){console.log(o.f(\"FAIL\"),o.f(\"FAIL\"),(0,o.f)(42));console.log(o?.f(\"FAIL\"),(o?.f)(\"FAIL\"),(0,o?.f)(42))})({a:\"PASS\",f(b){return this.a||b}});'\n    expect_stdout: [\n        \"PASS PASS 42\",\n        \"PASS PASS 42\",\n    ]\n    node_version: \">=14\"\n}\n\nunary_parentheses: {\n    input: {\n        var o = { p: 41 };\n        (function() {\n            return o;\n        }?.()).p++;\n        console.log(o.p);\n    }\n    expect_exact: \"var o={p:41};(function(){return o}?.()).p++;console.log(o.p);\"\n    expect_stdout: \"42\"\n    node_version: \">=14\"\n}\n\ncollapse_vars_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        A = 42;\n        a?.[42];\n        console.log(typeof A);\n    }\n    expect: {\n        var a;\n        A = 42;\n        a?.[42];\n        console.log(typeof A);\n    }\n    expect_stdout: \"number\"\n    node_version: \">=14\"\n}\n\ncollapse_vars_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        A = 42;\n        a?.(42);\n        console.log(typeof A);\n    }\n    expect: {\n        var a;\n        A = 42;\n        a?.(42);\n        console.log(typeof A);\n    }\n    expect_stdout: \"number\"\n    node_version: \">=14\"\n}\n\nproperties: {\n    options = {\n        evaluate: true,\n        properties: true,\n    }\n    input: {\n        var a;\n        console.log(a?.[\"FAIL\"]);\n    }\n    expect: {\n        var a;\n        console.log(a?.FAIL);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\nreduce_vars_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        null?.[a = 0];\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = 1;\n        null?.[a = 0];\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nreduce_vars_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        null?.(a = 0);\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a = 1;\n        null?.(a = 0);\n        console.log(a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nside_effects: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var a;\n        a?.[a = \"FAIL\"];\n        console.log(a);\n    }\n    expect: {\n        var a;\n        a?.[a = \"FAIL\"];\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\ntrim_1: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function(a, b) {\n            console?.log?.(a?.p, b?.[console.log(\"FAIL\")]);\n        })?.({ p: \"PASS\" });\n    }\n    expect: {\n        (function(a, b) {\n            console?.log?.(a.p, void 0);\n        })({ p: \"PASS\" });\n    }\n    expect_stdout: \"PASS undefined\"\n    node_version: \">=14\"\n}\n\ntrim_2: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n        side_effects: true,\n    }\n    input: {\n        (void console.log(\"PASS\"))?.[console.log(\"FAIL\")];\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\ntrim_dot_call_1: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n    }\n    input: {\n        console.log(null?.f());\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\ntrim_dot_call_2: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n        unsafe: true,\n    }\n    input: {\n        try {\n            (null?.p)();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (void 0)();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\ntrim_dot_call_3: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n        unsafe: true,\n    }\n    input: {\n        try {\n            ({ p: null })?.p();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            null();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\ntrim_dot_sub: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n    }\n    input: {\n        console.log(null?.p[42]);\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\ntrim_sub_call_call: {\n    options = {\n        evaluate: true,\n        optional_chains: true,\n    }\n    input: {\n        console.log(null?.[42]()());\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\nissue_4906: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        do {\n            var a = a?.[42];\n        } while (console.log(\"PASS\"));\n    }\n    expect: {\n        do {\n            var a = a?.[42];\n        } while (console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_4928: {\n    options = {\n        ie: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = a?.[function f() {\n            f(a);\n        }];\n        console.log(typeof f);\n    }\n    expect: {\n        var a = a?.[function f() {\n            f(a);\n        }];\n        console.log(typeof f);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\nissue_4947_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        console.log(console.foo ? 42..p : console.bar?.p);\n    }\n    expect: {\n        console.log(console.foo ? 42..p : console.bar?.p);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=14\"\n}\n\nissue_4947_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var log = console.log, fail;\n        log(\"PASS\") ? log(42) : fail?.(42);\n    }\n    expect: {\n        var log = console.log, fail;\n        log(\"PASS\") ? log(42) : fail?.(42);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5039: {\n    options = {\n        ie: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = a?.[function f() {\n            f;\n            a;\n        }];\n        console.log(\"PASS\");\n    }\n    expect: {\n        var a = a?.[function f() {}];\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5091: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            var b = a.p;\n            var c;\n            b?.[c = \"FAIL 2\"];\n            return b || c;\n        }\n        console.log(f(\"FAIL 1\") || \"PASS\");\n    }\n    expect: {\n        function f(a) {\n            var a = a.p;\n            var c;\n            a?.[c = \"FAIL 2\"];\n            return a || c;\n        }\n        console.log(f(\"FAIL 1\") || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5292_dot: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            }\n        };\n        o?.p;\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            }\n        };\n        o?.p;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5292_dot_pure_getters: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            }\n        };\n        o?.p;\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            }\n        };\n    }\n}\n\nissue_5292_dot_pure_getters_strict: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            }\n        };\n        o?.p;\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            }\n        };\n        o?.p;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5292_sub: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"foo\");\n            }\n        };\n        o?.[console.log(\"bar\"), \"p\"];\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"foo\");\n            }\n        };\n        o?.[console.log(\"bar\"), \"p\"];\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=14\"\n}\n\nissue_5292_sub_pure_getters: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"foo\");\n            }\n        };\n        o?.[console.log(\"bar\"), \"p\"];\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"foo\");\n            }\n        };\n        o?.[console.log(\"bar\")];\n    }\n}\n\nissue_5292_sub_pure_getters_strict: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"foo\");\n            }\n        };\n        o?.[console.log(\"bar\"), \"p\"];\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"foo\");\n            }\n        };\n        o?.[console.log(\"bar\"), \"p\"];\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n    node_version: \">=14\"\n}\n\nissue_5856: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        try {\n            var a;\n            a?.p;\n            a.q;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            var a;\n            a?.p;\n            a.q;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5900: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 42, b = \"PASS\";\n        a[a = null];\n        a?.[b = \"FAIL\"];\n        console.log(b);\n    }\n    expect: {\n        var a = 42, b = \"PASS\";\n        a[a = null];\n        a?.[b = \"FAIL\"];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5905: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        do {\n            var b = a++;\n            var c = c ?? b?.[42];\n        } while (console.log(\"PASS\"));\n    }\n    expect: {\n        var a;\n        do {\n            a++;\n        } while (console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n\nissue_5912: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a, b = {};\n        b = b.p;\n        a?.[b.q];\n        try {\n            b.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a, b = {};\n        b = b.p;\n        a?.[b.q];\n        try {\n            b.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=14\"\n}\n"
  },
  {
    "path": "test/compress/preserve_line.js",
    "content": "return_1: {\n    beautify = {\n        beautify: false,\n        preserve_line: true,\n    }\n    input: {\n        console.log(function f() {\n            return (\n                f.toString() != 42\n            );\n        }());\n    }\n    expect_exact: [\n        \"console.log(function f(){\",\n        \"\",\n        \"return 42!=f.toString()}());\",\n    ]\n    expect_stdout: \"true\"\n}\n\nreturn_2: {\n    beautify = {\n        beautify: true,\n        preserve_line: true,\n    }\n    input: {\n        console.log(function f() {\n            return (\n                f.toString() != 42\n            );\n        }());\n    }\n    expect_exact: [\n        \"console.log(function f() {\",\n        \"\",\n        \"    return 42 != f.toString();\",\n        \"}());\",\n    ]\n    expect_stdout: \"true\"\n}\n\nreturn_3: {\n    options = {}\n    beautify = {\n        beautify: false,\n        preserve_line: true,\n    }\n    input: {\n        console.log(function f() {\n            return (\n                f.toString() != 42\n            );\n        }());\n    }\n    expect_exact: [\n        \"console.log(function f(){\",\n        \"\",\n        \"return 42!=f.toString()}());\",\n    ]\n    expect_stdout: \"true\"\n}\n\nreturn_4: {\n    options = {}\n    beautify = {\n        beautify: true,\n        preserve_line: true,\n    }\n    input: {\n        console.log(function f() {\n            return (\n                f.toString() != 42\n            );\n        }());\n    }\n    expect_exact: [\n        \"console.log(function f() {\",\n        \"\",\n        \"    return 42 != f.toString();\",\n        \"}());\",\n    ]\n    expect_stdout: \"true\"\n}\n\nreturn_5: {\n    beautify = {\n        beautify: false,\n        preserve_line: true,\n    }\n    input: {\n        _is_selected = function(tags, slug) {\n            var ref;\n            return (ref = _.find(tags, {\n                slug: slug\n            })) != null ? ref.selected : void 0;\n        };\n    }\n    expect_exact: [\n        \"_is_selected=function(tags,slug){\",\n        \"var ref;\",\n        \"\",\n        \"\",\n        \"return null!=(ref=_.find(tags,{slug:slug}))?ref.selected:void 0};\",\n    ]\n}\n\nreturn_6: {\n    beautify = {\n        beautify: true,\n        preserve_line: true,\n    }\n    input: {\n        _is_selected = function(tags, slug) {\n            var ref;\n            return (ref = _.find(tags, {\n                slug: slug\n            })) != null ? ref.selected : void 0;\n        };\n    }\n    expect_exact: [\n        \"_is_selected = function(tags, slug) {\",\n        \"    var ref;\",\n        \"\",\n        \"\",\n        \"    return null != (ref = _.find(tags, {\",\n        \"        slug: slug\",\n        \"    })) ? ref.selected : void 0;\",\n        \"};\",\n    ]\n}\n\nreturn_7: {\n    options = {}\n    mangle = {}\n    beautify = {\n        beautify: false,\n        preserve_line: true,\n    }\n    input: {\n        _is_selected = function(tags, slug) {\n            var ref;\n            return (ref = _.find(tags, {\n                slug: slug\n            })) != null ? ref.selected : void 0;\n        };\n    }\n    expect_exact: [\n        \"_is_selected=function(e,l){\",\n        \"var n;\",\n        \"\",\n        \"\",\n        \"return null!=(n=_.find(e,{slug:l}))?n.selected:void 0};\",\n    ]\n}\n\nreturn_8: {\n    options = {}\n    mangle = {}\n    beautify = {\n        beautify: true,\n        preserve_line: true,\n    }\n    input: {\n        _is_selected = function(tags, slug) {\n            var ref;\n            return (ref = _.find(tags, {\n                slug: slug\n            })) != null ? ref.selected : void 0;\n        };\n    }\n    expect_exact: [\n        \"_is_selected = function(e, l) {\",\n        \"    var n;\",\n        \"\",\n        \"\",\n        \"    return null != (n = _.find(e, {\",\n        \"        slug: l\",\n        \"    })) ? n.selected : void 0;\",\n        \"};\",\n    ]\n}\n"
  },
  {
    "path": "test/compress/properties.js",
    "content": "keep_properties: {\n    options = {\n        evaluate: true,\n        properties: false,\n    }\n    input: {\n        a[\"foo\"] = \"bar\";\n    }\n    expect: {\n        a[\"foo\"] = \"bar\";\n    }\n}\n\ndot_properties: {\n    options = {\n        evaluate: true,\n        properties: true,\n    }\n    beautify = {\n        ie: true,\n    }\n    input: {\n        a[\"foo\"] = \"bar\";\n        a[\"if\"] = \"if\";\n        a[\"*\"] = \"asterisk\";\n        a[\"\\u0EB3\"] = \"unicode\";\n        a[\"\"] = \"whitespace\";\n        a[\"1_1\"] = \"foo\";\n    }\n    expect: {\n        a.foo = \"bar\";\n        a[\"if\"] = \"if\";\n        a[\"*\"] = \"asterisk\";\n        a[\"\\u0EB3\"] = \"unicode\";\n        a[\"\"] = \"whitespace\";\n        a[\"1_1\"] = \"foo\";\n    }\n}\n\ndot_properties_es5: {\n    options = {\n        evaluate: true,\n        properties: true,\n    }\n    beautify = {\n        ie: false,\n    }\n    input: {\n        a[\"foo\"] = \"bar\";\n        a[\"if\"] = \"if\";\n        a[\"*\"] = \"asterisk\";\n        a[\"\\u0EB3\"] = \"unicode\";\n        a[\"\"] = \"whitespace\";\n    }\n    expect: {\n        a.foo = \"bar\";\n        a.if = \"if\";\n        a[\"*\"] = \"asterisk\";\n        a[\"\\u0EB3\"] = \"unicode\";\n        a[\"\"] = \"whitespace\";\n    }\n}\n\nsub_properties: {\n    options = {\n        evaluate: true,\n        properties: true,\n    }\n    input: {\n        a[0] = 0;\n        a[\"0\"] = 1;\n        a[3.14] = 2;\n        a[\"3\" + \".14\"] = 3;\n        a[\"i\" + \"f\"] = 4;\n        a[\"foo\" + \" bar\"] = 5;\n        a[0 / 0] = 6;\n        a[null] = 7;\n        a[undefined] = 8;\n    }\n    expect: {\n        a[0] = 0;\n        a[0] = 1;\n        a[3.14] = 2;\n        a[3.14] = 3;\n        a.if = 4;\n        a[\"foo bar\"] = 5;\n        a.NaN = 6;\n        a.null = 7;\n        a[void 0] = 8;\n    }\n}\n\nevaluate_array_length: {\n    options = {\n        evaluate: true,\n        properties: true,\n        unsafe: true,\n    }\n    input: {\n        a = [1, 2, 3].length;\n        a = [1, 2, 3].join()[\"len\" + \"gth\"];\n        a = [1, 2, b].length;\n        a = [1, 2, 3].join(b).length;\n    }\n    expect: {\n        a = 3;\n        a = 5;\n        a = [1, 2, b].length;\n        a = [1, 2, 3].join(b).length;\n    }\n}\n\nevaluate_string_length: {\n    options = {\n        evaluate: true,\n        properties: true,\n        unsafe: true,\n    }\n    input: {\n        a = \"foo\".length;\n        a = (\"foo\" + \"bar\")[\"len\" + \"gth\"];\n        a = b.length;\n        a = (\"foo\" + b).length;\n    }\n    expect: {\n        a = 3;\n        a = 6;\n        a = b.length;\n        a = (\"foo\" + b).length;\n    }\n}\n\nmangle_properties_1: {\n    mangle = {\n        properties: {\n            domprops: true,\n            keep_quoted: false,\n        },\n    }\n    input: {\n        a[\"foo\"] = \"bar\";\n        a.color = \"red\";\n        x = {\"bar\": 10};\n        a.run(x.bar, a.foo);\n        a['run']({color: \"blue\", foo: \"baz\"});\n    }\n    expect: {\n        a[\"a\"] = \"bar\";\n        a.b = \"red\";\n        x = {o: 10};\n        a.run(x.o, a.a);\n        a['run']({b: \"blue\", a: \"baz\"});\n    }\n}\n\nmangle_properties_2: {\n    mangle = {\n        properties: {\n            domprops: true,\n            reserved: [\n                \"value\",\n            ],\n        },\n    }\n    input: {\n        var o = {\n            prop1: 1,\n        };\n        Object.defineProperty(o, \"prop2\", {\n            value: 2,\n        });\n        Object.defineProperties(o, {\n            prop3: {\n                value: 3,\n            },\n        });\n        console.log(\"prop1\", o.prop1, \"prop1\" in o);\n        console.log(\"prop2\", o.prop2, o.hasOwnProperty(\"prop2\"));\n        console.log(\"prop3\", o.prop3, Object.getOwnPropertyDescriptor(o, \"prop3\").value);\n    }\n    expect: {\n        var o = {\n            o: 1,\n        };\n        Object.defineProperty(o, \"p\", {\n            value: 2,\n        });\n        Object.defineProperties(o, {\n            r: {\n                value: 3,\n            },\n        });\n        console.log(\"prop1\", o.o, \"o\" in o);\n        console.log(\"prop2\", o.p, o.hasOwnProperty(\"p\"));\n        console.log(\"prop3\", o.r, Object.getOwnPropertyDescriptor(o, \"r\").value);\n    }\n    expect_stdout: [\n        \"prop1 1 true\",\n        \"prop2 2 true\",\n        \"prop3 3 3\",\n    ]\n}\n\nmangle_properties_3: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        console.log({\n            [(console, \"foo\")]: \"PASS\",\n        }.foo);\n    }\n    expect: {\n        console.log({\n            [(console, \"o\")]: \"PASS\",\n        }.o);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nmangle_unquoted_properties: {\n    options = {\n        evaluate: true,\n        properties: false,\n    }\n    mangle = {\n        properties: {\n            builtins: true,\n            domprops: true,\n            keep_quoted: true,\n        },\n    }\n    beautify = {\n        beautify: false,\n        quote_style: 3,\n        keep_quoted_props: true,\n    }\n    input: {\n        a.top = 1;\n        function f1() {\n            a[\"foo\"] = \"bar\";\n            a.color = \"red\";\n            a.stuff = 2;\n            x = {\"bar\": 10, size: 7};\n            a.size = 9;\n        }\n        function f2() {\n            a.foo = \"bar\";\n            a['color'] = \"red\";\n            x = {bar: 10, size: 7};\n            a.size = 9;\n            a.stuff = 3;\n        }\n    }\n    expect: {\n        a.a = 1;\n        function f1() {\n            a[\"foo\"] = \"bar\";\n            a.color = \"red\";\n            a.r = 2;\n            x = {\"bar\": 10, b: 7};\n            a.b = 9;\n        }\n        function f2() {\n            a.foo = \"bar\";\n            a['color'] = \"red\";\n            x = {bar: 10, b: 7};\n            a.b = 9;\n            a.r = 3;\n        }\n    }\n}\n\nmangle_debug: {\n    mangle = {\n        properties: {\n            debug: \"\",\n        },\n    }\n    input: {\n        a.foo = \"bar\";\n        x = { baz: \"ban\" };\n    }\n    expect: {\n        a._$foo$_ = \"bar\";\n        x = { _$baz$_: \"ban\" };\n    }\n}\n\nmangle_debug_true: {\n    mangle = {\n        properties: {\n            debug: true,\n        },\n    }\n    input: {\n        a.foo = \"bar\";\n        x = { baz: \"ban\" };\n    }\n    expect: {\n        a._$foo$_ = \"bar\";\n        x = { _$baz$_: \"ban\" };\n    }\n}\n\nmangle_debug_suffix: {\n    mangle = {\n        properties: {\n            debug: \"XYZ\",\n        },\n    }\n    input: {\n        a.foo = \"bar\";\n        x = { baz: \"ban\" };\n    }\n    expect: {\n        a._$foo$XYZ_ = \"bar\";\n        x = { _$baz$XYZ_: \"ban\" };\n    }\n}\n\nmangle_debug_suffix_keep_quoted: {\n    options = {\n        evaluate: true,\n        properties: false,\n    }\n    mangle = {\n        properties: {\n            builtins: true,\n            debug: \"XYZ\",\n            domprops: true,\n            keep_quoted: true,\n            reserved: [],\n        },\n    }\n    beautify = {\n        beautify: false,\n        quote_style: 3,\n        keep_quoted_props: true,\n    }\n    input: {\n        a.top = 1;\n        function f1() {\n            a[\"foo\"] = \"bar\";\n            a.color = \"red\";\n            a.stuff = 2;\n            x = {\"bar\": 10, size: 7};\n            a.size = 9;\n        }\n        function f2() {\n            a.foo = \"bar\";\n            a['color'] = \"red\";\n            x = {bar: 10, size: 7};\n            a.size = 9;\n            a.stuff = 3;\n        }\n    }\n    expect: {\n        a._$top$XYZ_ = 1;\n        function f1() {\n            a[\"foo\"] = \"bar\";\n            a.color = \"red\";\n            a._$stuff$XYZ_ = 2;\n            x = {\"bar\": 10, _$size$XYZ_: 7};\n            a._$size$XYZ_ = 9;\n        }\n        function f2() {\n            a.foo = \"bar\";\n            a['color'] = \"red\";\n            x = {bar: 10, _$size$XYZ_: 7};\n            a._$size$XYZ_ = 9;\n            a._$stuff$XYZ_ = 3;\n        }\n    }\n}\n\nkeep_substituted_property: {\n    options = {\n        evaluate: true,\n        properties: true,\n        reduce_vars: true,\n    }\n    mangle = {\n        properties: {\n            keep_quoted: true,\n        },\n    }\n    input: {\n        var o = { p: [] };\n        function f(b) {\n            return o[b];\n        }\n        function g() {\n            var a = \"p\";\n            return o[a] === f(a);\n        }\n        console.log(g() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var o = { p: [] };\n        function f(n) {\n            return o[n];\n        }\n        function g() {\n            var n = \"p\";\n            return o.p === f(n);\n        }\n        console.log(g() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nkeep_substituted_property_quotes: {\n    options = {\n        evaluate: true,\n        properties: true,\n        reduce_vars: true,\n    }\n    beautify = {\n        keep_quoted_props: true,\n    }\n    input: {\n        function f(o) {\n            var a = \"p\";\n            return o[a];\n        }\n        console.log(f({ p: \"PASS\" }));\n    }\n    expect: {\n        function f(o) {\n            var a = \"p\";\n            return o[\"p\"];\n        }\n        console.log(f({ p: \"PASS\" }));\n    }\n    expect_stdout: \"PASS\"\n}\n\nfirst_256_chars_as_properties: {\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        // Note: some of these unicode character keys are not visible on github.com\n        var o = {\n            \"\\0\":0,\"\u0001\":1,\"\u0002\":2,\"\u0003\":3,\"\u0004\":4,\"\u0005\":5,\"\u0006\":6,\"\u0007\":7,\"\\b\":8,\n            \"\\t\":9,\"\\n\":10,\"\\v\":11,\"\\f\":12,\"\\r\":13,\"\u000e\":14,\"\u000f\":15,\"\u0010\":16,\"\u0011\":17,\n            \"\u0012\":18,\"\u0013\":19,\"\u0014\":20,\"\u0015\":21,\"\u0016\":22,\"\u0017\":23,\"\u0018\":24,\"\u0019\":25,\"\u001a\":26,\n            \"\u001b\":27,\"\u001c\":28,\"\u001d\":29,\"\u001e\":30,\"\u001f\":31,\" \":32,\"!\":33,'\"':34,\"#\":35,\n            $:36,\"%\":37,\"&\":38,\"'\":39,\"(\":40,\")\":41,\"*\":42,\"+\":43,\",\":44,\n            \"-\":45,\".\":46,\"/\":47,\"0\":48,\"1\":49,\"2\":50,\"3\":51,\"4\":52,\"5\":53,\"6\":54,\"7\":55,\n            \"8\":56,\"9\":57,\":\":58,\";\":59,\"<\":60,\"=\":61,\">\":62,\"?\":63,\"@\":64,A:65,\n            B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,\n            O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,\"[\":91,\n            \"\\\\\":92,\"]\":93,\"^\":94,_:95,\"`\":96,a:97,b:98,c:99,d:100,e:101,\n            f:102,g:103,h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,\n            q:113,r:114,s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,\"{\":123,\n            \"|\":124,\"}\":125,\"~\":126,\"\":127,\"\":128,\"\":129,\"\":130,\"\":131,\n            \"\":132,\"\":133,\"\":134,\"\":135,\"\":136,\"\":137,\"\":138,\"\":139,\n            \"\":140,\"\":141,\"\":142,\"\":143,\"\":144,\"\":145,\"\":146,\"\":147,\n            \"\":148,\"\":149,\"\":150,\"\":151,\"\":152,\"\":153,\"\":154,\"\":155,\n            \"\":156,\"\":157,\"\":158,\"\":159,\" \":160,\"¡\":161,\"¢\":162,\"£\":163,\n            \"¤\":164,\"¥\":165,\"¦\":166,\"§\":167,\"¨\":168,\"©\":169,\"ª\":170,\"«\":171,\n            \"¬\":172,\"­\":173,\"®\":174,\"¯\":175,\"°\":176,\"±\":177,\"²\":178,\"³\":179,\n            \"´\":180,\"µ\":181,\"¶\":182,\"·\":183,\"¸\":184,\"¹\":185,\"º\":186,\"»\":187,\n            \"¼\":188,\"½\":189,\"¾\":190,\"¿\":191,\"À\":192,\"Á\":193,\"Â\":194,\"Ã\":195,\n            \"Ä\":196,\"Å\":197,\"Æ\":198,\"Ç\":199,\"È\":200,\"É\":201,\"Ê\":202,\"Ë\":203,\n            \"Ì\":204,\"Í\":205,\"Î\":206,\"Ï\":207,\"Ð\":208,\"Ñ\":209,\"Ò\":210,\"Ó\":211,\n            \"Ô\":212,\"Õ\":213,\"Ö\":214,\"×\":215,\"Ø\":216,\"Ù\":217,\"Ú\":218,\"Û\":219,\n            \"Ü\":220,\"Ý\":221,\"Þ\":222,\"ß\":223,\"à\":224,\"á\":225,\"â\":226,\"ã\":227,\n            \"ä\":228,\"å\":229,\"æ\":230,\"ç\":231,\"è\":232,\"é\":233,\"ê\":234,\"ë\":235,\n            \"ì\":236,\"í\":237,\"î\":238,\"ï\":239,\"ð\":240,\"ñ\":241,\"ò\":242,\"ó\":243,\n            \"ô\":244,\"õ\":245,\"ö\":246,\"÷\":247,\"ø\":248,\"ù\":249,\"ú\":250,\"û\":251,\n            \"ü\":252,\"ý\":253,\"þ\":254,\"ÿ\":255\n        };\n    }\n    expect: {\n        var o = {\n            \"\\0\":0,\"\\x01\":1,\"\\x02\":2,\"\\x03\":3,\"\\x04\":4,\"\\x05\":5,\"\\x06\":6,\n            \"\\x07\":7,\"\\b\":8,\"\\t\":9,\"\\n\":10,\"\\v\":11,\"\\f\":12,\"\\r\":13,\"\\x0e\":14,\n            \"\\x0f\":15,\"\\x10\":16,\"\\x11\":17,\"\\x12\":18,\"\\x13\":19,\"\\x14\":20,\"\\x15\":21,\n            \"\\x16\":22,\"\\x17\":23,\"\\x18\":24,\"\\x19\":25,\"\\x1a\":26,\"\\x1b\":27,\"\\x1c\":28,\n            \"\\x1d\":29,\"\\x1e\":30,\"\\x1f\":31,\" \":32,\"!\":33,'\"':34,\"#\":35,$:36,\n            \"%\":37,\"&\":38,\"'\":39,\"(\":40,\")\":41,\"*\":42,\"+\":43,\",\":44,\"-\":45,\n            \".\":46,\"/\":47,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,\n            \":\":58,\";\":59,\"<\":60,\"=\":61,\">\":62,\"?\":63,\"@\":64,A:65,B:66,C:67,\n            D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,\n            Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,\"[\":91,\"\\\\\":92,\n            \"]\":93,\"^\":94,_:95,\"`\":96,a:97,b:98,c:99,d:100,e:101,f:102,g:103,\n            h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,q:113,r:114,\n            s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,\"{\":123,\"|\":124,\n            \"}\":125,\"~\":126,\"\\x7f\":127,\"\\x80\":128,\"\\x81\":129,\"\\x82\":130,\"\\x83\":131,\n            \"\\x84\":132,\"\\x85\":133,\"\\x86\":134,\"\\x87\":135,\"\\x88\":136,\"\\x89\":137,\n            \"\\x8a\":138,\"\\x8b\":139,\"\\x8c\":140,\"\\x8d\":141,\"\\x8e\":142,\"\\x8f\":143,\n            \"\\x90\":144,\"\\x91\":145,\"\\x92\":146,\"\\x93\":147,\"\\x94\":148,\"\\x95\":149,\n            \"\\x96\":150,\"\\x97\":151,\"\\x98\":152,\"\\x99\":153,\"\\x9a\":154,\"\\x9b\":155,\n            \"\\x9c\":156,\"\\x9d\":157,\"\\x9e\":158,\"\\x9f\":159,\"\\xa0\":160,\"\\xa1\":161,\n            \"\\xa2\":162,\"\\xa3\":163,\"\\xa4\":164,\"\\xa5\":165,\"\\xa6\":166,\"\\xa7\":167,\n            \"\\xa8\":168,\"\\xa9\":169,\"\\xaa\":170,\"\\xab\":171,\"\\xac\":172,\"\\xad\":173,\n            \"\\xae\":174,\"\\xaf\":175,\"\\xb0\":176,\"\\xb1\":177,\"\\xb2\":178,\"\\xb3\":179,\n            \"\\xb4\":180,\"\\xb5\":181,\"\\xb6\":182,\"\\xb7\":183,\"\\xb8\":184,\"\\xb9\":185,\n            \"\\xba\":186,\"\\xbb\":187,\"\\xbc\":188,\"\\xbd\":189,\"\\xbe\":190,\"\\xbf\":191,\n            \"\\xc0\":192,\"\\xc1\":193,\"\\xc2\":194,\"\\xc3\":195,\"\\xc4\":196,\"\\xc5\":197,\n            \"\\xc6\":198,\"\\xc7\":199,\"\\xc8\":200,\"\\xc9\":201,\"\\xca\":202,\"\\xcb\":203,\n            \"\\xcc\":204,\"\\xcd\":205,\"\\xce\":206,\"\\xcf\":207,\"\\xd0\":208,\"\\xd1\":209,\n            \"\\xd2\":210,\"\\xd3\":211,\"\\xd4\":212,\"\\xd5\":213,\"\\xd6\":214,\"\\xd7\":215,\n            \"\\xd8\":216,\"\\xd9\":217,\"\\xda\":218,\"\\xdb\":219,\"\\xdc\":220,\"\\xdd\":221,\n            \"\\xde\":222,\"\\xdf\":223,\"\\xe0\":224,\"\\xe1\":225,\"\\xe2\":226,\"\\xe3\":227,\n            \"\\xe4\":228,\"\\xe5\":229,\"\\xe6\":230,\"\\xe7\":231,\"\\xe8\":232,\"\\xe9\":233,\n            \"\\xea\":234,\"\\xeb\":235,\"\\xec\":236,\"\\xed\":237,\"\\xee\":238,\"\\xef\":239,\n            \"\\xf0\":240,\"\\xf1\":241,\"\\xf2\":242,\"\\xf3\":243,\"\\xf4\":244,\"\\xf5\":245,\n            \"\\xf6\":246,\"\\xf7\":247,\"\\xf8\":248,\"\\xf9\":249,\"\\xfa\":250,\"\\xfb\":251,\n            \"\\xfc\":252,\"\\xfd\":253,\"\\xfe\":254,\"\\xff\":255\n        };\n    }\n}\n\nfirst_256_unicode_chars_as_properties: {\n    input: {\n        var o = {\n            \"\\u0000\":   0, \"\\u0001\":   1, \"\\u0002\":   2, \"\\u0003\":   3, \"\\u0004\":   4, \"\\u0005\":   5,\n            \"\\u0006\":   6, \"\\u0007\":   7, \"\\u0008\":   8, \"\\u0009\":   9, \"\\u000A\":  10, \"\\u000B\":  11,\n            \"\\u000C\":  12, \"\\u000D\":  13, \"\\u000E\":  14, \"\\u000F\":  15, \"\\u0010\":  16, \"\\u0011\":  17,\n            \"\\u0012\":  18, \"\\u0013\":  19, \"\\u0014\":  20, \"\\u0015\":  21, \"\\u0016\":  22, \"\\u0017\":  23,\n            \"\\u0018\":  24, \"\\u0019\":  25, \"\\u001A\":  26, \"\\u001B\":  27, \"\\u001C\":  28, \"\\u001D\":  29,\n            \"\\u001E\":  30, \"\\u001F\":  31, \"\\u0020\":  32, \"\\u0021\":  33, \"\\u0022\":  34, \"\\u0023\":  35,\n            \"\\u0024\":  36, \"\\u0025\":  37, \"\\u0026\":  38, \"\\u0027\":  39, \"\\u0028\":  40, \"\\u0029\":  41,\n            \"\\u002A\":  42, \"\\u002B\":  43, \"\\u002C\":  44, \"\\u002D\":  45, \"\\u002E\":  46, \"\\u002F\":  47,\n            \"\\u0030\":  48, \"\\u0031\":  49, \"\\u0032\":  50, \"\\u0033\":  51, \"\\u0034\":  52, \"\\u0035\":  53,\n            \"\\u0036\":  54, \"\\u0037\":  55, \"\\u0038\":  56, \"\\u0039\":  57, \"\\u003A\":  58, \"\\u003B\":  59,\n            \"\\u003C\":  60, \"\\u003D\":  61, \"\\u003E\":  62, \"\\u003F\":  63, \"\\u0040\":  64, \"\\u0041\":  65,\n            \"\\u0042\":  66, \"\\u0043\":  67, \"\\u0044\":  68, \"\\u0045\":  69, \"\\u0046\":  70, \"\\u0047\":  71,\n            \"\\u0048\":  72, \"\\u0049\":  73, \"\\u004A\":  74, \"\\u004B\":  75, \"\\u004C\":  76, \"\\u004D\":  77,\n            \"\\u004E\":  78, \"\\u004F\":  79, \"\\u0050\":  80, \"\\u0051\":  81, \"\\u0052\":  82, \"\\u0053\":  83,\n            \"\\u0054\":  84, \"\\u0055\":  85, \"\\u0056\":  86, \"\\u0057\":  87, \"\\u0058\":  88, \"\\u0059\":  89,\n            \"\\u005A\":  90, \"\\u005B\":  91, \"\\u005C\":  92, \"\\u005D\":  93, \"\\u005E\":  94, \"\\u005F\":  95,\n            \"\\u0060\":  96, \"\\u0061\":  97, \"\\u0062\":  98, \"\\u0063\":  99, \"\\u0064\": 100, \"\\u0065\": 101,\n            \"\\u0066\": 102, \"\\u0067\": 103, \"\\u0068\": 104, \"\\u0069\": 105, \"\\u006A\": 106, \"\\u006B\": 107,\n            \"\\u006C\": 108, \"\\u006D\": 109, \"\\u006E\": 110, \"\\u006F\": 111, \"\\u0070\": 112, \"\\u0071\": 113,\n            \"\\u0072\": 114, \"\\u0073\": 115, \"\\u0074\": 116, \"\\u0075\": 117, \"\\u0076\": 118, \"\\u0077\": 119,\n            \"\\u0078\": 120, \"\\u0079\": 121, \"\\u007A\": 122, \"\\u007B\": 123, \"\\u007C\": 124, \"\\u007D\": 125,\n            \"\\u007E\": 126, \"\\u007F\": 127, \"\\u0080\": 128, \"\\u0081\": 129, \"\\u0082\": 130, \"\\u0083\": 131,\n            \"\\u0084\": 132, \"\\u0085\": 133, \"\\u0086\": 134, \"\\u0087\": 135, \"\\u0088\": 136, \"\\u0089\": 137,\n            \"\\u008A\": 138, \"\\u008B\": 139, \"\\u008C\": 140, \"\\u008D\": 141, \"\\u008E\": 142, \"\\u008F\": 143,\n            \"\\u0090\": 144, \"\\u0091\": 145, \"\\u0092\": 146, \"\\u0093\": 147, \"\\u0094\": 148, \"\\u0095\": 149,\n            \"\\u0096\": 150, \"\\u0097\": 151, \"\\u0098\": 152, \"\\u0099\": 153, \"\\u009A\": 154, \"\\u009B\": 155,\n            \"\\u009C\": 156, \"\\u009D\": 157, \"\\u009E\": 158, \"\\u009F\": 159, \"\\u00A0\": 160, \"\\u00A1\": 161,\n            \"\\u00A2\": 162, \"\\u00A3\": 163, \"\\u00A4\": 164, \"\\u00A5\": 165, \"\\u00A6\": 166, \"\\u00A7\": 167,\n            \"\\u00A8\": 168, \"\\u00A9\": 169, \"\\u00AA\": 170, \"\\u00AB\": 171, \"\\u00AC\": 172, \"\\u00AD\": 173,\n            \"\\u00AE\": 174, \"\\u00AF\": 175, \"\\u00B0\": 176, \"\\u00B1\": 177, \"\\u00B2\": 178, \"\\u00B3\": 179,\n            \"\\u00B4\": 180, \"\\u00B5\": 181, \"\\u00B6\": 182, \"\\u00B7\": 183, \"\\u00B8\": 184, \"\\u00B9\": 185,\n            \"\\u00BA\": 186, \"\\u00BB\": 187, \"\\u00BC\": 188, \"\\u00BD\": 189, \"\\u00BE\": 190, \"\\u00BF\": 191,\n            \"\\u00C0\": 192, \"\\u00C1\": 193, \"\\u00C2\": 194, \"\\u00C3\": 195, \"\\u00C4\": 196, \"\\u00C5\": 197,\n            \"\\u00C6\": 198, \"\\u00C7\": 199, \"\\u00C8\": 200, \"\\u00C9\": 201, \"\\u00CA\": 202, \"\\u00CB\": 203,\n            \"\\u00CC\": 204, \"\\u00CD\": 205, \"\\u00CE\": 206, \"\\u00CF\": 207, \"\\u00D0\": 208, \"\\u00D1\": 209,\n            \"\\u00D2\": 210, \"\\u00D3\": 211, \"\\u00D4\": 212, \"\\u00D5\": 213, \"\\u00D6\": 214, \"\\u00D7\": 215,\n            \"\\u00D8\": 216, \"\\u00D9\": 217, \"\\u00DA\": 218, \"\\u00DB\": 219, \"\\u00DC\": 220, \"\\u00DD\": 221,\n            \"\\u00DE\": 222, \"\\u00DF\": 223, \"\\u00E0\": 224, \"\\u00E1\": 225, \"\\u00E2\": 226, \"\\u00E3\": 227,\n            \"\\u00E4\": 228, \"\\u00E5\": 229, \"\\u00E6\": 230, \"\\u00E7\": 231, \"\\u00E8\": 232, \"\\u00E9\": 233,\n            \"\\u00EA\": 234, \"\\u00EB\": 235, \"\\u00EC\": 236, \"\\u00ED\": 237, \"\\u00EE\": 238, \"\\u00EF\": 239,\n            \"\\u00F0\": 240, \"\\u00F1\": 241, \"\\u00F2\": 242, \"\\u00F3\": 243, \"\\u00F4\": 244, \"\\u00F5\": 245,\n            \"\\u00F6\": 246, \"\\u00F7\": 247, \"\\u00F8\": 248, \"\\u00F9\": 249, \"\\u00FA\": 250, \"\\u00FB\": 251,\n            \"\\u00FC\": 252, \"\\u00FD\": 253, \"\\u00FE\": 254, \"\\u00FF\": 255\n        };\n    }\n    expect: {\n        var o = {\n            \"\\0\":0,\"\\x01\":1,\"\\x02\":2,\"\\x03\":3,\"\\x04\":4,\"\\x05\":5,\"\\x06\":6,\n            \"\\x07\":7,\"\\b\":8,\"\\t\":9,\"\\n\":10,\"\\v\":11,\"\\f\":12,\"\\r\":13,\"\\x0e\":14,\n            \"\\x0f\":15,\"\\x10\":16,\"\\x11\":17,\"\\x12\":18,\"\\x13\":19,\"\\x14\":20,\"\\x15\":21,\n            \"\\x16\":22,\"\\x17\":23,\"\\x18\":24,\"\\x19\":25,\"\\x1a\":26,\"\\x1b\":27,\"\\x1c\":28,\n            \"\\x1d\":29,\"\\x1e\":30,\"\\x1f\":31,\" \":32,\"!\":33,'\"':34,\"#\":35,$:36,\n            \"%\":37,\"&\":38,\"'\":39,\"(\":40,\")\":41,\"*\":42,\"+\":43,\",\":44,\"-\":45,\n            \".\":46,\"/\":47,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,\n            \":\":58,\";\":59,\"<\":60,\"=\":61,\">\":62,\"?\":63,\"@\":64,A:65,B:66,C:67,\n            D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,\n            Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,\"[\":91,\"\\\\\":92,\n            \"]\":93,\"^\":94,_:95,\"`\":96,a:97,b:98,c:99,d:100,e:101,f:102,g:103,\n            h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,q:113,r:114,\n            s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,\"{\":123,\"|\":124,\n            \"}\":125,\"~\":126,\"\\x7f\":127,\"\\x80\":128,\"\\x81\":129,\"\\x82\":130,\"\\x83\":131,\n            \"\\x84\":132,\"\\x85\":133,\"\\x86\":134,\"\\x87\":135,\"\\x88\":136,\"\\x89\":137,\n            \"\\x8a\":138,\"\\x8b\":139,\"\\x8c\":140,\"\\x8d\":141,\"\\x8e\":142,\"\\x8f\":143,\n            \"\\x90\":144,\"\\x91\":145,\"\\x92\":146,\"\\x93\":147,\"\\x94\":148,\"\\x95\":149,\n            \"\\x96\":150,\"\\x97\":151,\"\\x98\":152,\"\\x99\":153,\"\\x9a\":154,\"\\x9b\":155,\n            \"\\x9c\":156,\"\\x9d\":157,\"\\x9e\":158,\"\\x9f\":159,\"\\xa0\":160,\"\\xa1\":161,\n            \"\\xa2\":162,\"\\xa3\":163,\"\\xa4\":164,\"\\xa5\":165,\"\\xa6\":166,\"\\xa7\":167,\n            \"\\xa8\":168,\"\\xa9\":169,\"\\xaa\":170,\"\\xab\":171,\"\\xac\":172,\"\\xad\":173,\n            \"\\xae\":174,\"\\xaf\":175,\"\\xb0\":176,\"\\xb1\":177,\"\\xb2\":178,\"\\xb3\":179,\n            \"\\xb4\":180,\"\\xb5\":181,\"\\xb6\":182,\"\\xb7\":183,\"\\xb8\":184,\"\\xb9\":185,\n            \"\\xba\":186,\"\\xbb\":187,\"\\xbc\":188,\"\\xbd\":189,\"\\xbe\":190,\"\\xbf\":191,\n            \"\\xc0\":192,\"\\xc1\":193,\"\\xc2\":194,\"\\xc3\":195,\"\\xc4\":196,\"\\xc5\":197,\n            \"\\xc6\":198,\"\\xc7\":199,\"\\xc8\":200,\"\\xc9\":201,\"\\xca\":202,\"\\xcb\":203,\n            \"\\xcc\":204,\"\\xcd\":205,\"\\xce\":206,\"\\xcf\":207,\"\\xd0\":208,\"\\xd1\":209,\n            \"\\xd2\":210,\"\\xd3\":211,\"\\xd4\":212,\"\\xd5\":213,\"\\xd6\":214,\"\\xd7\":215,\n            \"\\xd8\":216,\"\\xd9\":217,\"\\xda\":218,\"\\xdb\":219,\"\\xdc\":220,\"\\xdd\":221,\n            \"\\xde\":222,\"\\xdf\":223,\"\\xe0\":224,\"\\xe1\":225,\"\\xe2\":226,\"\\xe3\":227,\n            \"\\xe4\":228,\"\\xe5\":229,\"\\xe6\":230,\"\\xe7\":231,\"\\xe8\":232,\"\\xe9\":233,\n            \"\\xea\":234,\"\\xeb\":235,\"\\xec\":236,\"\\xed\":237,\"\\xee\":238,\"\\xef\":239,\n            \"\\xf0\":240,\"\\xf1\":241,\"\\xf2\":242,\"\\xf3\":243,\"\\xf4\":244,\"\\xf5\":245,\n            \"\\xf6\":246,\"\\xf7\":247,\"\\xf8\":248,\"\\xf9\":249,\"\\xfa\":250,\"\\xfb\":251,\n            \"\\xfc\":252,\"\\xfd\":253,\"\\xfe\":254,\"\\xff\":255\n        };\n    }\n}\n\nfirst_256_hex_chars_as_properties: {\n    input: {\n        var o = {\n            \"\\x00\":   0, \"\\x01\":   1, \"\\x02\":   2, \"\\x03\":   3, \"\\x04\":   4, \"\\x05\":   5,\n            \"\\x06\":   6, \"\\x07\":   7, \"\\x08\":   8, \"\\x09\":   9, \"\\x0A\":  10, \"\\x0B\":  11,\n            \"\\x0C\":  12, \"\\x0D\":  13, \"\\x0E\":  14, \"\\x0F\":  15, \"\\x10\":  16, \"\\x11\":  17,\n            \"\\x12\":  18, \"\\x13\":  19, \"\\x14\":  20, \"\\x15\":  21, \"\\x16\":  22, \"\\x17\":  23,\n            \"\\x18\":  24, \"\\x19\":  25, \"\\x1A\":  26, \"\\x1B\":  27, \"\\x1C\":  28, \"\\x1D\":  29,\n            \"\\x1E\":  30, \"\\x1F\":  31, \"\\x20\":  32, \"\\x21\":  33, \"\\x22\":  34, \"\\x23\":  35,\n            \"\\x24\":  36, \"\\x25\":  37, \"\\x26\":  38, \"\\x27\":  39, \"\\x28\":  40, \"\\x29\":  41,\n            \"\\x2A\":  42, \"\\x2B\":  43, \"\\x2C\":  44, \"\\x2D\":  45, \"\\x2E\":  46, \"\\x2F\":  47,\n            \"\\x30\":  48, \"\\x31\":  49, \"\\x32\":  50, \"\\x33\":  51, \"\\x34\":  52, \"\\x35\":  53,\n            \"\\x36\":  54, \"\\x37\":  55, \"\\x38\":  56, \"\\x39\":  57, \"\\x3A\":  58, \"\\x3B\":  59,\n            \"\\x3C\":  60, \"\\x3D\":  61, \"\\x3E\":  62, \"\\x3F\":  63, \"\\x40\":  64, \"\\x41\":  65,\n            \"\\x42\":  66, \"\\x43\":  67, \"\\x44\":  68, \"\\x45\":  69, \"\\x46\":  70, \"\\x47\":  71,\n            \"\\x48\":  72, \"\\x49\":  73, \"\\x4A\":  74, \"\\x4B\":  75, \"\\x4C\":  76, \"\\x4D\":  77,\n            \"\\x4E\":  78, \"\\x4F\":  79, \"\\x50\":  80, \"\\x51\":  81, \"\\x52\":  82, \"\\x53\":  83,\n            \"\\x54\":  84, \"\\x55\":  85, \"\\x56\":  86, \"\\x57\":  87, \"\\x58\":  88, \"\\x59\":  89,\n            \"\\x5A\":  90, \"\\x5B\":  91, \"\\x5C\":  92, \"\\x5D\":  93, \"\\x5E\":  94, \"\\x5F\":  95,\n            \"\\x60\":  96, \"\\x61\":  97, \"\\x62\":  98, \"\\x63\":  99, \"\\x64\": 100, \"\\x65\": 101,\n            \"\\x66\": 102, \"\\x67\": 103, \"\\x68\": 104, \"\\x69\": 105, \"\\x6A\": 106, \"\\x6B\": 107,\n            \"\\x6C\": 108, \"\\x6D\": 109, \"\\x6E\": 110, \"\\x6F\": 111, \"\\x70\": 112, \"\\x71\": 113,\n            \"\\x72\": 114, \"\\x73\": 115, \"\\x74\": 116, \"\\x75\": 117, \"\\x76\": 118, \"\\x77\": 119,\n            \"\\x78\": 120, \"\\x79\": 121, \"\\x7A\": 122, \"\\x7B\": 123, \"\\x7C\": 124, \"\\x7D\": 125,\n            \"\\x7E\": 126, \"\\x7F\": 127, \"\\x80\": 128, \"\\x81\": 129, \"\\x82\": 130, \"\\x83\": 131,\n            \"\\x84\": 132, \"\\x85\": 133, \"\\x86\": 134, \"\\x87\": 135, \"\\x88\": 136, \"\\x89\": 137,\n            \"\\x8A\": 138, \"\\x8B\": 139, \"\\x8C\": 140, \"\\x8D\": 141, \"\\x8E\": 142, \"\\x8F\": 143,\n            \"\\x90\": 144, \"\\x91\": 145, \"\\x92\": 146, \"\\x93\": 147, \"\\x94\": 148, \"\\x95\": 149,\n            \"\\x96\": 150, \"\\x97\": 151, \"\\x98\": 152, \"\\x99\": 153, \"\\x9A\": 154, \"\\x9B\": 155,\n            \"\\x9C\": 156, \"\\x9D\": 157, \"\\x9E\": 158, \"\\x9F\": 159, \"\\xA0\": 160, \"\\xA1\": 161,\n            \"\\xA2\": 162, \"\\xA3\": 163, \"\\xA4\": 164, \"\\xA5\": 165, \"\\xA6\": 166, \"\\xA7\": 167,\n            \"\\xA8\": 168, \"\\xA9\": 169, \"\\xAA\": 170, \"\\xAB\": 171, \"\\xAC\": 172, \"\\xAD\": 173,\n            \"\\xAE\": 174, \"\\xAF\": 175, \"\\xB0\": 176, \"\\xB1\": 177, \"\\xB2\": 178, \"\\xB3\": 179,\n            \"\\xB4\": 180, \"\\xB5\": 181, \"\\xB6\": 182, \"\\xB7\": 183, \"\\xB8\": 184, \"\\xB9\": 185,\n            \"\\xBA\": 186, \"\\xBB\": 187, \"\\xBC\": 188, \"\\xBD\": 189, \"\\xBE\": 190, \"\\xBF\": 191,\n            \"\\xC0\": 192, \"\\xC1\": 193, \"\\xC2\": 194, \"\\xC3\": 195, \"\\xC4\": 196, \"\\xC5\": 197,\n            \"\\xC6\": 198, \"\\xC7\": 199, \"\\xC8\": 200, \"\\xC9\": 201, \"\\xCA\": 202, \"\\xCB\": 203,\n            \"\\xCC\": 204, \"\\xCD\": 205, \"\\xCE\": 206, \"\\xCF\": 207, \"\\xD0\": 208, \"\\xD1\": 209,\n            \"\\xD2\": 210, \"\\xD3\": 211, \"\\xD4\": 212, \"\\xD5\": 213, \"\\xD6\": 214, \"\\xD7\": 215,\n            \"\\xD8\": 216, \"\\xD9\": 217, \"\\xDA\": 218, \"\\xDB\": 219, \"\\xDC\": 220, \"\\xDD\": 221,\n            \"\\xDE\": 222, \"\\xDF\": 223, \"\\xE0\": 224, \"\\xE1\": 225, \"\\xE2\": 226, \"\\xE3\": 227,\n            \"\\xE4\": 228, \"\\xE5\": 229, \"\\xE6\": 230, \"\\xE7\": 231, \"\\xE8\": 232, \"\\xE9\": 233,\n            \"\\xEA\": 234, \"\\xEB\": 235, \"\\xEC\": 236, \"\\xED\": 237, \"\\xEE\": 238, \"\\xEF\": 239,\n            \"\\xF0\": 240, \"\\xF1\": 241, \"\\xF2\": 242, \"\\xF3\": 243, \"\\xF4\": 244, \"\\xF5\": 245,\n            \"\\xF6\": 246, \"\\xF7\": 247, \"\\xF8\": 248, \"\\xF9\": 249, \"\\xFA\": 250, \"\\xFB\": 251,\n            \"\\xFC\": 252, \"\\xFD\": 253, \"\\xFE\": 254, \"\\xFF\": 255\n        };\n    }\n    expect: {\n        var o = {\n            \"\\0\":0,\"\\x01\":1,\"\\x02\":2,\"\\x03\":3,\"\\x04\":4,\"\\x05\":5,\"\\x06\":6,\n            \"\\x07\":7,\"\\b\":8,\"\\t\":9,\"\\n\":10,\"\\v\":11,\"\\f\":12,\"\\r\":13,\"\\x0e\":14,\n            \"\\x0f\":15,\"\\x10\":16,\"\\x11\":17,\"\\x12\":18,\"\\x13\":19,\"\\x14\":20,\"\\x15\":21,\n            \"\\x16\":22,\"\\x17\":23,\"\\x18\":24,\"\\x19\":25,\"\\x1a\":26,\"\\x1b\":27,\"\\x1c\":28,\n            \"\\x1d\":29,\"\\x1e\":30,\"\\x1f\":31,\" \":32,\"!\":33,'\"':34,\"#\":35,$:36,\n            \"%\":37,\"&\":38,\"'\":39,\"(\":40,\")\":41,\"*\":42,\"+\":43,\",\":44,\"-\":45,\n            \".\":46,\"/\":47,0:48,1:49,2:50,3:51,4:52,5:53,6:54,7:55,8:56,9:57,\n            \":\":58,\";\":59,\"<\":60,\"=\":61,\">\":62,\"?\":63,\"@\":64,A:65,B:66,C:67,\n            D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,\n            Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,\"[\":91,\"\\\\\":92,\n            \"]\":93,\"^\":94,_:95,\"`\":96,a:97,b:98,c:99,d:100,e:101,f:102,g:103,\n            h:104,i:105,j:106,k:107,l:108,m:109,n:110,o:111,p:112,q:113,r:114,\n            s:115,t:116,u:117,v:118,w:119,x:120,y:121,z:122,\"{\":123,\"|\":124,\n            \"}\":125,\"~\":126,\"\\x7f\":127,\"\\x80\":128,\"\\x81\":129,\"\\x82\":130,\"\\x83\":131,\n            \"\\x84\":132,\"\\x85\":133,\"\\x86\":134,\"\\x87\":135,\"\\x88\":136,\"\\x89\":137,\n            \"\\x8a\":138,\"\\x8b\":139,\"\\x8c\":140,\"\\x8d\":141,\"\\x8e\":142,\"\\x8f\":143,\n            \"\\x90\":144,\"\\x91\":145,\"\\x92\":146,\"\\x93\":147,\"\\x94\":148,\"\\x95\":149,\n            \"\\x96\":150,\"\\x97\":151,\"\\x98\":152,\"\\x99\":153,\"\\x9a\":154,\"\\x9b\":155,\n            \"\\x9c\":156,\"\\x9d\":157,\"\\x9e\":158,\"\\x9f\":159,\"\\xa0\":160,\"\\xa1\":161,\n            \"\\xa2\":162,\"\\xa3\":163,\"\\xa4\":164,\"\\xa5\":165,\"\\xa6\":166,\"\\xa7\":167,\n            \"\\xa8\":168,\"\\xa9\":169,\"\\xaa\":170,\"\\xab\":171,\"\\xac\":172,\"\\xad\":173,\n            \"\\xae\":174,\"\\xaf\":175,\"\\xb0\":176,\"\\xb1\":177,\"\\xb2\":178,\"\\xb3\":179,\n            \"\\xb4\":180,\"\\xb5\":181,\"\\xb6\":182,\"\\xb7\":183,\"\\xb8\":184,\"\\xb9\":185,\n            \"\\xba\":186,\"\\xbb\":187,\"\\xbc\":188,\"\\xbd\":189,\"\\xbe\":190,\"\\xbf\":191,\n            \"\\xc0\":192,\"\\xc1\":193,\"\\xc2\":194,\"\\xc3\":195,\"\\xc4\":196,\"\\xc5\":197,\n            \"\\xc6\":198,\"\\xc7\":199,\"\\xc8\":200,\"\\xc9\":201,\"\\xca\":202,\"\\xcb\":203,\n            \"\\xcc\":204,\"\\xcd\":205,\"\\xce\":206,\"\\xcf\":207,\"\\xd0\":208,\"\\xd1\":209,\n            \"\\xd2\":210,\"\\xd3\":211,\"\\xd4\":212,\"\\xd5\":213,\"\\xd6\":214,\"\\xd7\":215,\n            \"\\xd8\":216,\"\\xd9\":217,\"\\xda\":218,\"\\xdb\":219,\"\\xdc\":220,\"\\xdd\":221,\n            \"\\xde\":222,\"\\xdf\":223,\"\\xe0\":224,\"\\xe1\":225,\"\\xe2\":226,\"\\xe3\":227,\n            \"\\xe4\":228,\"\\xe5\":229,\"\\xe6\":230,\"\\xe7\":231,\"\\xe8\":232,\"\\xe9\":233,\n            \"\\xea\":234,\"\\xeb\":235,\"\\xec\":236,\"\\xed\":237,\"\\xee\":238,\"\\xef\":239,\n            \"\\xf0\":240,\"\\xf1\":241,\"\\xf2\":242,\"\\xf3\":243,\"\\xf4\":244,\"\\xf5\":245,\n            \"\\xf6\":246,\"\\xf7\":247,\"\\xf8\":248,\"\\xf9\":249,\"\\xfa\":250,\"\\xfb\":251,\n            \"\\xfc\":252,\"\\xfd\":253,\"\\xfe\":254,\"\\xff\":255\n        };\n    }\n}\n\nnative_prototype: {\n    options = {\n        unsafe_proto: true,\n    }\n    input: {\n        Array.prototype.splice.apply(a, [1, 2, b, c]);\n        Function.prototype.call.apply(console.log, console, [ \"foo\" ]);\n        Number.prototype.toFixed.call(Math.PI, 2);\n        Object.prototype.hasOwnProperty.call(d, \"foo\");\n        RegExp.prototype.test.call(/foo/, \"bar\");\n        String.prototype.indexOf.call(e, \"bar\");\n    }\n    expect: {\n        [].splice.apply(a, [1, 2, b, c]);\n        (function() {}).call.apply(console.log, console, [ \"foo\" ]);\n        0..toFixed.call(Math.PI, 2);\n        ({}).hasOwnProperty.call(d, \"foo\");\n        /t/.test.call(/foo/, \"bar\");\n        \"\".indexOf.call(e, \"bar\");\n    }\n}\n\nnative_prototype_lhs: {\n    options = {\n        unsafe_proto: true,\n    }\n    input: {\n        console.log(function() {\n            Function.prototype.bar = \"PASS\";\n            return function() {};\n        }().bar);\n    }\n    expect: {\n        console.log(function() {\n            Function.prototype.bar = \"PASS\";\n            return function() {};\n        }().bar);\n    }\n    expect_stdout: \"PASS\"\n}\n\naccessor_boolean: {\n    input: {\n        var a = 1;\n        var b = {\n            get true() {\n                return a;\n            },\n            set false(c) {\n                a = c;\n            }\n        };\n        console.log(b.true, b.false = 2, b.true);\n    }\n    expect_exact: 'var a=1;var b={get true(){return a},set false(c){a=c}};console.log(b.true,b.false=2,b.true);'\n    expect_stdout: \"1 2 2\"\n}\n\naccessor_get_set: {\n    input: {\n        var a = 1;\n        var b = {\n            get set() {\n                return a;\n            },\n            set get(c) {\n                a = c;\n            }\n        };\n        console.log(b.set, b.get = 2, b.set);\n    }\n    expect_exact: 'var a=1;var b={get set(){return a},set get(c){a=c}};console.log(b.set,b.get=2,b.set);'\n    expect_stdout: \"1 2 2\"\n}\n\naccessor_null_undefined: {\n    input: {\n        var a = 1;\n        var b = {\n            get null() {\n                return a;\n            },\n            set undefined(c) {\n                a = c;\n            }\n        };\n        console.log(b.null, b.undefined = 2, b.null);\n    }\n    expect_exact: 'var a=1;var b={get null(){return a},set undefined(c){a=c}};console.log(b.null,b.undefined=2,b.null);'\n    expect_stdout: \"1 2 2\"\n}\n\naccessor_number: {\n    input: {\n        var a = 1;\n        var b = {\n            get 42() {\n                return a;\n            },\n            set 42(c) {\n                a = c;\n            }\n        };\n        console.log(b[42], b[42] = 2, b[42]);\n    }\n    expect_exact: 'var a=1;var b={get 42(){return a},set 42(c){a=c}};console.log(b[42],b[42]=2,b[42]);'\n    expect_stdout: \"1 2 2\"\n}\n\naccessor_string: {\n    input: {\n        var a = 1;\n        var b = {\n            get \"a-b\"() {\n                return a;\n            },\n            set \"a-b\"(c) {\n                a = c;\n            }\n        };\n        console.log(b[\"a-b\"], b[\"a-b\"] = 2, b[\"a-b\"]);\n    }\n    expect_exact: 'var a=1;var b={get\"a-b\"(){return a},set\"a-b\"(c){a=c}};console.log(b[\"a-b\"],b[\"a-b\"]=2,b[\"a-b\"]);'\n    expect_stdout: \"1 2 2\"\n}\n\naccessor_this: {\n    input: {\n        var a = 1;\n        var b = {\n            get this() {\n                return a;\n            },\n            set this(c) {\n                a = c;\n            }\n        };\n        console.log(b.this, b.this = 2, b.this);\n    }\n    expect_exact: 'var a=1;var b={get this(){return a},set this(c){a=c}};console.log(b.this,b.this=2,b.this);'\n    expect_stdout: \"1 2 2\"\n}\n\nignore_global_property: {\n    mangle = {\n        properties: {\n            globals: false,\n        }\n    }\n    input: {\n        foo = \"PASS\";\n        global.foo = \"FAIL\";\n        console.log(foo);\n    }\n    expect: {\n        foo = \"PASS\";\n        global.o = \"FAIL\";\n        console.log(foo);\n    }\n}\n\nmangle_global_property_read: {\n    mangle = {\n        properties: {\n            globals: true,\n        }\n    }\n    input: {\n        foo = \"PASS\";\n        console.log(global.foo);\n    }\n    expect: {\n        o = \"PASS\";\n        console.log(global.o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nmangle_global_property_write: {\n    mangle = {\n        properties: {\n            globals: true,\n        }\n    }\n    input: {\n        foo = \"FAIL\";\n        global.foo = \"PASS\";\n        console.log(foo);\n    }\n    expect: {\n        o = \"FAIL\";\n        global.o = \"PASS\";\n        console.log(o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nkeep_sandboxed_variable: {\n    mangle = {\n        properties: {\n            globals: true,\n        }\n    }\n    options = {\n        toplevel: true,\n    }\n    input: {\n        var foo = \"PASS\";\n        global.foo = \"FAIL\";\n        console.log(foo);\n    }\n    expect: {\n        var foo = \"PASS\";\n        global.o = \"FAIL\";\n        console.log(foo);\n    }\n    expect_stdout: \"PASS\"\n}\n\nmangle_global_property_collision_global: {\n    mangle = {\n        properties: {\n            globals: true,\n        }\n    }\n    input: {\n        o = \"foo\";\n        A = \"bar\";\n        global.A = \"baz\";\n        console.log(o, A);\n    }\n    expect: {\n        o = \"foo\";\n        l = \"bar\";\n        global.l = \"baz\";\n        console.log(o, l);\n    }\n    expect_stdout: \"foo baz\"\n}\n\nmangle_global_property_collision_local: {\n    mangle = {\n        properties: {\n            globals: true,\n        }\n    }\n    input: {\n        var o = \"foo\";\n        A = \"bar\";\n        global.A = \"baz\";\n        console.log(o, A);\n    }\n    expect: {\n        var o = \"foo\";\n        l = \"bar\";\n        global.l = \"baz\";\n        console.log(o, l);\n    }\n    expect_stdout: \"foo baz\"\n}\n\nmangle_global_property_collision_property: {\n    mangle = {\n        properties: {\n            globals: true,\n        }\n    }\n    input: {\n        var a = global;\n        a.p = \"foo\";\n        A = \"bar\";\n        global.A = \"baz\";\n        console.log(a.p, A);\n    }\n    expect: {\n        var a = global;\n        a.l = \"foo\";\n        o = \"bar\";\n        global.o = \"baz\";\n        console.log(a.l, o);\n    }\n    expect_stdout: \"foo baz\"\n}\n\nissue_2208_1: {\n    options = {\n        inline: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log({\n            p: function() {\n                return 42;\n            }\n        }.p());\n    }\n    expect: {\n        console.log(42);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_2: {\n    options = {\n        inline: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log({\n            a: 42,\n            p: function() {\n                return this.a;\n            }\n        }.p());\n    }\n    expect: {\n        console.log({\n            a: 42,\n            p: function() {\n                return this.a;\n            }\n        }.p());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_3: {\n    options = {\n        inline: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        a = 42;\n        console.log({\n            p: function() {\n                return function() {\n                    return this.a;\n                }();\n            }\n        }.p());\n    }\n    expect: {\n        a = 42;\n        console.log(function() {\n            return this.a;\n        }());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_4: {\n    options = {\n        inline: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        function foo() {}\n        console.log({\n            a: foo(),\n            p: function() {\n                return 42;\n            }\n        }.p());\n    }\n    expect: {\n        function foo() {}\n        console.log((foo(), function() {\n            return 42;\n        })());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_5: {\n    options = {\n        inline: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log({\n            p: \"FAIL\",\n            p: function() {\n                return 42;\n            }\n        }.p());\n    }\n    expect: {\n        console.log(42);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2208_6: {\n    options = {\n        inline: true,\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        a = 42;\n        console.log((\"FAIL\", {\n            p: function() {\n                return this.a;\n            }\n        }.p)());\n    }\n    expect: {\n        a = 42;\n        console.log(function() {\n            return this.a;\n        }());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_2256: {\n    options = {\n        side_effects: true,\n    }\n    mangle = {\n        properties: {\n            keep_quoted: true,\n        },\n    }\n    input: {\n        ({ \"keep\": 42 });\n        global.keep = global.change = \"PASS\";\n        console.log(keep);\n    }\n    expect: {\n        global.keep = global.l = \"PASS\";\n        console.log(keep);\n    }\n    expect_stdout: \"PASS\"\n}\n\nlhs_prop_1: {\n    options = {\n        evaluate: true,\n        properties: true,\n    }\n    input: {\n        console.log(++{\n            a: 1\n        }.a);\n    }\n    expect: {\n        console.log(++{\n            a: 1\n        }.a);\n    }\n    expect_stdout: \"2\"\n}\n\nlhs_prop_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        [1][0] = 42;\n        (function(a) {\n            a.b = \"g\";\n        })(\"abc\");\n        (function(a) {\n            a[2] = \"g\";\n        })(\"def\");\n        (function(a) {\n            a[\"\"] = \"g\";\n        })(\"ghi\");\n    }\n    expect: {\n        [1][0] = 42;\n        \"abc\".b = \"g\";\n        \"def\"[2] = \"g\";\n        \"ghi\"[\"\"] = \"g\";\n    }\n}\n\nliteral_duplicate_key_side_effects: {\n    options = {\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log({\n            a: \"FAIL\",\n            a: console.log ? \"PASS\" : \"FAIL\"\n        }.a);\n    }\n    expect: {\n        console.log(console.log ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nprop_side_effects_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var C = 1;\n        console.log(C);\n        var obj = {\n            bar: function() {\n                return C + C;\n            }\n        };\n        console.log(obj.bar());\n    }\n    expect: {\n        console.log(1);\n        var obj = {\n            bar: function() {\n                return 2;\n            }\n        };\n        console.log(obj.bar());\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\nprop_side_effects_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var C = 1;\n        console.log(C);\n        var obj = {\n            \"\": function() {\n                return C + C;\n            }\n        };\n        console.log(obj[\"\"]());\n    }\n    expect: {\n        console.log(1);\n        console.log(2);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\naccessor_1: {\n    options = {\n        properties: true,\n    }\n    input: {\n        console.log({\n            a: \"FAIL\",\n            get a() {\n                return \"PASS\";\n            }\n        }.a);\n    }\n    expect: {\n        console.log({\n            a: \"FAIL\",\n            get a() {\n                return \"PASS\";\n            }\n        }.a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\naccessor_2: {\n    options = {\n        properties: true,\n    }\n    input: {\n        console.log({\n            get a() {\n                return \"PASS\";\n            },\n            set a(v) {},\n            a: \"FAIL\"\n        }.a);\n    }\n    expect: {\n        console.log({\n            get a() {\n                return \"PASS\";\n            },\n            set a(v) {},\n            a: \"FAIL\"\n        }.a);\n    }\n    expect_stdout: true\n}\n\narray_hole: {\n    options = {\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        Array.prototype[2] = \"PASS\";\n        console.log([ 1, 2, , 3 ][1]);\n        console.log([ 1, 2, , 3 ][2]);\n        console.log([ 1, 2, , 3 ][3]);\n    }\n    expect: {\n        Array.prototype[2] = \"PASS\";\n        console.log(2);\n        console.log([ , , , ][2]);\n        console.log(3);\n    }\n    expect_stdout: [\n        \"2\",\n        \"PASS\",\n        \"3\",\n    ]\n}\n\nnew_this: {\n    options = {\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        new {\n            f: function(a) {\n                this.a = a;\n            }\n        }.f(42);\n    }\n    expect: {}\n}\n\nissue_2513: {\n    options = {\n        evaluate: true,\n        properties: true,\n    }\n    input: {\n        !function(Infinity, NaN, undefined) {\n            console.log(\"a\"[1/0], \"b\"[\"Infinity\"]);\n            console.log(\"c\"[0/0], \"d\"[\"NaN\"]);\n            console.log(\"e\"[void 0], \"f\"[\"undefined\"]);\n        }(0, 0, 0);\n    }\n    expect: {\n        !function(Infinity, NaN, undefined) {\n            console.log(\"a\"[1/0], \"b\"[1/0]);\n            console.log(\"c\".NaN, \"d\".NaN);\n            console.log(\"e\"[void 0], \"f\"[void 0]);\n        }(0, 0, 0);\n    }\n    expect_stdout: [\n        \"undefined undefined\",\n        \"undefined undefined\",\n        \"undefined undefined\",\n    ]\n}\n\nconst_prop_assign_strict: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        function Simulator() {\n            /abc/.index = 1;\n            this._aircraft = [];\n        }\n        (function() {}).prototype.destroy = x();\n    }\n    expect: {\n        function Simulator() {\n            this._aircraft = [];\n        }\n        x();\n    }\n}\n\nconst_prop_assign_pure: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        function Simulator() {\n            /abc/.index = 1;\n            this._aircraft = [];\n        }\n        (function() {}).prototype.destroy = x();\n    }\n    expect: {\n        function Simulator() {\n            this._aircraft = [];\n        }\n        x();\n    }\n}\n\nissue_869_1: {\n    mangle = {\n        properties: {\n            reserved: [ \"get\" ]\n        },\n    }\n    input: {\n        var o = { p: \"FAIL\" };\n        Object.defineProperty(o, \"p\", {\n            get: function() {\n                return \"PASS\";\n            }\n        });\n        console.log(o.p);\n    }\n    expect: {\n        var o = { o: \"FAIL\" };\n        Object.defineProperty(o, \"o\", {\n            get: function() {\n                return \"PASS\";\n            }\n        });\n        console.log(o.o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_869_2: {\n    mangle = {\n        properties: {\n            reserved: [ \"get\" ]\n        },\n    }\n    input: {\n        var o = { p: \"FAIL\" };\n        Object.defineProperties(o, {\n            p: {\n                get: function() {\n                    return \"PASS\";\n                }\n            }\n        });\n        console.log(o.p);\n    }\n    expect: {\n        var o = { o: \"FAIL\" };\n        Object.defineProperties(o, {\n            o: {\n                get: function() {\n                    return \"PASS\";\n                }\n            }\n        });\n        console.log(o.o);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3188_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        properties: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                console.log(this.p);\n            }\n            (function() {\n                var o = {\n                    p: \"PASS\",\n                    f: f\n                };\n                o.f();\n            })();\n        })();\n    }\n    expect: {\n        (function() {\n            function f() {\n                console.log(this.p);\n            }\n            ({\n                p: \"PASS\",\n                f: f\n            }).f();\n            var o;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3188_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        properties: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var f = function() {\n                console.log(this.p);\n            };\n            function g() {\n                var o = {\n                    p: \"PASS\",\n                    f: f\n                };\n                o.f();\n            }\n            g();\n        })();\n    }\n    expect: {\n        ({\n            p: \"PASS\",\n            f: function() {\n                console.log(this.p);\n            }\n        }).f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3188_3: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        properties: true,\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                console.log(this[0]);\n            }\n            (function() {\n                var o = [\"PASS\", f];\n                o[1]();\n            })();\n        })();\n    }\n    expect: {\n        (function() {\n            function f() {\n                console.log(this[0]);\n            }\n            [\"PASS\", f][1]();\n            var o;\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3389: {\n    options = {\n        evaluate: true,\n        properties: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        (function() {\n            var a = \"PASS\";\n            if (delete b)\n                b = a[null] = 42;\n            console.log(a);\n        })();\n    }\n    expect: {\n        (function() {\n            var a = \"PASS\";\n            if (delete b)\n                b = a.null = 42;\n            console.log(a);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nobject_super: {\n    options = {\n        properties: true,\n    }\n    input: {\n        ({\n            f(a) {\n                return a ? console.log(\"PASS\") : super.log(\"PASS\");\n            },\n        }).f(console);\n    }\n    expect: {\n        ({\n            f(a) {\n                return a ? console.log(\"PASS\") : super.log(\"PASS\");\n            },\n        }).f(console);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4831_1: {\n    options = {\n        properties: true,\n    }\n    input: {\n        console.log({\n            f() {\n                return arguments;\n            },\n        }.f(\"PASS\")[0]);\n    }\n    expect: {\n        console.log([\n            function() {\n                return arguments;\n            },\n        ][0](\"PASS\")[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4831_2: {\n    options = {\n        properties: true,\n    }\n    input: {\n        var f = {\n            f() {\n                return arguments;\n            },\n        }.f;\n        console.log(f(\"PASS\")[0]);\n    }\n    expect: {\n        var f = {\n            f() {\n                return arguments;\n            },\n        }.f;\n        console.log(f(\"PASS\")[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4888: {\n    options = {\n        properties: true,\n    }\n    input: {\n        console.log(typeof {\n            __proto__: 42,\n        }.__proto__);\n    }\n    expect: {\n        console.log(typeof {\n            __proto__: 42,\n        }.__proto__);\n    }\n    expect_stdout: \"object\"\n}\n\nissue_5093: {\n    beautify = {\n        keep_quoted_props: true,\n    }\n    input: {\n        console.log({\n            a: true,\n            '42': \"PASS\",\n            \"null\": [],\n        }[6 * 7]);\n    }\n    expect_exact: 'console.log({a:true,\"42\":\"PASS\",\"null\":[]}[6*7]);'\n    expect_stdout: \"PASS\"\n}\n\nissue_5093_quote_keys: {\n    beautify = {\n        keep_quoted_props: true,\n        quote_keys: true,\n    }\n    input: {\n        console.log({\n            a: true,\n            '42': \"PASS\",\n            \"null\": [],\n        }[6 * 7]);\n    }\n    expect_exact: 'console.log({\"a\":true,\"42\":\"PASS\",\"null\":[]}[6*7]);'\n    expect_stdout: \"PASS\"\n}\n\nissue_5093_quote_style: {\n    beautify = {\n        keep_quoted_props: true,\n        quote_style: 3,\n    }\n    input: {\n        console.log({\n            a: true,\n            '42': \"PASS\",\n            \"null\": [],\n        }[6 * 7]);\n    }\n    expect_exact: 'console.log({a:true,\\'42\\':\"PASS\",\"null\":[]}[6*7]);'\n    expect_stdout: \"PASS\"\n}\n\nobject_methods: {\n    options = {\n        properties: true,\n    }\n    input: {\n        ({\n            p() {\n                console.log(\"FAIL 1\");\n            },\n            *q() {\n                console.log(\"FAIL 2\");\n            },\n            async r() {\n                console.log(\"FAIL 3\");\n            },\n            async *s() {\n                console.log(\"PASS\");\n            },\n        }).s().next();\n    }\n    expect: {\n        [\n            () => {\n                console.log(\"FAIL 1\");\n            },\n            function*() {\n                console.log(\"FAIL 2\");\n            },\n            async () => {\n                console.log(\"FAIL 3\");\n            },\n            async function*() {\n                console.log(\"PASS\");\n            },\n        ][3]().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5177: {\n    options = {\n        properties: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var o = { a: \"PASS\" };\n        o.p = {\n            q() {\n                return this.a;\n            },\n        }.q;\n        console.log(o.p());\n    }\n    expect: {\n        var a = \"FAIL\";\n        var o = { a: \"PASS\" };\n        o.p = {\n            q() {\n                return this.a;\n            },\n        }.q;\n        console.log(o.p());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5682_in_1: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return \"foo\" in a;\n        }\n        var o = {};\n        var p = \"foo\";\n        o[p] = 42;\n        console.log(f(o) ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        function f(o) {\n            return \"foo\" in o;\n        }\n        var o = {};\n        var p = \"foo\";\n        o[p] = 42;\n        console.log(f(o) ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5682_in_2: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return \"foo\" in a;\n        }\n        var o = { foo: 42 };\n        console.log(f(o) ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        function f(o) {\n            return \"o\" in o;\n        }\n        var o = { o: 42 };\n        console.log(f(o) ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5682_dot_1: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return a.foo;\n        }\n        var o = {};\n        var p = \"foo\";\n        o[p] = \"PASS\";\n        console.log(f(o));\n    }\n    expect: {\n        function f(o) {\n            return o.foo;\n        }\n        var o = {};\n        var p = \"foo\";\n        o[p] = \"PASS\";\n        console.log(f(o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5682_dot_2: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return a.foo;\n        }\n        var o = { foo: \"PASS\" };\n        console.log(f(o));\n    }\n    expect: {\n        function f(o) {\n            return o.o;\n        }\n        var o = { o: \"PASS\" };\n        console.log(f(o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5682_dot_2_computed: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return a.foo;\n        }\n        var o = { [\"foo\"]: \"PASS\" };\n        console.log(f(o));\n    }\n    expect: {\n        function f(o) {\n            return o.o;\n        }\n        var o = { [\"o\"]: \"PASS\" };\n        console.log(f(o));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5682_sub_1: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return a[\"foo\"];\n        }\n        var o = {};\n        var p = \"foo\";\n        o[p] = \"PASS\";\n        console.log(f(o));\n    }\n    expect: {\n        function f(o) {\n            return o[\"foo\"];\n        }\n        var o = {};\n        var p = \"foo\";\n        o[p] = \"PASS\";\n        console.log(f(o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5682_sub_2: {\n    mangle = {\n        properties: true,\n    }\n    input: {\n        function f(a) {\n            return a[\"foo\"];\n        }\n        var o = { foo: \"PASS\" };\n        console.log(f(o));\n    }\n    expect: {\n        function f(o) {\n            return o[\"o\"];\n        }\n        var o = { o: \"PASS\" };\n        console.log(f(o));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5927: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        A = {};\n        while (console.log(\"PASS\"));\n        A.p;\n        A.q = 42;\n        A.q.r = 42;\n    }\n    expect: {\n        A = {};\n        while (console.log(\"PASS\"));\n        A.p;\n        A.q = 42;\n        A.q.r = 42;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5949_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 42;\n        a[a = null];\n        try {\n            a.p;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = 42;\n        a[a = null];\n        try {\n            a.p;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5949_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        try {\n            a[42];\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            a[42];\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5963_dot: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        try {\n            b.p = (b.q = null, a = \"FAIL 1\", !0);\n            console.log(\"FAIL 2\")\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"PASS\", b;\n        try {\n            b.p = (b.q = null, a = \"FAIL 1\", !0);\n            console.log(\"FAIL 2\")\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5963_sub: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        try {\n            b[42] = (b.q = null, a = \"FAIL 1\", !0);\n            console.log(\"FAIL 2\")\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"PASS\", b;\n        try {\n            b[42] = (b.q = null, a = \"FAIL 1\", !0);\n            console.log(\"FAIL 2\")\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5963_assign: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = Object.create(null);\n        a.PASS = 42;\n        a.FAIL;\n        for (var p in a)\n            console.log(p);\n    }\n    expect: {\n        var a = Object.create(null);\n        a.PASS = 42;\n        for (var p in a)\n            console.log(p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5963_compound_assign: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = Object.create(null);\n        a.PASS ^= 42;\n        a.FAIL;\n        for (var p in a)\n            console.log(p);\n    }\n    expect: {\n        var a = Object.create(null);\n        a.PASS ^= 42;\n        for (var p in a)\n            console.log(p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5963_unary: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = Object.create(null);\n        a.PASS++;\n        a.FAIL;\n        for (var p in a)\n            console.log(p);\n    }\n    expect: {\n        var a = Object.create(null);\n        a.PASS++;\n        for (var p in a)\n            console.log(p);\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/pure_funcs.js",
    "content": "array: {\n    options = {\n        pure_funcs: [ \"Math.floor\" ],\n        side_effects: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            Math.floor(a / b);\n            Math.floor(c / b);\n        }\n    }\n    expect: {\n        var a;\n        function f(b) {\n            c;\n        }\n    }\n}\n\nfunc: {\n    options = {\n        pure_funcs: function(node) {\n            return !~node.args[0].print_to_string().indexOf(\"a\");\n        },\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            Math.floor(a / b);\n            Math.floor(c / b);\n        }\n    }\n    expect: {\n        function f(a, b) {\n            Math.floor(c / b);\n        }\n    }\n}\n\nside_effects: {\n    options = {\n        pure_funcs: [ \"console.log\" ],\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            console.log(a());\n            console.log(b);\n        }\n    }\n    expect: {\n        function f(a, b) {\n            a();\n        }\n    }\n}\n\nunused: {\n    options = {\n        pure_funcs: [ \"pure\" ],\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            var u = pure(1);\n            var x = pure(2);\n            var y = pure(x);\n            var z = pure(pure(side_effects()));\n            return pure(3);\n        }\n    }\n    expect: {\n        function foo() {\n            side_effects();\n            return pure(3);\n        }\n    }\n}\n\nbabel: {\n    options = {\n        pure_funcs: [ \"_classCallCheck\" ],\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function _classCallCheck(instance, Constructor) {\n            if (!(instance instanceof Constructor))\n                throw new TypeError(\"Cannot call a class as a function\");\n        }\n        var Foo = function Foo() {\n            _classCallCheck(this, Foo);\n        };\n    }\n    expect: {\n        function _classCallCheck(instance, Constructor) {\n            if (!(instance instanceof Constructor))\n                throw new TypeError(\"Cannot call a class as a function\");\n        }\n        var Foo = function() {\n        };\n    }\n}\n\nconditional: {\n    options = {\n        pure_funcs: [ \"pure\" ],\n        side_effects: true,\n    }\n    input: {\n        pure(1 | a() ? 2 & b() : 7 ^ c());\n        pure(1 | a() ? 2 & b() : 5);\n        pure(1 | a() ? 4 : 7 ^ c());\n        pure(1 | a() ? 4 : 5);\n        pure(3 ? 2 & b() : 7 ^ c());\n        pure(3 ? 2 & b() : 5);\n        pure(3 ? 4 : 7 ^ c());\n        pure(3 ? 4 : 5);\n    }\n    expect: {\n        1 | a() ? b() : c();\n        1 | a() && b();\n        1 | a() || c();\n        a();\n        3 ? b() : c();\n        3 && b();\n        3 || c();\n    }\n}\n\nrelational: {\n    options = {\n        pure_funcs: [ \"foo\" ],\n        side_effects: true,\n    }\n    input: {\n        foo() in new foo();\n        foo() instanceof bar();\n        foo() < \"bar\";\n        bar() > foo();\n        bar() != bar();\n        bar() !== \"bar\";\n        \"bar\" == foo();\n        \"bar\" === bar();\n        \"bar\" >= \"bar\";\n    }\n    expect: {\n        [] instanceof bar();\n        bar();\n        bar(), bar();\n        bar();\n        bar();\n    }\n}\n\narithmetic: {\n    options = {\n        pure_funcs: [ \"foo\" ],\n        side_effects: true,\n    }\n    input: {\n        foo() + foo();\n        foo() - bar();\n        foo() * \"bar\";\n        bar() / foo();\n        bar() & bar();\n        bar() | \"bar\";\n        \"bar\" >> foo();\n        \"bar\" << bar();\n        \"bar\" >>> \"bar\";\n    }\n    expect: {\n        bar();\n        bar();\n        bar(), bar();\n        bar();\n        bar();\n    }\n}\n\nboolean_and: {\n    options = {\n        pure_funcs: [ \"foo\" ],\n        side_effects: true,\n    }\n    input: {\n        foo() && foo();\n        foo() && bar();\n        foo() && \"bar\";\n        bar() && foo();\n        bar() && bar();\n        bar() && \"bar\";\n        \"bar\" && foo();\n        \"bar\" && bar();\n        \"bar\" && \"bar\";\n    }\n    expect: {\n        foo() && bar();\n        bar();\n        bar() && bar();\n        bar();\n        \"bar\" && bar();\n    }\n}\n\nboolean_or: {\n    options = {\n        pure_funcs: [ \"foo\" ],\n        side_effects: true,\n    }\n    input: {\n        foo() || foo();\n        foo() || bar();\n        foo() || \"bar\";\n        bar() || foo();\n        bar() || bar();\n        bar() || \"bar\";\n        \"bar\" || foo();\n        \"bar\" || bar();\n        \"bar\" || \"bar\";\n    }\n    expect: {\n        foo() || bar();\n        bar();\n        bar() || bar();\n        bar();\n        \"bar\" || bar();\n    }\n}\n\nassign: {\n    options = {\n        pure_funcs: [ \"foo\" ],\n        side_effects: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            a = foo();\n            b *= 4 + foo();\n            c >>= 0 | foo();\n        }\n    }\n    expect: {\n        var a;\n        function f(b) {\n            a = foo();\n            b *= 4 + foo();\n            c >>= 0 | foo();\n        }\n    }\n}\n\nunary: {\n    options = {\n        pure_funcs: [ \"foo\" ],\n        side_effects: true,\n    }\n    input: {\n        typeof foo();\n        typeof bar();\n        typeof \"bar\";\n        void foo();\n        void bar();\n        void \"bar\";\n        delete a[foo()];\n        delete a[bar()];\n        delete a[\"bar\"];\n        a[foo()]++;\n        a[bar()]++;\n        a[\"bar\"]++;\n        --a[foo()];\n        --a[bar()];\n        --a[\"bar\"];\n        ~foo();\n        ~bar();\n        ~\"bar\";\n    }\n    expect: {\n        bar();\n        bar();\n        delete a[foo()];\n        delete a[bar()];\n        delete a[\"bar\"];\n        a[foo()]++;\n        a[bar()]++;\n        a[\"bar\"]++;\n        --a[foo()];\n        --a[bar()];\n        --a[\"bar\"];\n        bar();\n    }\n}\n\nissue_3065_1: {\n    options = {\n        inline: true,\n        pure_funcs: [ \"pureFunc\" ],\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function modifyWrapper(a, f, wrapper) {\n            wrapper.a = a;\n            wrapper.f = f;\n            return wrapper;\n        }\n        function pureFunc(fun) {\n            return modifyWrapper(1, fun, function(a) {\n                return fun(a);\n            });\n        }\n        var unused = pureFunc(function(x) {\n            return x;\n        });\n    }\n    expect: {}\n}\n\nissue_3065_2: {\n    rename = true\n    options = {\n        inline: true,\n        pure_funcs: [ \"pureFunc\" ],\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        reserved: [ \"pureFunc\" ],\n        toplevel: true,\n    }\n    input: {\n        function modifyWrapper(a, f, wrapper) {\n            wrapper.a = a;\n            wrapper.f = f;\n            return wrapper;\n        }\n        function pureFunc(fun) {\n            return modifyWrapper(1, fun, function(a) {\n                return fun(a);\n            });\n        }\n        var unused = pureFunc(function(x) {\n            return x;\n        });\n    }\n    expect: {}\n}\n\nissue_3065_3: {\n    options = {\n        pure_funcs: [ \"debug\" ],\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function debug(msg) {\n            console.log(msg);\n        }\n        debug(function() {\n            console.log(\"PASS\");\n            return \"FAIL\";\n        }());\n    }\n    expect: {\n        (function() {\n            console.log(\"PASS\");\n        })();\n    }\n}\n\nissue_3065_4: {\n    options = {\n        pure_funcs: [ \"debug\" ],\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var debug = function(msg) {\n            console.log(msg);\n        };\n        debug(function() {\n            console.log(\"PASS\");\n            return \"FAIL\";\n        }());\n    }\n    expect: {\n        (function() {\n            console.log(\"PASS\");\n        })();\n    }\n}\n\nissue_3325_1: {\n    options = {\n        pure_funcs: \"cb\",\n        side_effects: true,\n    }\n    input: {\n        function cb() {\n            console.log(\"PASS\");\n        }\n        cb();\n    }\n    expect: {\n        function cb() {\n            console.log(\"PASS\");\n        }\n    }\n}\n\nissue_3325_2: {\n    options = {\n        pure_funcs: \"xxxcbxxx\",\n        side_effects: true,\n    }\n    input: {\n        function cb() {\n            console.log(\"PASS\");\n        }\n        cb();\n    }\n    expect: {\n        function cb() {\n            console.log(\"PASS\");\n        }\n        cb();\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/pure_getters.js",
    "content": "strict: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_funcs: false,\n        reduce_vars: false,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = null, c = {};\n        a.prop;\n        b.prop;\n        c.prop;\n        d.prop;\n        null.prop;\n        (void 0).prop;\n        undefined.prop;\n    }\n    expect: {\n        var a, b = null, c = {};\n        a.prop;\n        b.prop;\n        c.prop;\n        d.prop;\n        null.prop;\n        (void 0).prop;\n        (void 0).prop;\n    }\n}\n\nstrict_reduce_vars: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = null, c = {};\n        a.prop;\n        b.prop;\n        c.prop;\n        d.prop;\n        null.prop;\n        (void 0).prop;\n        undefined.prop;\n    }\n    expect: {\n        var a, b = null, c = {};\n        a.prop;\n        b.prop;\n        d.prop;\n        null.prop;\n        (void 0).prop;\n        (void 0).prop;\n    }\n}\n\nunsafe: {\n    options = {\n        pure_getters: true,\n        reduce_funcs: false,\n        reduce_vars: false,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = null, c = {};\n        a.prop;\n        b.prop;\n        c.prop;\n        d.prop;\n        null.prop;\n        (void 0).prop;\n        undefined.prop;\n    }\n    expect: {\n        var a, b = null, c = {};\n        d;\n        null.prop;\n        (void 0).prop;\n        (void 0).prop;\n    }\n}\n\nunsafe_reduce_vars: {\n    options = {\n        pure_getters: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = null, c = {};\n        a.prop;\n        b.prop;\n        c.prop;\n        d.prop;\n        null.prop;\n        (void 0).prop;\n        undefined.prop;\n    }\n    expect: {\n        var a, b = null, c = {};\n        d;\n        null.prop;\n        (void 0).prop;\n        (void 0).prop;\n    }\n}\n\nchained: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        a.b.c;\n    }\n    expect: {\n        a.b.c;\n    }\n}\n\nimpure_getter_1: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        ({\n            get a() {\n                console.log(1);\n            },\n            b: 1\n        }).a;\n        ({\n            get a() {\n                console.log(1);\n            },\n            b: 1\n        }).b;\n    }\n    expect: {\n        ({\n            get a() {\n                console.log(1);\n            },\n            b: 1\n        }).a;\n        ({\n            get a() {\n                console.log(1);\n            },\n            b: 1\n        }).b;\n    }\n    expect_stdout: \"1\"\n}\n\nimpure_getter_2: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        // will produce incorrect output because getter is not pure\n        ({\n            get a() {\n                console.log(1);\n            },\n            b: 1\n        }).a;\n        ({\n            get a() {\n                console.log(1);\n            },\n            b: 1\n        }).b;\n    }\n    expect: {}\n}\n\nissue_2110_1: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function f() {}\n            function g() {\n                return this;\n            }\n            f.g = g;\n            return f.g();\n        }\n        console.log(typeof f());\n    }\n    expect: {\n        function f() {\n            function f() {}\n            return f.g = function() {\n                return this;\n            }, f.g();\n        }\n        console.log(typeof f());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2110_2: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function f() {}\n            function g() {\n                return this;\n            }\n            f.g = g;\n            return f.g();\n        }\n        console.log(typeof f());\n    }\n    expect: {\n        function f() {\n            function f() {}\n            f.g = function() {\n                return this;\n            };\n            return f.g();\n        }\n        console.log(typeof f());\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2110_3: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        function g() {\n            return this;\n        }\n        console.log(typeof function() {\n            function f() {}\n            f.g = g;\n            return f.g();\n        }());\n    }\n    expect: {\n        function g() {\n            return this;\n        }\n        console.log(typeof function() {\n            function f() {}\n            f.g = g;\n            return f.g();\n        }());\n    }\n    expect_stdout: \"function\"\n}\n\nset_immutable_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        a.foo += \"\";\n        if (a.foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect: {\n        1..foo += \"\";\n        if (1..foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nset_immutable_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        a.foo += \"\";\n        if (a.foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect: {\n        var a = 1;\n        a.foo += \"\", a.foo ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nset_immutable_3: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 1;\n        a.foo += \"\";\n        if (a.foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        1..foo += \"\";\n        if (1..foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect_stdout: true\n}\n\nset_immutable_4: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 1;\n        a.foo += \"\";\n        if (a.foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        var a = 1;\n        a.foo += \"\", a.foo ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: true\n}\n\nset_immutable_5: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var a = 1;\n        a.foo += \"\";\n        if (a.foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        1..foo += \"\";\n        1..foo ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: true\n}\n\nset_immutable_6: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 1;\n        a.foo += \"\";\n        if (a.foo) console.log(\"FAIL\");\n        else console.log(\"PASS\");\n    }\n    expect: {\n        1..foo ? console.log(\"FAIL\") : console.log(\"PASS\");\n    }\n    expect_stdout: true\n}\n\nset_mutable_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function a() {\n            a.foo += \"\";\n            if (a.foo) console.log(\"PASS\");\n            else console.log(\"FAIL\");\n        }();\n    }\n    expect: {\n        !function a() {\n            if (a.foo += \"\") console.log(\"PASS\");\n            else console.log(\"FAIL\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nset_mutable_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        !function a() {\n            a.foo += \"\";\n            if (a.foo) console.log(\"PASS\");\n            else console.log(\"FAIL\");\n        }();\n    }\n    expect: {\n        !function a() {\n            (a.foo += \"\") ? console.log(\"PASS\") : console.log(\"FAIL\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2313_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function x() {\n            console.log(1);\n            return {\n                y: function() {\n                    console.log(2);\n                    return {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++;\n        if (x().y().z) {\n            console.log(3);\n        }\n    }\n    expect: {\n        function x() {\n            return console.log(1), {\n                y: function() {\n                    return console.log(2), {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++,\n        x().y().z && console.log(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_2313_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function x() {\n            console.log(1);\n            return {\n                y: function() {\n                    console.log(2);\n                    return {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++;\n        if (x().y().z) {\n            console.log(3);\n        }\n    }\n    expect: {\n        function x() {\n            return console.log(1), {\n                y: function() {\n                    return console.log(2), {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++,\n        x().y().z && console.log(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_2313_3: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        function x() {\n            console.log(1);\n            return {\n                y: function() {\n                    console.log(2);\n                    return {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++;\n        if (x().y().z) {\n            console.log(3);\n        }\n    }\n    expect: {\n        function x() {\n            console.log(1);\n            return {\n                y: function() {\n                    console.log(2);\n                    return {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++;\n        x().y().z && console.log(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_2313_4: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: true,\n    }\n    input: {\n        function x() {\n            console.log(1);\n            return {\n                y: function() {\n                    console.log(2);\n                    return {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++;\n        if (x().y().z) {\n            console.log(3);\n        }\n    }\n    expect: {\n        function x() {\n            console.log(1);\n            return {\n                y: function() {\n                    console.log(2);\n                    return {\n                        z: 0\n                    };\n                }\n            };\n        }\n        x().y().z++;\n        x().y().z && console.log(3);\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_2313_5: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        x().y++;\n        x().y;\n    }\n    expect: {\n        x().y++;\n        x().y;\n    }\n}\n\nissue_2313_6: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        x().y++;\n        x().y;\n    }\n    expect: {\n        x().y++;\n        x();\n    }\n}\n\nissue_2678: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var a = 1, c = \"FAIL\";\n        (function f() {\n            (a-- && f()).p;\n            return {\n                get p() {\n                    c = \"PASS\";\n                }\n            };\n        })();\n        console.log(c);\n    }\n    expect: {\n        var a = 1, c = \"FAIL\";\n        (function f() {\n            (a-- && f()).p;\n            return {\n                get p() {\n                    c = \"PASS\";\n                }\n            };\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2838: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            (a || b).c = \"PASS\";\n            (function() {\n                return f(a, b);\n            }).prototype.foo = \"bar\";\n        }\n        var o = {};\n        f(null, o);\n        console.log(o.c);\n    }\n    expect: {\n        function f(a, b) {\n            (a || b).c = \"PASS\";\n        }\n        var o = {};\n        f(null, o);\n        console.log(o.c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2938_1: {\n    options = {\n        pure_getters: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            a.b = \"PASS\";\n        }\n        var o = {};\n        f(o);\n        console.log(o.b);\n    }\n    expect: {\n        function f(a) {\n            a.b = \"PASS\";\n        }\n        var o = {};\n        f(o);\n        console.log(o.b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2938_2: {\n    options = {\n        pure_getters: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var Parser = function Parser() {};\n        var p = Parser.prototype;\n        p.initialContext = function initialContext() {\n            console.log(\"PASS\");\n        };\n        p.braceIsBlock = function() {};\n        (new Parser).initialContext();\n    }\n    expect: {\n        var Parser = function() {};\n        var p = Parser.prototype;\n        p.initialContext = function() {\n            console.log(\"PASS\");\n        };\n        p.braceIsBlock = function() {};\n        (new Parser).initialContext();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2938_3: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var unused = a.a;\n            a.b = \"PASS\";\n            a.c;\n        }\n        var o = {};\n        o.d;\n        f(o);\n        console.log(o.b);\n    }\n    expect: {\n        function f(a) {\n            a.b = \"PASS\";\n        }\n        var o = {};\n        f(o);\n        console.log(o.b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2938_4: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var Parser = function Parser() {};\n        var p = Parser.prototype;\n        var unused = p.x;\n        p.initialContext = function initialContext() {\n            p.y;\n            console.log(\"PASS\");\n        };\n        p.braceIsBlock = function() {};\n        (new Parser).initialContext();\n    }\n    expect: {\n        var Parser = function() {};\n        var p = Parser.prototype;\n        p.initialContext = function() {\n            console.log(\"PASS\");\n        };\n        p.braceIsBlock = function() {};\n        (new Parser).initialContext();\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_vars_1_true: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            for (;;) {\n                var c = a.g();\n                var d = b.p;\n                if (c || d) break;\n            }\n        }\n    }\n    expect: {\n        function f(a, b) {\n            for (;;)\n                if (a.g() || b.p) break;\n        }\n    }\n}\n\ncollapse_vars_1_false: {\n    options = {\n        collapse_vars: true,\n        pure_getters: false,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            for (;;) {\n                var c = a.g();\n                var d = b.p;\n                if (c || d) break;\n            }\n        }\n    }\n    expect: {\n        function f(a, b) {\n            for (;;) {\n                var c = a.g();\n                var d = b.p;\n                if (c || d) break;\n            }\n        }\n    }\n}\n\ncollapse_vars_1_strict: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            for (;;) {\n                var c = a.g();\n                var d = b.p;\n                if (c || d) break;\n            }\n        }\n    }\n    expect: {\n        function f(a, b) {\n            for (;;) {\n                var c = a.g();\n                var d = b.p;\n                if (c || d) break;\n            }\n        }\n    }\n}\n\ncollapse_vars_2_true: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            function g() {}\n            g.a = function() {};\n            g.b = g.a;\n            return g;\n        }\n    }\n    expect: {\n        function f() {\n            function g() {}\n            g.b = g.a = function() {};\n            return g;\n        }\n    }\n}\n\ncollapse_vars_2_false: {\n    options = {\n        collapse_vars: true,\n        pure_getters: false,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            function g() {}\n            g.a = function() {};\n            g.b = g.a;\n            return g;\n        }\n    }\n    expect: {\n        function f() {\n            function g() {}\n            g.a = function() {};\n            g.b = g.a;\n            return g;\n        }\n    }\n}\n\ncollapse_vars_2_strict: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            function g() {}\n            g.a = function() {};\n            g.b = g.a;\n            return g;\n        }\n    }\n    expect: {\n        function f() {\n            function g() {}\n            g.b = g.a = function() {};\n            return g;\n        }\n    }\n}\n\ncollapse_rhs_true: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: true,\n    }\n    input: {\n        console.log((42..length = \"PASS\", \"PASS\"));\n        console.log((\"foo\".length = \"PASS\", \"PASS\"));\n        console.log((false.length = \"PASS\", \"PASS\"));\n        console.log((function() {}.length = \"PASS\", \"PASS\"));\n        console.log(({\n            get length() {\n                return \"FAIL\";\n            }\n        }.length = \"PASS\", \"PASS\"));\n    }\n    expect: {\n        console.log(42..length = \"PASS\");\n        console.log(\"foo\".length = \"PASS\");\n        console.log(false.length = \"PASS\");\n        console.log(function() {}.length = \"PASS\");\n        console.log({\n            get length() {\n                return \"FAIL\";\n            }\n        }.length = \"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\ncollapse_rhs_false: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: false,\n    }\n    input: {\n        console.log((42..length = \"PASS\", \"PASS\"));\n        console.log((\"foo\".length = \"PASS\", \"PASS\"));\n        console.log((false.length = \"PASS\", \"PASS\"));\n        console.log((function() {}.length = \"PASS\", \"PASS\"));\n        console.log(({\n            get length() {\n                return \"FAIL\";\n            }\n        }.length = \"PASS\", \"PASS\"));\n    }\n    expect: {\n        console.log(42..length = \"PASS\");\n        console.log(\"foo\".length = \"PASS\");\n        console.log(false.length = \"PASS\");\n        console.log(function() {}.length = \"PASS\");\n        console.log({\n            get length() {\n                return \"FAIL\";\n            }\n        }.length = \"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\ncollapse_rhs_strict: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        console.log((42..length = \"PASS\", \"PASS\"));\n        console.log((\"foo\".length = \"PASS\", \"PASS\"));\n        console.log((false.length = \"PASS\", \"PASS\"));\n        console.log((function() {}.length = \"PASS\", \"PASS\"));\n        console.log(({\n            get length() {\n                return \"FAIL\";\n            }\n        }.length = \"PASS\", \"PASS\"));\n    }\n    expect: {\n        console.log(42..length = \"PASS\");\n        console.log(\"foo\".length = \"PASS\");\n        console.log(false.length = \"PASS\");\n        console.log(function() {}.length = \"PASS\");\n        console.log({\n            get length() {\n                return \"FAIL\";\n            }\n        }.length = \"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\ncollapse_rhs_setter: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        try {\n            console.log(({\n                set length(v) {\n                    throw \"PASS\";\n                }\n            }.length = \"FAIL\", \"FAIL\"));\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        try {\n            console.log({\n                set length(v) {\n                    throw \"PASS\";\n                }\n            }.length = \"FAIL\");\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_rhs_call: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {};\n        function f() {\n            console.log(\"PASS\");\n        }\n        o.f = f;\n        f();\n    }\n    expect: {\n        ({}.f = function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\ncollapse_rhs_lhs: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n    }\n    input: {\n        function f(a, b) {\n            a.b = b, b += 2;\n            console.log(a.b, b);\n        }\n        f({}, 1);\n    }\n    expect: {\n        function f(a, b) {\n            a.b = b, b += 2;\n            console.log(a.b, b);\n        }\n        f({}, 1);\n    }\n    expect_stdout: \"1 3\"\n}\n\ndrop_arguments: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            arguments.slice = function() {\n                console.log(\"PASS\");\n            };\n            arguments[42];\n            arguments.length;\n            arguments.slice();\n        })();\n    }\n    expect: {\n        (function() {\n            arguments.slice = function() {\n                console.log(\"PASS\");\n            };\n            arguments.slice();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nlvalues_def: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        var a = b++, b = +function() {}();\n        a && a[a++];\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 1;\n        a = b++, b = +void 0;\n        a && a++;\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\nside_effects_assign: {\n    options = {\n        evaluate: true,\n        pure_getters: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = typeof void (a && a.in == 1, 0);\n        console.log(a);\n    }\n    expect: {\n        var a = \"undefined\";\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_2062: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        conditionals: true,\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 1;\n        if ([ a || a++ + a--, a++ + a--, a && a.var ]);\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        a || (a++, a--), a++, a--;\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2878: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var c = 0;\n        (function(a, b) {\n            function f2() {\n                if (a) c++;\n            }\n            b = f2();\n            a = 1;\n            b && b.b;\n            f2();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(a, b) {\n            function f2() {\n                if (a) c++;\n            }\n            b = f2(),\n            a = 1,\n            f2();\n        })(),\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3427: {\n    options = {\n        assignments: true,\n        evaluate: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b) {\n            b.p = 42;\n        })(a || (a = {}));\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nissue_3490_1: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        inline: true,\n        pure_getters: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 42, c = \"FAIL\";\n        if ({\n            3: function() {\n                var a;\n                return (a && a.p) < this;\n            }(),\n        }) c = \"PASS\";\n        if (b) while (\"\" == typeof d);\n        console.log(c, b);\n    }\n    expect: {\n        var b = 42, c = \"FAIL\";\n        var a;\n        if (c = \"PASS\", b) while (\"\" == typeof d);\n        console.log(c, b);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nissue_4135: {\n    options = {\n        evaluate: true,\n        inline: true,\n        merge_vars: true,\n        pure_getters: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        --b;\n        a++;\n        if (!a)\n            var c = function() {\n                var d = 0;\n                function f() {\n                    d && d.p;\n                }\n                f();\n                this;\n            }(a++);\n        console.log(a, b, c);\n    }\n    expect: {\n        var a = 0;\n        0;\n        a++;\n        if (!a)\n            var c = void a++;\n        console.log(a, -1, c);\n    }\n    expect_stdout: \"1 -1 undefined\"\n}\n\nissue_4440: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        try {\n            (function() {\n                arguments = null;\n                console.log(arguments.p = \"FAIL\");\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function() {\n                arguments = null;\n                console.log(arguments.p = \"FAIL\");\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4730_1: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        console.log(\"PASS\") + (a && a[a.p]);\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4730_2: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        !console.log(\"PASS\") || a && a[a.p];\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4751: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            },\n        };\n        o && o.p;\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            },\n        };\n    }\n}\n\nsuper_toString: {\n    options = {\n        pure_getters: true,\n        unsafe: true,\n    }\n    input: {\n        console.log({\n            f() {\n                return super.toString();\n            },\n        }.f());\n    }\n    expect: {\n        console.log({\n            f() {\n                return super.toString();\n            },\n        }.f());\n    }\n    expect_stdout: \"[object Object]\"\n    node_version: \">=4\"\n}\n\nthis_toString: {\n    options = {\n        pure_getters: true,\n        unsafe: true,\n    }\n    input: {\n        console.log({\n            f() {\n                return this.toString();\n            },\n        }.f());\n    }\n    expect: {\n        console.log({\n            f() {\n                return \"\" + this;\n            },\n        }.f());\n    }\n    expect_stdout: \"[object Object]\"\n    node_version: \">=4\"\n}\n\nissue_4803: {\n    options = {\n        hoist_vars: true,\n        join_vars: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            get f() {\n                console.log(\"PASS\");\n            },\n        } || 42;\n        for (var k in o)\n            o[k];\n    }\n    expect: {\n        var k, o = {\n            get f() {\n                console.log(\"PASS\");\n            },\n        } || 42;\n        for (k in o)\n            o[k];\n    }\n    expect_stdout: \"PASS\"\n}\n\nnested_property_assignments_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f;\n        ((f = function() {\n            console.log(\"FAIL\");\n        }).p = f).q = console.log(\"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nnested_property_assignments_2: {\n    options = {\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var o = {};\n        (function() {\n            var a;\n            (o.p = a = {}).q = \"PASS\";\n        })();\n        console.log(o.p.q);\n    }\n    expect: {\n        var o = {};\n        (function() {\n            (o.p = {}).q = \"PASS\";\n        })();\n        console.log(o.p.q);\n    }\n    expect_stdout: \"PASS\"\n}\n\nnested_property_assignments_3: {\n    options = {\n        collapse_vars: true,\n        pure_getters: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var o = { p: {} };\n        (function(a) {\n            console && a;\n            if (console) {\n                a = a.p;\n                a.q = a;\n            }\n        })(o);\n        console.log(o.p.q === o.p ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var o = { p: {} };\n        (function(a) {\n            console;\n            if (console)\n                (a = a.p).q = a;\n        })(o);\n        console.log(o.p.q === o.p ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nnested_property_assignments_4: {\n    options = {\n        pure_getters: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var n, o = { p: { q: { r: \"PASS\" } } };\n        (n = o.p).r = n.q.r;\n        console.log(o.p.r);\n    }\n    expect: {\n        var n, o = { p: { q: { r: \"PASS\" } } };\n        (n = o.p).r = n.q.r;\n        console.log(o.p.r);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4939: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        ({\n            __proto__: {\n                get p() {\n                    console.log(\"PASS\");\n                },\n            },\n        }).p;\n    }\n    expect: {\n        ({\n            __proto__: {\n                get p() {\n                    console.log(\"PASS\");\n                },\n            },\n        }).p;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5856: {\n    options = {\n        pure_getters: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a = [ \"FAIL\", \"PASS\" ];\n        (function(b) {\n            var c = b[0];\n            b[0] = b[1];\n            b[1] = c;\n        })(a);\n        console.log(a[0]);\n    }\n    expect: {\n        var a = [ \"FAIL\", \"PASS\" ];\n        (function(b) {\n            var c = b[0];\n            b[0] = b[1];\n            b[1] = c;\n        })(a);\n        console.log(a[0]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5917_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a;\n        console || (a = function() {})(f);\n        function f() {\n            a.p;\n        }\n        try {\n            f();\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a;\n        console || (a = function() {})(f);\n        function f() {\n            a.p;\n        }\n        try {\n            f();\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5917_2: {\n    options = {\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var b;\n        if (!console) {\n            b = function() {};\n            FAIL(f);\n        }\n        function f() {\n            b.p;\n        }\n        try {\n            f();\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var b;\n        if (!console) {\n            b = function() {};\n            FAIL(f);\n        }\n        function f() {\n            b.p;\n        }\n        try {\n            f();\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/reduce_vars.js",
    "content": "reduce_vars: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        global_defs: {\n            C: 0,\n        },\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var A = 1;\n        (function f0() {\n            var a = 2;\n            console.log(a - 5);\n            console.log(A - 5);\n        })();\n        (function f1() {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })();\n        (function f2(eval) {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })(eval);\n        (function f3() {\n            var b = typeof C !== \"undefined\";\n            var c = 4;\n            if (b) {\n                return 'yes';\n            } else {\n                return 'no';\n            }\n        })();\n        console.log(A + 1);\n    }\n    expect: {\n        var A = 1;\n        console.log(-3);\n        console.log(A - 5);\n        (function f1() {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })();\n        (function f2(eval) {\n            var a = 2;\n            console.log(a - 5);\n            eval(\"console.log(a);\");\n        })(eval);\n        true, \"yes\";\n        console.log(A + 1);\n    }\n    expect_stdout: true\n}\n\nmodified: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f0() {\n            var a = 1, b = 2;\n            b++;\n            console.log(a + 1);\n            console.log(b + 1);\n        }\n        function f1() {\n            var a = 1, b = 2;\n            --b;\n            console.log(a + 1);\n            console.log(b + 1);\n        }\n        function f2() {\n            var a = 1, b = 2, c = 3;\n            b = c;\n            console.log(a + b);\n            console.log(b + c);\n            console.log(a + c);\n            console.log(a + b + c);\n        }\n        function f3() {\n            var a = 1, b = 2, c = 3;\n            b *= c;\n            console.log(a + b);\n            console.log(b + c);\n            console.log(a + c);\n            console.log(a + b + c);\n        }\n        function f4() {\n            var a = 1, b = 2, c = 3;\n            if (a) {\n                b = c;\n            } else {\n                c = b;\n            }\n            console.log(a + b);\n            console.log(b + c);\n            console.log(a + c);\n            console.log(a + b + c);\n        }\n        function f5(a) {\n            B = a;\n            console.log(typeof A ? \"yes\" : \"no\");\n            console.log(typeof B ? \"yes\" : \"no\");\n        }\n        f0(), f1(), f2(), f3(), f4(), f5();\n    }\n    expect: {\n        function f0() {\n            var b = 2;\n            +b;\n            console.log(2);\n            console.log(4);\n        }\n        function f1() {\n            var b = 2;\n            --b;\n            console.log(2);\n            console.log(2);\n        }\n        function f2() {\n            3;\n            console.log(4);\n            console.log(6);\n            console.log(4);\n            console.log(7);\n        }\n        function f3() {\n            var b = 2;\n            b *= 3;\n            console.log(7);\n            console.log(9);\n            console.log(4);\n            console.log(10);\n        }\n        function f4() {\n            var b = 2, c = 3;\n            1, b = c;\n            console.log(1 + b);\n            console.log(b + c);\n            console.log(1 + c);\n            console.log(1 + b + c);\n        }\n        function f5(a) {\n            B = a;\n            console.log(typeof A ? \"yes\" : \"no\");\n            console.log(typeof B ? \"yes\" : \"no\");\n        }\n        f0(), f1(), f2(), f3(), f4(), f5();\n    }\n    expect_stdout: [\n        \"2\",\n        \"4\",\n        \"2\",\n        \"2\",\n        \"4\",\n        \"6\",\n        \"4\",\n        \"7\",\n        \"7\",\n        \"9\",\n        \"4\",\n        \"10\",\n        \"4\",\n        \"6\",\n        \"4\",\n        \"7\",\n        \"yes\",\n        \"yes\",\n    ]\n}\n\nunsafe_evaluate: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f0() {\n            var a = { b: 1 };\n            console.log(a.b + 3);\n        }\n        function f1() {\n            var a = {\n                b: { c: 1 },\n                d: 2\n            };\n            console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);\n        }\n        f0();\n        f1();\n    }\n    expect: {\n        function f0() {\n            console.log(4);\n        }\n        function f1() {\n            var a = {\n                b: { c: 1 },\n                d: 2\n            };\n            console.log(a.b + 3, 6, 6, NaN);\n        }\n        f0();\n        f1();\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_defun: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            function f() {}\n            return ++f;\n        }());\n    }\n    expect: {\n        console.log(NaN);\n    }\n    expect_stdout: \"NaN\"\n}\n\nunsafe_evaluate_side_effect_free_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(){ var o={p:1}; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:2}; console.log(o.p); return o; }());\n        console.log(function(){ var o={p:3}; console.log([o][0].p); return o.p; }());\n    }\n    expect: {\n        console.log(function(){ console.log(1); return 1; }());\n        console.log(function(){ var o={p:2}; console.log(2); return o; }());\n        console.log(function(){ console.log(3); return 3; }());\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_side_effect_free_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(){ var o={p:1},a=[o]; console.log(a[0].p); return o.p; }());\n    }\n    expect: {\n        console.log(function(){ console.log(1); return 1; }());\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_escaped: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(){ var o={p:1}; console.log(o, o.p); return o.p; }());\n        console.log(function(){ var o={p:2}; console.log(o.p, o); return o.p; }());\n        console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());\n    }\n    expect: {\n        console.log(function(){ var o={p:1}; console.log(o, 1); return o.p; }());\n        console.log(function(){ var o={p:2}; console.log(2, o); return o.p; }());\n        console.log(function(){ var o={p:3},a=[o]; console.log(a[0].p++); return o.p; }());\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_modified: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(){ var o={p:1}; o.p++; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:2}; --o.p; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:3}; o.p += \"\"; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:4}; o = {}; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:5}; o.p = -9; console.log(o.p); return o.p; }());\n        function inc() { this.p++; }\n        console.log(function(){ var o={p:6}; inc.call(o); console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:7}; console.log([o][0].p++); return o.p; }());\n        console.log(function(){ var o={p:8}; console.log({q:o}.q.p++); return o.p; }());\n    }\n    expect: {\n        console.log(function(){ var o={p:1}; o.p++; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:2}; --o.p; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:3}; o.p += \"\"; console.log(o.p); return o.p; }());\n        console.log(function(){ var o; o = {}; console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:5}; o.p = -9; console.log(o.p); return o.p; }());\n        function inc() { this.p++; }\n        console.log(function(){ var o={p:6}; inc.call(o); console.log(o.p); return o.p; }());\n        console.log(function(){ var o={p:7}; console.log([o][0].p++); return o.p; }());\n        console.log(function(){ var o={p:8}; console.log({q:o}.q.p++); return o.p; }());\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_unknown: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(){ var o={p:1}; console.log(o.not_present); return o.p; }());\n        console.log(function(){ var o={p:2}; console.log(o.prototype); return o.p; }());\n        console.log(function(){ var o={p:3}; console.log(o.hasOwnProperty); return o.p; }());\n    }\n    expect: {\n        console.log(function(){ var o={p:1}; console.log(o.not_present); return o.p; }());\n        console.log(function(){ var o={p:2}; console.log(o.prototype); return o.p; }());\n        console.log(function(){ var o={p:3}; console.log(o.hasOwnProperty); return o.p; }());\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_object_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f0(){\n            var a = 1;\n            var b = {};\n            b[a] = 2;\n            console.log(a + 3);\n        }\n\n        function f1(){\n            var a = {\n                b:1\n            };\n            a.b = 2;\n            console.log(a.b + 3);\n        }\n    }\n    expect: {\n        function f0(){\n            var a = 1;\n            var b = {};\n            b[1] = 2;\n            console.log(4);\n        }\n\n        function f1(){\n            var a = {\n                b:1\n            };\n            a.b = 2;\n            console.log(a.b + 3);\n        }\n    }\n}\n\nunsafe_evaluate_object_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var obj = {\n            foo: 1,\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(obj.foo, obj.bar, obj.square(2), obj.cube);\n    }\n    expect: {\n        var obj = {\n            foo: 1,\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(1, 2, obj.square(2), obj.cube);\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_object_3: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var obj = {\n            get foo() {\n                return 1;\n            },\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(obj.foo, obj.bar, obj.square(2), obj.cube);\n    }\n    expect: {\n        var obj = {\n            get foo() {\n                return 1;\n            },\n            bar: 2,\n            square: function(x) {\n                return x * x;\n            },\n            cube: function(x) {\n                return x * x * x;\n            },\n        };\n        console.log(obj.foo, obj.bar, obj.square(2), obj.cube);\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_array_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f0(){\n            var a = 1;\n            var b = [];\n            b[a] = 2;\n            console.log(a + 3);\n        }\n\n        function f1(){\n            var a = [1];\n            a[2] = 3;\n            console.log(a.length);\n        }\n\n        function f2(){\n            var a = [1];\n            a.push(2);\n            console.log(a.length);\n        }\n    }\n    expect: {\n        function f0(){\n            var a = 1;\n            var b = [];\n            b[1] = 2;\n            console.log(4);\n        }\n\n        function f1(){\n            var a = [1];\n            a[2] = 3;\n            console.log(a.length);\n        }\n\n        function f2(){\n            var a = [1];\n            a.push(2);\n            console.log(a.length);\n        }\n    }\n}\n\nunsafe_evaluate_array_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var arr = [\n            1,\n            2,\n            function(x) {\n                return x * x;\n            },\n            function(x) {\n                return x * x * x;\n            },\n        ];\n        console.log(arr[0], arr[1], arr[2](2), arr[3]);\n    }\n    expect: {\n        var arr = [\n            1,\n            2,\n            function(x) {\n                return x * x;\n            },\n            function(x) {\n                return x * x * x;\n            },\n        ];\n        console.log(1, 2, arr[2](2), arr[3]);\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_array_3: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var arr = [\n            1,\n            2,\n            function() {\n                return ++arr[0];\n            },\n        ];\n        console.log(arr[0], arr[1], arr[2](), arr[0]);\n    }\n    expect: {\n        var arr = [\n            1,\n            2,\n            function() {\n                return ++arr[0];\n            },\n        ];\n        console.log(arr[0], arr[1], arr[2](), arr[0]);\n    }\n    expect_stdout: \"1 2 2 2\"\n}\n\nunsafe_evaluate_array_4: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var arr = [\n            1,\n            2,\n            function() {\n                return ++this[0];\n            },\n        ];\n        console.log(arr[0], arr[1], arr[2], arr[0]);\n    }\n    expect: {\n        var arr = [\n            1,\n            2,\n            function() {\n                return ++this[0];\n            },\n        ];\n        console.log(1, 2, arr[2], 1);\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_array_5: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var arr = [\n            1,\n            2,\n            function() {\n                return ++this[0];\n            },\n        ];\n        console.log(arr[0], arr[1], arr[2](), arr[0]);\n    }\n    expect: {\n        var arr = [\n            1,\n            2,\n            function() {\n                return ++this[0];\n            },\n        ];\n        console.log(arr[0], arr[1], arr[2](), arr[0]);\n    }\n    expect_stdout: \"1 2 2 2\"\n}\n\nunsafe_evaluate_equality_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f0() {\n            var a = {};\n            return a === a;\n        }\n        function f1() {\n            var a = [];\n            return a === a;\n        }\n        console.log(f0(), f1());\n    }\n    expect: {\n        function f0() {\n            return true;\n        }\n        function f1() {\n            return true;\n        }\n        console.log(f0(), f1());\n    }\n    expect_stdout: true\n}\n\nunsafe_evaluate_equality_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f2() {\n            var a = {a:1, b:2};\n            var b = a;\n            var c = a;\n            return b === c;\n        }\n        function f3() {\n            var a = [1, 2, 3];\n            var b = a;\n            var c = a;\n            return b === c;\n        }\n        console.log(f2(), f3());\n    }\n    expect: {\n        function f2() {\n            return true;\n        }\n        function f3() {\n            return true;\n        }\n        console.log(f2(), f3());\n    }\n    expect_stdout: true\n}\n\npasses: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a = 1, b = 2, c = 3;\n            if (a) {\n                b = c;\n            } else {\n                c = b;\n            }\n            console.log(a + b);\n            console.log(b + c);\n            console.log(a + c);\n            console.log(a + b + c);\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(4),\n            console.log(6),\n            console.log(4),\n            console.log(7);\n        })();\n    }\n    expect_stdout: [\n        \"4\",\n        \"6\",\n        \"4\",\n        \"7\",\n    ]\n}\n\niife: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        !function(a, b, c) {\n            b++;\n            console.log(a - 1, b * 1, c + 2);\n        }(1, 2, 3);\n    }\n    expect: {\n        !function(a, b, c) {\n            b++;\n            console.log(0, 3, 5);\n        }(1, 2, 3);\n    }\n    expect_stdout: true\n}\n\niife_new: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        var A = new function(a, b, c) {\n            b++;\n            console.log(a - 1, b * 1, c + 2);\n        }(1, 2, 3);\n    }\n    expect: {\n        var A = new function(a, b, c) {\n            b++;\n            console.log(0, 3, 5);\n        }(1, 2, 3);\n    }\n    expect_stdout: true\n}\n\nmulti_def_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            if (a)\n                var b = 1;\n            else\n                var b = 2;\n            console.log(b + 1);\n        }\n    }\n    expect: {\n        function f(a) {\n            if (a)\n                var b = 1;\n            else\n                var b = 2;\n            console.log(b + 1);\n        }\n    }\n}\n\nmulti_def_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(){\n            if (code == 16)\n                var bitsLength = 2, bitsOffset = 3, what = len;\n            else if (code == 17)\n                var bitsLength = 3, bitsOffset = 3, what = (len = 0);\n            else if (code == 18)\n                var bitsLength = 7, bitsOffset = 11, what = (len = 0);\n            var repeatLength = this.getBits(bitsLength) + bitsOffset;\n        }\n    }\n    expect: {\n        function f(){\n            if (16 == code)\n                var bitsLength = 2, bitsOffset = 3, what = len;\n            else if (17 == code)\n                var bitsLength = 3, bitsOffset = 3, what = (len = 0);\n            else if (18 == code)\n                var bitsLength = 7, bitsOffset = 11, what = (len = 0);\n            var repeatLength = this.getBits(bitsLength) + bitsOffset;\n        }\n    }\n}\n\nmulti_def_3: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            var b = 2;\n            if (a)\n                var b;\n            else\n                var b;\n            console.log(b + 1);\n        }\n    }\n    expect: {\n        function f(a) {\n            var b = 2;\n            if (a)\n                var b;\n            else\n                var b;\n            console.log(3);\n        }\n    }\n}\n\nuse_before_var: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(){\n            console.log(t);\n            var t = 1;\n        }\n    }\n    expect: {\n        function f(){\n            console.log(t);\n            var t = 1;\n        }\n    }\n}\n\ninner_var_if: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a){\n            if (a)\n                var t = 1;\n            if (!t)\n                console.log(t);\n        }\n    }\n    expect: {\n        function f(a){\n            if (a)\n                var t = 1;\n            if (!t)\n                console.log(t);\n        }\n    }\n}\n\ninner_var_label: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a){\n            l: {\n                if (a) break l;\n                var t = 1;\n            }\n            console.log(t);\n        }\n    }\n    expect: {\n        function f(a){\n            l: {\n                if (a) break l;\n                var t = 1;\n            }\n            console.log(t);\n        }\n    }\n}\n\ninner_var_for_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            var a = 1;\n            x(a, b, d);\n            for (var b = 2, c = 3; x(a, b, c, d); x(a, b, c, d)) {\n                var d = 4, e = 5;\n                x(a, b, c, d, e);\n            }\n            x(a, b, c, d, e);\n        }\n    }\n    expect: {\n        function f() {\n            var a = 1;\n            x(1, b, d);\n            for (var b = 2, c = 3; x(1, 2, 3, d); x(1, 2, 3, d)) {\n                var d = 4, e = 5;\n                x(1, 2, 3, d, e);\n            }\n            x(1, 2, 3, d, e);\n        }\n    }\n}\n\ninner_var_for_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a = 1;\n            for (var b = 1; --b;) var a = 2;\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            var a = 1;\n            for (var b = 1; --b;) a = 2;\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"1\"\n}\n\ninner_var_for_in_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            var a = 1, b = 2;\n            for (b in (function() {\n                return x(a, b, c);\n            })()) {\n                var c = 3, d = 4;\n                x(a, b, c, d);\n            }\n            x(a, b, c, d);\n        }\n    }\n    expect: {\n        function f() {\n            var a = 1, b = 2;\n            for (b in (function() {\n                return x(1, b, c);\n            })()) {\n                var c = 3, d = 4;\n                x(1, b, c, d);\n            }\n            x(1, b, c, d);\n        }\n    }\n}\n\ninner_var_for_in_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            for (var long_name in {})\n                console.log(long_name);\n        }\n    }\n    expect: {\n        function f() {\n            for (var long_name in {})\n                console.log(long_name);\n        }\n    }\n}\n\ninner_var_catch: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            try {\n                a();\n            } catch (e) {\n                var b = 1;\n            }\n            console.log(b);\n        }\n    }\n    expect: {\n        function f() {\n            try {\n                a();\n            } catch (e) {\n                var b = 1;\n            }\n            console.log(b);\n        }\n    }\n}\n\nissue_1533_1: {\n    options = {\n        collapse_vars: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            var id = \"\";\n            for (id in {break: \"me\"})\n                console.log(id);\n        }\n    }\n    expect: {\n        function f() {\n            var id = \"\";\n            for (id in {break: \"me\"})\n                console.log(id);\n        }\n    }\n}\n\nissue_1533_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            var id = \"\";\n            for (var id in {break: \"me\"})\n                console.log(id);\n            console.log(id);\n        }\n    }\n    expect: {\n        function f() {\n            var id = \"\";\n            for (var id in {break: \"me\"})\n                console.log(id);\n            console.log(id);\n        }\n    }\n}\n\ntoplevel_on: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = 3;\n        console.log(x);\n    }\n    expect: {\n        console.log(3);\n    }\n    expect_stdout: true\n}\n\ntoplevel_off: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        var x = 3;\n        console.log(x);\n    }\n    expect: {\n        var x = 3;\n        console.log(x);\n    }\n    expect_stdout: true\n}\n\ntoplevel_on_loops_1: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function bar() {\n            console.log(\"bar:\", --x);\n        }\n        var x = 3;\n        do\n            bar();\n        while (x);\n    }\n    expect: {\n        var x = 3;\n        for (;function() {\n            console.log(\"bar:\", --x);\n        }(), x;);\n    }\n    expect_stdout: true\n}\n\ntoplevel_off_loops_1: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        function bar() {\n            console.log(\"bar:\", --x);\n        }\n        var x = 3;\n        do\n            bar();\n        while (x);\n    }\n    expect: {\n        function bar() {\n            console.log(\"bar:\", --x);\n        }\n        var x = 3;\n        for (;bar(), x;);\n    }\n    expect_stdout: true\n}\n\ntoplevel_on_loops_2: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function bar() {\n            console.log(\"bar:\");\n        }\n        var x = 3;\n        do\n            bar();\n        while (x);\n    }\n    expect: {\n        for (;;) (function() {\n            console.log(\"bar:\");\n        })();\n    }\n}\n\ntoplevel_off_loops_2: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        function bar() {\n            console.log(\"bar:\");\n        }\n        var x = 3;\n        do\n            bar();\n        while (x);\n    }\n    expect: {\n        function bar() {\n            console.log(\"bar:\");\n        }\n        var x = 3;\n        for (;bar(), x;);\n    }\n}\n\ntoplevel_on_loops_3: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = 3;\n        while (x) bar();\n    }\n    expect: {\n        for (;;) bar();\n    }\n}\n\ntoplevel_off_loops_3: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        var x = 3;\n        while (x) bar();\n    }\n    expect: {\n        var x = 3;\n        for (;x;) bar();\n    }\n}\n\ndefun_reference: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                x();\n                return a;\n            }\n            var a = h();\n            var b = 2;\n            return a + b;\n            function h() {\n                y();\n                return b;\n            }\n        }\n    }\n    expect: {\n        function f() {\n            function g() {\n                x();\n                return a;\n            }\n            var a = h();\n            var b = 2;\n            return a + b;\n            function h() {\n                y();\n                return b;\n            }\n        }\n    }\n}\n\ndefun_inline_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return g(2) + h();\n            function g(b) {\n                return b;\n            }\n            function h() {\n                return h();\n            }\n        }\n    }\n    expect: {\n        function f() {\n            return function(b) {\n                return b;\n            }(2) + function h() {\n                return h();\n            }();\n        }\n    }\n}\n\ndefun_inline_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g(b) {\n                return b;\n            }\n            function h() {\n                return h();\n            }\n            return g(2) + h();\n        }\n    }\n    expect: {\n        function f() {\n            return function(b) {\n                return b;\n            }(2) + function h() {\n                return h();\n            }();\n        }\n    }\n}\n\ndefun_inline_3: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return g(2);\n            function g(b) {\n                return b;\n            }\n        }\n    }\n    expect: {\n        function f() {\n            return 2;\n        }\n    }\n}\n\ndefun_call: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {\n            return g() + h(1) - h(g(), 2, 3);\n            function g() {\n                return 4;\n            }\n            function h(a) {\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\ndefun_redefine: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                return 1;\n            }\n            function h() {\n                return 2;\n            }\n            g = function() {\n                return 3;\n            };\n            return g() + h();\n        }\n        console.log(f());\n    }\n    expect:  {\n        function f() {\n            (function() {\n                return 3;\n            });\n            return 5;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"5\"\n}\n\nfunc_inline: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var g = function() {\n                return 1;\n            };\n            console.log(g() + h());\n            var h = function() {\n                return 2;\n            };\n        }\n    }\n    expect: {\n        function f() {\n            console.log(1 + (void 0)());\n        }\n    }\n}\n\nfunc_modified: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            function a() {\n                return 1;\n            }\n            function b() {\n                return 2;\n            }\n            function c() {\n                return 3;\n            }\n            b.inject = [];\n            c = function() {\n                return 4;\n            };\n            return a() + b() + c();\n        }\n        console.log(f());\n    }\n    expect: {\n        function f(a) {\n            function b() {\n                return 2;\n            }\n            b.inject = [];\n            (function() {\n                return 4;\n            });\n            return 7;\n        }\n        console.log(f());\n    }\n    expect_stdout: \"7\"\n}\n\nunused_modified: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var b = 1, c = \"FAIL\";\n            if (0 || b--)\n                c = \"PASS\";\n            b = 1;\n            return c;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var b = 1, c = \"FAIL\";\n            if (0 || b--)\n                c = \"PASS\";\n            b = 1;\n            return c;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\ndefun_label: {\n    options = {\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function f(a) {\n                L: {\n                    if (a) break L;\n                    return 1;\n                }\n            }\n            console.log(f(2));\n        }();\n    }\n    expect: {\n        !function() {\n            console.log(function(a) {\n                L: {\n                    if (2) break L;\n                    return 1;\n                }\n            }());\n        }();\n    }\n    expect_stdout: true\n}\n\ndouble_reference_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var g = function g() {\n                g();\n            };\n            g();\n        }\n    }\n    expect: {\n        function f() {\n            var g = function g() {\n                g();\n            };\n            g();\n        }\n    }\n}\n\ndouble_reference_2: {\n    options = {\n        functions: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var g = function g() {\n                g();\n            };\n            g();\n        }\n    }\n    expect: {\n        function f() {\n            (function g() {\n                g();\n            })();\n        }\n    }\n}\n\ndouble_reference_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = function f() {\n            return f;\n        };\n        function g() {\n            return x();\n        }\n        console.log(g() === g());\n    }\n    expect: {\n        var x = function f() {\n            return f;\n        };\n        function g() {\n            return x();\n        }\n        console.log(g() === g());\n    }\n    expect_stdout: \"true\"\n}\n\ndouble_reference_4: {\n    options = {\n        comparisons: true,\n        functions: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = function f() {\n            return f;\n        };\n        function g() {\n            return x();\n        }\n        console.log(g() === g());\n    }\n    expect: {\n        console.log(true);\n    }\n    expect_stdout: \"true\"\n}\n\niife_arguments_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(x) {\n            console.log(x() === arguments[0]);\n        })(function f() {\n            return f;\n        });\n    }\n    expect: {\n        (function(x) {\n            console.log(x() === arguments[0]);\n        })(function f() {\n            return f;\n        });\n    }\n    expect_stdout: true\n}\n\niife_arguments_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var x = function f() {\n                return f;\n            };\n            console.log(x() === arguments[0]);\n        })();\n    }\n    expect: {\n        (function() {\n            var x = function f() {\n                return f;\n            };\n            console.log(x() === arguments[0]);\n        })();\n    }\n    expect_stdout: true\n}\n\niife_arguments_3: {\n    options = {\n        functions: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var x = function f() {\n                return f;\n            };\n            console.log(x() === arguments[0]);\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(function x() {\n                return x;\n            }() === arguments[0]);\n        })();\n    }\n    expect_stdout: true\n}\n\niife_eval_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(x) {\n            console.log(x() === eval(\"x\"));\n        })(function f() {\n            return f;\n        });\n    }\n    expect: {\n        (function(x) {\n            console.log(x() === eval(\"x\"));\n        })(function f() {\n            return f;\n        });\n    }\n    expect_stdout: true\n}\n\niife_eval_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var x = function f() {\n                return f;\n            };\n            console.log(x() === eval(\"x\"));\n        })();\n    }\n    expect: {\n        (function() {\n            var x = function f() {\n                return f;\n            };\n            console.log(x() === eval(\"x\"));\n        })();\n    }\n    expect_stdout: true\n}\n\niife_func_side_effects: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function x() {\n            console.log(\"x\");\n        }\n        function y() {\n            console.log(\"y\");\n        }\n        function z() {\n            console.log(\"z\");\n        }\n        (function(a, b, c) {\n            function y() {\n                console.log(\"FAIL\");\n            }\n            return y + b();\n        })(x(), function() {\n            return y();\n        }, z());\n    }\n    expect: {\n        function x() {\n            console.log(\"x\");\n        }\n        function y() {\n            console.log(\"y\");\n        }\n        function z() {\n            console.log(\"z\");\n        }\n        (function(a, b, c) {\n            return function() {\n                console.log(\"FAIL\");\n            } + b();\n        })(x(), function() {\n            return y();\n        }, z());\n    }\n    expect_stdout: [\n        \"x\",\n        \"z\",\n        \"y\",\n    ]\n}\n\nissue_1595_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return f(a + 1);\n        })(2);\n    }\n    expect: {\n        (function f(a) {\n            return f(a + 1);\n        })(2);\n    }\n}\n\nissue_1595_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return g(a + 1);\n        })(2);\n    }\n    expect: {\n        (function(a) {\n            return g(a + 1);\n        })(2);\n    }\n}\n\nissue_1595_3: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            return g(a + 1);\n        })(2);\n    }\n    expect: {\n        (function(a) {\n            return g(3);\n        })();\n    }\n}\n\nissue_1595_4: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function iife(a, b, c) {\n            console.log(a, b, c);\n            if (a) iife(a - 1, b, c);\n        })(3, 4, 5);\n    }\n    expect: {\n        (function iife(a, b, c) {\n            console.log(a, b, c);\n            if (a) iife(a - 1, b, c);\n        })(3, 4, 5);\n    }\n    expect_stdout: true\n}\n\nissue_1606: {\n    options = {\n        evaluate: true,\n        hoist_vars: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f() {\n            var a;\n            function g(){};\n            var b = 2;\n            x(b);\n        }\n    }\n    expect: {\n        function f() {\n            var a, b;\n            function g(){};\n            b = 2;\n            x(2);\n        }\n    }\n}\n\nissue_1670_1: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        switches: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        (function f() {\n            switch (1) {\n              case 0:\n                var a = true;\n                break;\n              default:\n                if (typeof a === \"undefined\") console.log(\"PASS\");\n                else console.log(\"FAIL\");\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            var a;\n            void 0 === a ? console.log(\"PASS\") : console.log(\"FAIL\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1670_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        switches: true,\n        unused: true,\n    }\n    input: {\n        (function f() {\n            switch (1) {\n              case 0:\n                var a = true;\n                break;\n              default:\n                if (typeof a === \"undefined\") console.log(\"PASS\");\n                else console.log(\"FAIL\");\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1670_3: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        switches: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            switch (1) {\n              case a:\n                console.log(a);\n                break;\n              default:\n                console.log(2);\n                break;\n            }\n        })(1);\n    }\n    expect: {\n        (function() {\n            console.log(1);\n        })();\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1670_4: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        switches: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            switch (1) {\n              case a = 1:\n                console.log(a);\n                break;\n              default:\n                console.log(2);\n                break;\n            }\n        })(1);\n    }\n    expect: {\n        (function() {\n            console.log(1);\n        })();\n    }\n    expect_stdout: \"1\"\n}\n\nunary_delete: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var b = 10;\n        function f() {\n            var a;\n            if (delete a) b--;\n        }\n        f();\n        console.log(b);\n    }\n    expect: {\n        var b = 10;\n        function f() {\n            var a;\n            if (delete a) b--;\n        }\n        f();\n        console.log(b);\n    }\n    expect_stdout: true\n}\n\nredefine_arguments_1: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var arguments;\n            return typeof arguments;\n        }\n        function g() {\n            var arguments = 42;\n            return typeof arguments;\n        }\n        function h(x) {\n            var arguments = x;\n            return typeof arguments;\n        }\n        console.log(f(), g(), h());\n    }\n    expect: {\n        function f() {\n            var arguments;\n            return typeof arguments;\n        }\n        function g() {\n            return \"number\";\n        }\n        function h(x) {\n            var arguments = x;\n            return typeof arguments;\n        }\n        console.log(f(), g(), h());\n    }\n    expect_stdout: \"object number undefined\"\n}\n\nredefine_arguments_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var arguments;\n            return typeof arguments;\n        }\n        function g() {\n            var arguments = 42;\n            return typeof arguments;\n        }\n        function h(x) {\n            var arguments = x;\n            return typeof arguments;\n        }\n        console.log(f(), g(), h());\n    }\n    expect: {\n        console.log(function() {\n            var arguments;\n            return typeof arguments;\n        }(), \"number\", function(x) {\n            var arguments = x;\n            return typeof arguments;\n        }());\n    }\n    expect_stdout: \"object number undefined\"\n}\n\nredefine_arguments_3: {\n    options = {\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var arguments;\n            return typeof arguments;\n        }\n        function g() {\n            var arguments = 42;\n            return typeof arguments;\n        }\n        function h(x) {\n            var arguments = x;\n            return typeof arguments;\n        }\n        console.log(f(), g(), h());\n    }\n    expect: {\n        console.log(function() {\n            var arguments;\n            return typeof arguments;\n        }(), \"number\", function(x) {\n            var arguments = x;\n            return typeof arguments;\n        }());\n    }\n    expect_stdout: \"object number undefined\"\n}\n\nredefine_farg_1: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var a;\n            return typeof a;\n        }\n        function g(a) {\n            var a = 42;\n            return typeof a;\n        }\n        function h(a, b) {\n            var a = b;\n            return typeof a;\n        }\n        console.log(f([]), g([]), h([]));\n    }\n    expect: {\n        function f(a) {\n            return typeof a;\n        }\n        function g(a) {\n            return \"number\";\n        }\n        function h(a, b) {\n            a = b;\n            return typeof a;\n        }\n        console.log(f([]), g([]), h([]));\n    }\n    expect_stdout: \"object number undefined\"\n}\n\nredefine_farg_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var a;\n            return typeof a;\n        }\n        function g(a) {\n            var a = 42;\n            return typeof a;\n        }\n        function h(a, b) {\n            var a = b;\n            return typeof a;\n        }\n        console.log(f([]), g([]), h([]));\n    }\n    expect: {\n        console.log(typeof [], \"number\",function(a, b) {\n            a = b;\n            return typeof a;\n        }());\n    }\n    expect_stdout: \"object number undefined\"\n}\n\nredefine_farg_3: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 3,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var a;\n            return typeof a;\n        }\n        function g(a) {\n            var a = 42;\n            return typeof a;\n        }\n        function h(a, b) {\n            var a = b;\n            return typeof a;\n        }\n        console.log(f([]), g([]), h([]));\n    }\n    expect: {\n        console.log(typeof [], \"number\", \"undefined\");\n    }\n    expect_stdout: \"object number undefined\"\n}\n\ndelay_def: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return a;\n            var a;\n        }\n        function g() {\n            return a;\n            var a = 1;\n        }\n        console.log(f(), g());\n    }\n    expect: {\n        function f() {\n            return;\n        }\n        function g() {\n            return;\n        }\n        console.log(f(), g());\n    }\n    expect_stdout: true\n}\n\ndelay_def_lhs: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            long_name++;\n            return long_name;\n            var long_name;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            long_name++;\n            return NaN;\n            var long_name;\n        }());\n    }\n    expect_stdout: \"NaN\"\n}\n\nbooleans: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            if (a != 0);\n            switch (a) {\n              case 0:\n                return \"FAIL\";\n              case false:\n                return \"PASS\";\n            }\n        }(false));\n    }\n    expect: {\n        console.log(function(a) {\n            if (0);\n            switch (!1) {\n              case 0:\n                return \"FAIL\";\n              case !1:\n                return \"PASS\";\n            }\n        }(!1));\n    }\n    expect_stdout: \"PASS\"\n}\n\nside_effects_assign: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = typeof void (a && a.in == 1, 0);\n        console.log(a);\n    }\n    expect: {\n        var a = \"undefined\";\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\npure_getters_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            var a = (a.b, 2);\n        } catch (e) {}\n        console.log(a);\n    }\n    expect: {\n        try {\n            var a = (a.b, 2);\n        } catch (e) {}\n        console.log(a);\n    }\n    expect_stdout: \"undefined\"\n}\n\npure_getters_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        var a = a && a.b;\n    }\n    expect: {\n        var a;\n        a && a.b;\n    }\n}\n\npure_getters_3: {\n    options = {\n        pure_getters: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        var a = a && a.b;\n    }\n    expect: {\n    }\n}\n\ncatch_var: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        try {\n            throw {};\n        } catch (e) {\n            var e;\n            console.log(!!e);\n        }\n    }\n    expect: {\n        try {\n            throw {};\n        } catch (e) {\n            var e;\n            console.log(!!e);\n        }\n    }\n    expect_stdout: \"true\"\n}\n\nvar_assign_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a;\n            a = 2;\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            console.log(2);\n        }();\n    }\n    expect_stdout: \"2\"\n}\n\nvar_assign_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a;\n            if (a = 2) console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            if (2) console.log(2);\n        }();\n    }\n    expect_stdout: \"2\"\n}\n\nvar_assign_3: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a;\n            while (a = 2);\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            var a;\n            while (a = 2);\n            console.log(a);\n        }();\n    }\n}\n\nvar_assign_4: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        !function a() {\n            a = 2;\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function a() {\n            a = 2,\n            console.log(a);\n        }();\n    }\n}\n\nvar_assign_5: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a;\n            !function(b) {\n                a = 2;\n                console.log(a, b);\n            }(a);\n        }();\n    }\n    expect: {\n        !function() {\n            !function(b) {\n                console.log(2, void 0);\n            }();\n        }();\n    }\n    expect_stdout: \"2 undefined\"\n}\n\nvar_assign_6: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a = function(){}(a = 1);\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            (function(){}());\n            console.log(void 0);\n        }();\n    }\n    expect_stdout: \"undefined\"\n}\n\nimmutable: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a = \"test\";\n            console.log(a.indexOf(\"e\"));\n        }();\n    }\n    expect: {\n        !function() {\n            console.log(\"test\".indexOf(\"e\"));\n        }();\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1814_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        !function() {\n            var b = a;\n            !function(a) {\n                console.log(a++, b);\n            }(0);\n        }();\n    }\n    expect: {\n        !function() {\n            !function(a) {\n                console.log(0, 42);\n            }();\n        }();\n    }\n    expect_stdout: \"0 42\"\n}\n\nissue_1814_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"32\";\n        !function() {\n            var b = a + 1;\n            !function(a) {\n                console.log(b, a++);\n            }(0);\n        }();\n    }\n    expect: {\n        !function() {\n            !function(a) {\n                console.log(\"321\", 0);\n            }();\n        }();\n    }\n    expect_stdout: \"321 0\"\n}\n\ntry_abort: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            try {\n                var a = 1;\n                throw \"\";\n                var b = 2;\n            } catch (e) {\n            }\n            console.log(a, b);\n        }();\n    }\n    expect: {\n        !function() {\n            try {\n                var a = 1;\n                throw \"\";\n                var b = 2;\n            } catch (e) {\n            }\n            console.log(a, b);\n        }();\n    }\n    expect_stdout: \"1 undefined\"\n}\n\nboolean_binary_assign: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a;\n            void 0 && (a = 1);\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            var a;\n            void 0;\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"undefined\"\n}\n\ncond_assign: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a;\n            void 0 ? (a = 1) : 0;\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            var a;\n            void 0 ? (a = 1) : 0;\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"undefined\"\n}\n\niife_assign: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            var a = 1, b = 0;\n            !function() {\n                b++;\n                return;\n                a = 2;\n            }();\n            console.log(a);\n        }();\n    }\n    expect: {\n        !function() {\n            var a = 1, b = 0;\n            !function() {\n                b++;\n                return;\n                a = 2;\n            }();\n            console.log(a);\n        }();\n    }\n    expect_stdout: \"1\"\n}\n\nissue_1850_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: false,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(a, a, a);\n        }\n        var a = 1;\n        f();\n    }\n    expect: {\n        function f() {\n            console.log(a, a, a);\n        }\n        var a = 1;\n        f();\n    }\n    expect_stdout: true\n}\n\nissue_1850_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: \"funcs\",\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(a, a, a);\n        }\n        var a = 1;\n        f();\n    }\n    expect: {\n        var a = 1;\n        (function() {\n            console.log(a, a, a);\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_1850_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: \"vars\",\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(a, a, a);\n        }\n        var a = 1;\n        f();\n    }\n    expect: {\n        function f() {\n            console.log(a, a, a);\n        }\n        var a = 1;\n        f();\n    }\n    expect_stdout: true\n}\n\nissue_1850_4: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(a, a, a);\n        }\n        var a = 1;\n        f();\n    }\n    expect: {\n        var a = 1;\n        (function() {\n            console.log(a, a, a);\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_1865: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unsafe: true,\n    }\n    input: {\n        function f(some) {\n            some.thing = false;\n        }\n        console.log(function() {\n            var some = { thing: true };\n            f(some);\n            return some.thing;\n        }());\n    }\n    expect: {\n        function f(some) {\n            some.thing = false;\n        }\n        console.log(function() {\n            var some = { thing: true };\n            f(some);\n            return some.thing;\n        }());\n    }\n    expect_stdout: true\n}\n\nissue_1922_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            arguments[0] = 2;\n            return a;\n        }(1));\n    }\n    expect: {\n        console.log(function(a) {\n            arguments[0] = 2;\n            return a;\n        }(1));\n    }\n    expect_stdout: \"2\"\n}\n\nissue_1922_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a;\n            eval(\"a = 1\");\n            return a;\n        }(1));\n    }\n    expect: {\n        console.log(function() {\n            var a;\n            eval(\"a = 1\");\n            return a;\n        }(1));\n    }\n    expect_stdout: \"1\"\n}\n\naccessor_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1;\n        console.log({\n            get a() {\n                a = 2;\n                return a;\n            },\n            b: 1,\n        }.b, a);\n    }\n    expect: {\n        var a = 1;\n        console.log({\n            get a() {\n                a = 2;\n                return a;\n            },\n            b: 1,\n        }.b, a);\n    }\n    expect_stdout: \"1 1\"\n}\n\naccessor_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var A = 1;\n        var B = {\n            get c() {\n                console.log(A);\n            },\n        };\n        B.c;\n    }\n    expect: {\n        ({\n            get c() {\n                console.log(1);\n            },\n        }).c;\n    }\n    expect_stdout: \"1\"\n}\n\nfor_in_prop: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = {\n            foo: function() {\n                for (this.b in [1, 2]);\n            }\n        };\n        a.foo();\n        console.log(a.b);\n    }\n    expect: {\n        var a = {\n            foo: function() {\n                for (this.b in [1, 2]);\n            }\n        };\n        a.foo();\n        console.log(a.b);\n    }\n    expect_stdout: \"1\"\n}\n\nobj_var_1: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var C = 1;\n        var obj = {\n            bar: function() {\n                return C + C;\n            },\n        };\n        console.log(obj.bar());\n    }\n    expect: {\n        console.log({\n            bar: function() {\n                return 2;\n            },\n        }.bar());\n    }\n    expect_stdout: \"2\"\n}\n\nobj_var_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var C = 1;\n        var obj = {\n            bar: function() {\n                return C + C;\n            },\n        };\n        console.log(obj.bar());\n    }\n    expect: {\n        console.log(2);\n    }\n    expect_stdout: \"2\"\n}\n\nobj_arg_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var C = 1;\n        function f(obj) {\n            return obj.bar();\n        }\n        console.log(f({\n            bar: function() {\n                return C + C;\n            }\n        }));\n    }\n    expect: {\n        console.log({\n            bar: function() {\n                return 2;\n            }\n        }.bar());\n    }\n    expect_stdout: \"2\"\n}\n\nobj_arg_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        properties: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var C = 1;\n        function f(obj) {\n            return obj.bar();\n        }\n        console.log(f({\n            bar: function() {\n                return C + C;\n            }\n        }));\n    }\n    expect: {\n        console.log(2);\n    }\n    expect_stdout: \"2\"\n}\n\nfunc_arg_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        !function(a) {\n            console.log(a());\n        }(function() {\n            return a;\n        });\n    }\n    expect: {\n        console.log(42);\n    }\n    expect_stdout: \"42\"\n}\n\nfunc_arg_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 42;\n        !function(a) {\n            console.log(a());\n        }(function(a) {\n            return a;\n        });\n    }\n    expect: {\n        console.log(void 0);\n    }\n    expect_stdout: \"undefined\"\n}\n\nregex_loop: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(x) {\n            for (var r, s = \"acdabcdeabbb\"; r = x().exec(s);)\n                console.log(r[0]);\n        }\n        var a = /ab*/g;\n        f(function() {\n            return a;\n        });\n    }\n    expect: {\n        var a = /ab*/g;\n        (function(x) {\n            for (var r, s = \"acdabcdeabbb\"; r = x().exec(s);)\n                console.log(r[0]);\n        })(function() {\n            return a;\n        });\n    }\n    expect_stdout: true\n}\n\nobj_for_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = { a: 1 };\n        for (var i = o.a--; i; i--)\n            console.log(i);\n    }\n    expect: {\n        for (var i = { a: 1 }.a--; i; i--)\n            console.log(i);\n    }\n    expect_stdout: \"1\"\n}\n\nobj_for_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = { a: 1 };\n        for (var i; i = o.a--;)\n            console.log(i);\n    }\n    expect: {\n        var o = { a: 1 };\n        for (var i; i = o.a--;)\n            console.log(i);\n    }\n    expect_stdout: \"1\"\n}\n\narray_forin_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = [ 1, 2, 3 ];\n        for (var b in a)\n            console.log(b);\n    }\n    expect: {\n        for (var b in [ 1, 2, 3 ])\n            console.log(b);\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n        \"2\",\n    ]\n}\n\narray_forin_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = [];\n        for (var b in [ 1, 2, 3 ])\n            a.push(b);\n        console.log(a.length);\n    }\n    expect: {\n        var a = [];\n        for (var b in [ 1, 2, 3 ])\n            a.push(b);\n        console.log(a.length);\n    }\n    expect_stdout: \"3\"\n}\n\nconst_expr_1: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2\n        };\n        o.a++;\n        console.log(o.a, o.b);\n    }\n    expect: {\n        var o = {\n            a: 1,\n            b: 2\n        };\n        o.a++;\n        console.log(o.a, o.b);\n    }\n    expect_stdout: \"2 2\"\n}\n\nconst_expr_2: {\n    options = {\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        Object.prototype.c = function() {\n            this.a++;\n        };\n        var o = {\n            a: 1,\n            b: 2\n        };\n        o.c();\n        console.log(o.a, o.b);\n    }\n    expect: {\n        Object.prototype.c = function() {\n            this.a++;\n        };\n        var o = {\n            a: 1,\n            b: 2\n        };\n        o.c();\n        console.log(o.a, o.b);\n    }\n    expect_stdout: \"2 2\"\n}\n\nescaped_prop_1: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var obj = { o: { a: 1 } };\n        (function(o) {\n            o.a++;\n        })(obj.o);\n        (function(o) {\n            console.log(o.a);\n        })(obj.o);\n    }\n    expect: {\n        var obj = { o: { a: 1 } };\n        obj.o.a++;\n        console.log(obj.o.a);\n    }\n    expect_stdout: \"2\"\n}\n\nescaped_prop_2: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var obj = { o: { a: 1 } };\n        (function(o) {\n            o.a++;\n        })(obj.o);\n        (function(o) {\n            console.log(o.a);\n        })(obj.o);\n    }\n    expect: {\n        var obj = { o: { a: 1 } };\n        obj.o.a++;\n        console.log(obj.o.a);\n    }\n    expect_stdout: \"2\"\n}\n\nescaped_prop_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            if (a) console.log(a === b.c);\n            a = b.c;\n        }\n        function g() {}\n        function h() {\n            f({ c: g });\n        }\n        h();\n        h();\n    }\n    expect: {\n        var a;\n        function g() {}\n        function h() {\n            (function(b) {\n                if (a) console.log(a === b.c);\n                a = b.c;\n            })({ c: g });\n        }\n        h();\n        h();\n    }\n    expect_stdout: \"true\"\n}\n\nissue_2420_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function run() {\n            var self = this;\n            if (self.count++)\n                self.foo();\n            else\n                self.bar();\n        }\n        var o = {\n            count: 0,\n            foo: function() { console.log(\"foo\"); },\n            bar: function() { console.log(\"bar\"); },\n        };\n        run.call(o);\n        run.call(o);\n    }\n    expect: {\n        function run() {\n            if (this.count++)\n                this.foo();\n            else\n                this.bar();\n        }\n        var o = {\n            count: 0,\n            foo: function() { console.log(\"foo\"); },\n            bar: function() { console.log(\"bar\"); },\n        };\n        run.call(o);\n        run.call(o);\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nissue_2420_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var that = this;\n            if (that.bar)\n                that.foo();\n            else\n                !function(that, self) {\n                    console.log(this === that, self === this, that === self);\n                }(that, this);\n        }\n        f.call({\n            bar: 1,\n            foo: function() { console.log(\"foo\", this.bar); },\n        });\n        f.call({});\n    }\n    expect: {\n        function f() {\n            if (this.bar)\n                this.foo();\n            else\n                !function(that, self) {\n                    console.log(this === that, self === this, that === self);\n                }(this, this);\n        }\n        f.call({\n            bar: 1,\n            foo: function() { console.log(\"foo\", this.bar); },\n        });\n        f.call({});\n    }\n    expect_stdout: [\n        \"foo 1\",\n        \"false false true\",\n    ]\n}\n\nissue_2423_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function c() { return 1; }\n        function p() { console.log(c()); }\n        p();\n        p();\n    }\n    expect: {\n        function p() { console.log(function() { return 1; }()); }\n        p();\n        p();\n    }\n    expect_stdout: [\n        \"1\",\n        \"1\",\n    ]\n}\n\nissue_2423_2: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function c() { return 1; }\n        function p() { console.log(c()); }\n        p();\n        p();\n    }\n    expect: {\n        function p() { console.log(1); }\n        p();\n        p();\n    }\n    expect_stdout: [\n        \"1\",\n        \"1\",\n    ]\n}\n\nissue_2423_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function c() { return 1; }\n        function p() { console.log(c()); }\n        p();\n    }\n    expect: {\n        (function() { console.log(function() { return 1; }()); })();\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2423_4: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function c() { return 1; }\n        function p() { console.log(c()); }\n        p();\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2423_5: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function x() {\n            y();\n        }\n        function y() {\n            console.log(1);\n        }\n        function z() {\n            function y() {\n                console.log(2);\n            }\n            x();\n        }\n        z();\n        z();\n    }\n    expect: {\n        function z() {\n            console.log(1);\n        }\n        z();\n        z();\n    }\n    expect_stdout: [\n        \"1\",\n        \"1\",\n    ]\n}\n\nissue_2423_6: {\n    options = {\n        inline: true,\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function x() {\n            y();\n        }\n        function y() {\n            console.log(1);\n        }\n        function z() {\n            function y() {\n                console.log(2);\n            }\n            x();\n            y();\n        }\n        z();\n        z();\n    }\n    expect: {\n        function z(){\n            console.log(1);\n            console.log(2);\n        }\n        z();\n        z();\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n        \"1\",\n        \"2\",\n    ]\n}\n\nissue_2440_eval_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            return bar();\n        }\n        baz = {\n            quux: foo\n        };\n        exec = function() {\n            return eval(\"foo()\");\n        };\n    }\n    expect: {\n        function foo() {\n            return bar();\n        }\n        baz = {\n            quux: foo\n        };\n        exec = function() {\n            return eval(\"foo()\");\n        };\n    }\n}\n\nissue_2440_eval_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        baz = {\n            quux: foo\n        };\n        exec = function() {\n            return eval(\"foo()\");\n        };\n        function foo() {\n            return bar();\n        }\n    }\n    expect: {\n        baz = {\n            quux: foo\n        };\n        exec = function() {\n            return eval(\"foo()\");\n        };\n        function foo() {\n            return bar();\n        }\n    }\n}\n\nissue_2440_with_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            return bar();\n        }\n        baz = {\n            quux: foo\n        };\n        with (o) whatever();\n    }\n    expect: {\n        function foo() {\n            return bar();\n        }\n        baz = {\n            quux: foo\n        };\n        with (o) whatever();\n    }\n}\n\nissue_2440_with_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        baz = {\n            quux: foo\n        };\n        with (o) whatever();\n        function foo() {\n            return bar();\n        }\n    }\n    expect: {\n        baz = {\n            quux: foo\n        };\n        with (o) whatever();\n        function foo() {\n            return bar();\n        }\n    }\n}\n\nissue_2442: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            foo();\n        }\n    }\n    expect: {}\n}\n\nrecursive_inlining_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function foo() { bar(); }\n            function bar() { foo(); }\n            console.log(\"PASS\");\n        }();\n    }\n    expect: {\n        !function() {\n            console.log(\"PASS\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nrecursive_inlining_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function foo() { qux(); }\n            function bar() { foo(); }\n            function qux() { bar(); }\n            console.log(\"PASS\");\n        }();\n    }\n    expect: {\n        !function() {\n            console.log(\"PASS\");\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nrecursive_inlining_3: {\n    options = {\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function foo(x) { console.log(\"foo\", x); if (x) bar(x-1); }\n            function bar(x) { console.log(\"bar\", x); if (x) qux(x-1); }\n            function qux(x) { console.log(\"qux\", x); if (x) foo(x-1); }\n            qux(4);\n        }();\n    }\n    expect: {\n        !function() {\n            function qux(x) {\n                console.log(\"qux\", x);\n                if (x) (function(x) {\n                    console.log(\"foo\", x);\n                    if (x) (function(x) {\n                        console.log(\"bar\", x);\n                        if (x) qux(x - 1);\n                    })(x - 1);\n                })(x - 1);\n            }\n            qux(4);\n        }();\n    }\n    expect_stdout: [\n        \"qux 4\",\n        \"foo 3\",\n        \"bar 2\",\n        \"qux 1\",\n        \"foo 0\",\n    ]\n}\n\nrecursive_inlining_4: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function foo(x) { console.log(\"foo\", x); if (x) bar(x-1); }\n            function bar(x) { console.log(\"bar\", x); if (x) qux(x-1); }\n            function qux(x) { console.log(\"qux\", x); if (x) foo(x-1); }\n            qux(4);\n            bar(5);\n        }();\n    }\n    expect: {\n        !function() {\n            function bar(x) {\n                console.log(\"bar\", x);\n                if (x) qux(x - 1);\n            }\n            function qux(x) {\n                console.log(\"qux\", x);\n                if (x) (function(x) {\n                    console.log(\"foo\", x);\n                    if (x) bar(x - 1);\n                })(x - 1);\n            }\n            qux(4);\n            bar(5);\n        }();\n    }\n    expect_stdout: [\n        \"qux 4\",\n        \"foo 3\",\n        \"bar 2\",\n        \"qux 1\",\n        \"foo 0\",\n        \"bar 5\",\n        \"qux 4\",\n        \"foo 3\",\n        \"bar 2\",\n        \"qux 1\",\n        \"foo 0\",\n    ]\n}\n\nrecursive_inlining_5: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function() {\n            function foo(x) { console.log(\"foo\", x); if (x) bar(x-1); }\n            function bar(x) { console.log(\"bar\", x); if (x) qux(x-1); }\n            function qux(x) { console.log(\"qux\", x); if (x) foo(x-1); }\n            qux(4);\n            bar(5);\n            foo(3);\n        }();\n    }\n    expect: {\n        !function() {\n            function foo(x) {\n                console.log(\"foo\", x);\n                if (x) bar(x - 1);\n            }\n            function bar(x) {\n                console.log(\"bar\", x);\n                if (x) qux(x - 1);\n            }\n            function qux(x) {\n                console.log(\"qux\", x);\n                if (x) foo(x - 1);\n            }\n            qux(4);\n            bar(5);\n            foo(3);\n        }();\n    }\n    expect_stdout: [\n        \"qux 4\",\n        \"foo 3\",\n        \"bar 2\",\n        \"qux 1\",\n        \"foo 0\",\n        \"bar 5\",\n        \"qux 4\",\n        \"foo 3\",\n        \"bar 2\",\n        \"qux 1\",\n        \"foo 0\",\n        \"foo 3\",\n        \"bar 2\",\n        \"qux 1\",\n        \"foo 0\",\n    ]\n}\n\nissue_2450_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        function g() {\n            return f;\n        }\n        console.log(g() === g());\n    }\n    expect: {\n        function f() {}\n        function g() {\n            return f;\n        }\n        console.log(g() === g());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_2450_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function g() {\n            function f() {}\n            return f;\n        }\n        console.log(g() === g());\n    }\n    expect: {\n        function g() {\n            return function() {};\n        }\n        console.log(g() === g());\n    }\n    expect_stdout: \"false\"\n}\n\nissue_2450_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var x = (function() {\n            function test() {\n                return \"foo\";\n            }\n            return function b() {\n                return [1, test];\n            }\n        })();\n        console.log(x()[1] === x()[1]);\n    }\n    expect: {\n        var x = (function() {\n            function test() {\n                return \"foo\";\n            }\n            return function() {\n                return [1, test];\n            }\n        })();\n        console.log(x()[1] === x()[1]);\n    }\n    expect_stdout: \"true\"\n}\n\nissue_2450_4: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            console.log(a === b);\n            a = b;\n        }\n        function g() {}\n        for (var i = 3; --i >= 0;)\n            f(g);\n    }\n    expect: {\n        var a;\n        function g() {}\n        for (var i = 3; --i >= 0;)\n            (function(b) {\n                console.log(a === b);\n                a = b;\n            })(g);\n    }\n    expect_stdout: [\n        \"false\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nissue_2450_5: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f(b) {\n            console.log(a === b);\n            a = b;\n        }\n        function g() {}\n        [1, 2, 3].forEach(function() {\n            f(g);\n        });\n    }\n    expect: {\n        var a;\n        function g() {}\n        [1, 2, 3].forEach(function() {\n            (function(b) {\n                console.log(a === b);\n                a = b;\n            })(g);\n        });\n    }\n    expect_stdout: [\n        \"false\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nissue_2449: {\n    options = {\n        passes: 10,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            return a;\n        }\n        function g() {\n            return f();\n        }\n        (function() {\n            var a = \"FAIL\";\n            if (a == a) console.log(g());\n        })();\n    }\n    expect: {\n        var a = \"PASS\";\n        function g() {\n            return function() {\n                return a;\n            }();\n        }\n        (function() {\n            var a = \"FAIL\";\n            if (a == a) console.log(g());\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nperf_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        }\n        function indirect_foo(x, y, z) {\n            return foo(x, y, z);\n        }\n        var sum = 0;\n        for (var i = 0; i < 100; ++i) {\n            sum += indirect_foo(i, i + 1, 3 * i);\n        }\n        console.log(sum);\n    }\n    expect: {\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += function(x, y, z) {\n                return function(x, y, z) {\n                    return x < y ? x * y + z : x * z - y;\n                }(x, y, z);\n            }(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_2: {\n    options = {\n        reduce_funcs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function foo(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        }\n        function indirect_foo(x, y, z) {\n            return foo(x, y, z);\n        }\n        var sum = 0;\n        for (var i = 0; i < 100; ++i) {\n            sum += indirect_foo(i, i + 1, 3 * i);\n        }\n        console.log(sum);\n    }\n    expect: {\n        function foo(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        }\n        function indirect_foo(x, y, z) {\n            return foo(x, y, z);\n        }\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_3: {\n    options = {\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var foo = function(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        };\n        var indirect_foo = function(x, y, z) {\n            return foo(x, y, z);\n        };\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect: {\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += function(x, y, z) {\n                return function(x, y, z) {\n                    return x < y ? x * y + z : x * z - y;\n                }(x, y, z);\n            }(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_4: {\n    options = {\n        reduce_funcs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var foo = function(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        };\n        var indirect_foo = function(x, y, z) {\n            return foo(x, y, z);\n        };\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect: {\n        var foo = function(x, y, z) {\n            return x < y ? x * y + z : x * z - y;\n        };\n        var indirect_foo = function(x, y, z) {\n            return foo(x, y, z);\n        };\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_5: {\n    options = {\n        passes: 10,\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function indirect_foo(x, y, z) {\n            function foo(x, y, z) {\n                return x < y ? x * y + z : x * z - y;\n            }\n            return foo(x, y, z);\n        }\n        var sum = 0;\n        for (var i = 0; i < 100; ++i) {\n            sum += indirect_foo(i, i + 1, 3 * i);\n        }\n        console.log(sum);\n    }\n    expect: {\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += function(x, y, z) {\n                return function(x, y, z) {\n                    return x < y ? x * y + z : x * z - y;\n                }(x, y, z);\n            }(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_6: {\n    options = {\n        passes: 10,\n        reduce_funcs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function indirect_foo(x, y, z) {\n            function foo(x, y, z) {\n                return x < y ? x * y + z : x * z - y;\n            }\n            return foo(x, y, z);\n        }\n        var sum = 0;\n        for (var i = 0; i < 100; ++i) {\n            sum += indirect_foo(i, i + 1, 3 * i);\n        }\n        console.log(sum);\n    }\n    expect: {\n        function indirect_foo(x, y, z) {\n            return function(x, y, z) {\n                return x < y ? x * y + z : x * z - y;\n            }(x, y, z);\n        }\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_7: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var indirect_foo = function(x, y, z) {\n            var foo = function(x, y, z) {\n                return x < y ? x * y + z : x * z - y;\n            };\n            return foo(x, y, z);\n        };\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect: {\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += function(x, y, z) {\n                return function(x, y, z) {\n                    return x < y ? x * y + z : x * z - y;\n                }(x, y, z);\n            }(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nperf_8: {\n    options = {\n        reduce_funcs: false,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var indirect_foo = function(x, y, z) {\n            var foo = function(x, y, z) {\n                return x < y ? x * y + z : x * z - y;\n            };\n            return foo(x, y, z);\n        };\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect: {\n        var indirect_foo = function(x, y, z) {\n            return function(x, y, z) {\n                return x < y ? x * y + z : x * z - y;\n            }(x, y, z);\n        };\n        var sum = 0;\n        for (var i = 0; i < 100; ++i)\n            sum += indirect_foo(i, i + 1, 3 * i);\n        console.log(sum);\n    }\n    expect_stdout: \"348150\"\n}\n\nissue_2485_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var foo = function(bar) {\n            var n = function(a, b) {\n                return a + b;\n            };\n            var sumAll = function(arg) {\n                return arg.reduce(n, 0);\n            };\n            var runSumAll = function(arg) {\n                return sumAll(arg);\n            };\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect: {\n        var foo = function(bar) {\n            var n = function(a, b) {\n                return a + b;\n            };\n            var runSumAll = function(arg) {\n                return function(arg) {\n                    return arg.reduce(n, 0);\n                }(arg);\n            };\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect_stdout: \"6\"\n}\n\nissue_2485_2: {\n    options = {\n        inline: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var foo = function(bar) {\n            var n = function(a, b) {\n                return a + b;\n            };\n            var sumAll = function(arg) {\n                return arg.reduce(n, 0);\n            };\n            var runSumAll = function(arg) {\n                return sumAll(arg);\n            };\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect: {\n        var foo = function(bar) {\n            var n = function(a, b) {\n                return a + b;\n            };\n            var runSumAll = function(arg) {\n                    return arg.reduce(n, 0);\n            };\n            bar.baz = function(arg) {\n                var n = runSumAll(arg);\n                return (n.get = 1), n;\n            };\n            return bar;\n        };\n        var bar = foo({});\n        console.log(bar.baz([1, 2, 3]));\n    }\n    expect_stdout: \"6\"\n}\n\nissue_2455: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function foo() {\n            var that = this;\n            for (;;) that.bar();\n        }\n    }\n    expect: {\n        function foo() {\n            for (;;) this.bar();\n        }\n    }\n}\n\nescape_conditional: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function main() {\n            var thing = baz();\n            if (thing !== (thing = baz()))\n                console.log(\"FAIL\");\n            else\n                console.log(\"PASS\");\n        }\n        function baz(s) {\n            return s ? foo : bar;\n        }\n        function foo() {}\n        function bar() {}\n        main();\n    }\n    expect: {\n        function baz(s) {\n            return s ? foo : bar;\n        }\n        function foo() {}\n        function bar() {}\n        (function() {\n            var thing = baz();\n            if (thing !== baz())\n                console.log(\"FAIL\");\n            else\n                console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nescape_sequence: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function main() {\n            var thing = baz();\n            if (thing !== (thing = baz()))\n                console.log(\"FAIL\");\n            else\n                console.log(\"PASS\");\n        }\n        function baz() {\n            return foo, bar;\n        }\n        function foo() {}\n        function bar() {}\n        main();\n    }\n    expect: {\n        function baz() {\n            return function() {}, bar;\n        }\n        function bar() {}\n        (function() {\n            var thing = baz();\n            if (thing !== baz())\n                console.log(\"FAIL\");\n            else\n                console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nescape_throw: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function main() {\n            var thing = baz();\n            if (thing !== (thing = baz()))\n                console.log(\"FAIL\");\n            else\n                console.log(\"PASS\");\n        }\n        function baz() {\n            try {\n                throw foo;\n            } catch (bar) {\n                return bar;\n            }\n        }\n        function foo() {}\n        main();\n    }\n    expect: {\n        function baz() {\n            try {\n                throw foo;\n            } catch (bar) {\n                return bar;\n            }\n        }\n        function foo() {}\n        (function() {\n            var thing = baz();\n            if (thing !== baz())\n                console.log(\"FAIL\");\n            else\n                console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nescape_local_conditional: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function main() {\n            var thing = baz();\n            if (thing !== (thing = baz()))\n                console.log(\"PASS\");\n            else\n                console.log(\"FAIL\");\n        }\n        function baz(s) {\n            function foo() {}\n            function bar() {}\n            return s ? foo : bar;\n        }\n        main();\n    }\n    expect: {\n        function baz(s) {\n            return s ? function() {} : function() {};\n        }\n        (function() {\n            var thing = baz();\n            if (thing !== baz())\n                console.log(\"PASS\");\n            else\n                console.log(\"FAIL\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nescape_local_sequence: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function main() {\n            var thing = baz();\n            if (thing !== (thing = baz()))\n                console.log(\"PASS\");\n            else\n                console.log(\"FAIL\");\n        }\n        function baz() {\n            function foo() {}\n            function bar() {}\n            return foo, bar;\n        }\n        main();\n    }\n    expect: {\n        function baz() {\n            return function() {}, function() {};\n        }\n        (function() {\n            var thing = baz();\n            if (thing !== baz())\n                console.log(\"PASS\");\n            else\n                console.log(\"FAIL\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nescape_local_throw: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function main() {\n            var thing = baz();\n            if (thing !== (thing = baz()))\n                console.log(\"PASS\");\n            else\n                console.log(\"FAIL\");\n        }\n        function baz() {\n            function foo() {}\n            try {\n                throw foo;\n            } catch (bar) {\n                return bar;\n            }\n        }\n        main();\n    }\n    expect: {\n        function baz() {\n            try {\n                throw function() {};\n            } catch (bar) {\n                return bar;\n            }\n        }\n        (function() {\n            var thing = baz();\n            if (thing !== baz())\n                console.log(\"PASS\");\n            else\n                console.log(\"FAIL\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\ninverted_var: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = 1;\n            return a;\n        }(), function() {\n            var b;\n            b = 2;\n            return b;\n        }(), function() {\n            c = 3;\n            return c;\n            var c;\n        }(), function(c) {\n            c = 4;\n            return c;\n        }(), function(c) {\n            c = 5;\n            return c;\n            var c;\n        }(), function c() {\n            c = 6;\n            return c;\n        }(), function c() {\n            c = 7;\n            return c;\n            var c;\n        }(), function() {\n            c = 8;\n            return c;\n            var c = \"foo\";\n        }());\n    }\n    expect: {\n        console.log(1, 2, 3, 4, 5, function c() {\n            c = 6;\n            return c;\n        }(), 7, 8);\n    }\n    expect_stdout: true\n}\n\ndefun_single_use_loop: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        for (var x, i = 2; --i >= 0;) {\n            var y = x;\n            x = f;\n            console.log(x === y);\n        }\n        function f() {};\n    }\n    expect: {\n        for (var x, i = 2; --i >= 0;) {\n            var y = x;\n            x = f;\n            console.log(x === y);\n        }\n        function f() {};\n    }\n    expect_stdout: [\n        \"false\",\n        \"true\",\n    ]\n}\n\ndo_while: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            do {\n                (function() {\n                    a && (c = \"PASS\");\n                })();\n            } while (a = 0);\n        }\n        var c = \"FAIL\";\n        f(1);\n        console.log(c);\n    }\n    expect: {\n        function f(a) {\n            do {\n                (function() {\n                    a && (c = \"PASS\");\n                })();\n            } while (a = 0);\n        }\n        var c = \"FAIL\";\n        f(1);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2598: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        function g(a) {\n            return a || f;\n        }\n        console.log(g(false) === g(null));\n    }\n    expect: {\n        function f() {}\n        function g(a) {\n            return a || f;\n        }\n        console.log(g(false) === g(null));\n    }\n    expect_stdout: \"true\"\n}\n\nvar_if: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            if (x()) {\n                var a;\n                if (!g) a = true;\n                if (a) g();\n            }\n        }\n    }\n    expect: {\n        function f() {\n            if (x()) {\n                var a;\n                if (!g) a = true;\n                if (a) g();\n            }\n        }\n    }\n}\n\ndefun_assign: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(typeof a);\n        a = 42;\n        console.log(typeof a);\n        function a() {}\n        console.log(typeof a);\n    }\n    expect: {\n        console.log(typeof a);\n        a = 42;\n        console.log(typeof a);\n        function a() {}\n        console.log(typeof a);\n    }\n    expect_stdout: [\n        \"function\",\n        \"number\",\n        \"number\",\n    ]\n}\n\ndefun_var_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        var a = 42, b;\n        function a() {}\n        function b() {}\n        console.log(typeof a, typeof b);\n    }\n    expect: {\n        console.log(\"number\", \"function\");\n    }\n    expect_stdout: \"number function\"\n}\n\ndefun_var_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        function a() {}\n        function b() {}\n        var a = 42, b;\n        console.log(typeof a, typeof b);\n    }\n    expect: {\n        console.log(\"number\", \"function\");\n    }\n    expect_stdout: \"number function\"\n}\n\ndefun_var_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        function a() {}\n        function b() {}\n        console.log(typeof a, typeof b);\n        var a = 42, b;\n    }\n    expect: {\n        console.log(\"function\", \"function\");\n    }\n    expect_stdout: \"function function\"\n}\n\ndefun_catch_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function a() {}\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\ndefun_catch_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            function a() {}\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\ndefun_catch_3: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw 42;\n            function a() {}\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\ndefun_catch_4: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (a) {\n            function a() {}\n            console.log(a);\n        }\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (a) {\n            function a() {}\n            console.log(a);\n        }\n    }\n    expect_stdout: true\n}\n\ndefun_catch_5: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n            function a() {}\n        }\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n            function a() {}\n        }\n    }\n    expect_stdout: true\n}\n\ndefun_catch_6: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n        function a() {}\n    }\n    expect: {\n        try {\n            throw 42;\n        } catch (a) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"42\"\n}\n\nduplicate_lambda_defun_name_1: {\n    options = {\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function f(a) {\n            function f() {}\n            return f.length;\n        }());\n    }\n    expect: {\n        console.log(function f(a) {\n            function f() {}\n            return f.length;\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nduplicate_lambda_defun_name_2: {\n    options = {\n        passes: 2,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f(a) {\n            function f() {}\n            return f.length;\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            return function() {}.length;\n        }());\n    }\n    expect_stdout: \"0\"\n}\n\nissue_2774: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log({\n            get a() {\n                var b;\n                (b = true) && b.c;\n                b = void 0;\n            }\n        }.a);\n    }\n    expect: {\n        console.log({\n            get a() {\n                var b;\n                (b = true) && b.c;\n                void 0;\n            }\n        }.a);\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_2799_1: {\n    options = {\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return f;\n            function f(n) {\n                function g(i) {\n                    return i && i + g(i - 1);\n                }\n                function h(j) {\n                    return g(j);\n                }\n                return h(n);\n            }\n        }()(5));\n    }\n    expect: {\n        console.log(function() {\n            return function(n) {\n                return function(j) {\n                    return function g(i) {\n                        return i && i + g(i - 1);\n                    }(j);\n                }(n);\n            }\n        }()(5));\n    }\n    expect_stdout: \"15\"\n}\n\nissue_2799_2: {\n    options = {\n        reduce_vars: true,\n        unsafe_proto: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function foo() {\n                Function.prototype.call.apply(console.log, [ null, \"PASS\" ]);\n            }\n            foo();\n        })();\n    }\n    expect: {\n        (function() {\n            (function() {\n                (function() {}).call.apply(console.log, [ null, \"PASS\" ]);\n            })();\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2836: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            return \"FAIL\";\n        }\n        console.log(f());\n        function f() {\n            return \"PASS\";\n        }\n    }\n    expect: {\n        console.log(function() {\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nlvalues_def_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        var a = b++, b = NaN;\n        console.log(a, b);\n    }\n    expect: {\n        var b = 1;\n        var a = +b, b = NaN;\n        console.log(a, b);\n    }\n    expect_stdout: \"1 NaN\"\n}\n\nlvalues_def_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var b = 1;\n        var a = b += 1, b = NaN;\n        console.log(a, b);\n    }\n    expect: {\n        var b = 1;\n        var a = b += 1, b = NaN;\n        console.log(a, b);\n    }\n    expect_stdout: \"2 NaN\"\n}\n\nchained_assignments: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            var a = [0x5e, 0xad, 0xbe, 0xef];\n            var b = 0;\n            b |= a[0];\n            b <<= 8;\n            b |= a[1];\n            b <<= 8;\n            b |= a[2];\n            b <<= 8;\n            b |= a[3];\n            return b;\n        }\n        console.log(f().toString(16));\n    }\n    expect: {\n        console.log(\"5eadbeef\");\n    }\n    expect_stdout: \"5eadbeef\"\n}\n\nissue_2860_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a ^= 1;\n            a ^= 2;\n        }());\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2860_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a ^= 1;\n            a ^= 2;\n        }());\n    }\n    expect: {\n        console.log(1);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2869: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function f(a) {\n            var a;\n            if (!f) a = 0;\n            if (a) c = \"PASS\";\n        })(1);\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function f(a) {\n            var a;\n            if (!f) a = 0;\n            if (a) c = \"PASS\";\n        })(1);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2919: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var arr = [ function() {} ];\n        console.log(typeof arr[0]);\n    }\n    expect: {\n        console.log(\"function\");\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2992: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = \"PASS\";\n        (function f(b) {\n            switch (0) {\n            case 0:\n            case b = 1:\n                b && (c = \"FAIL\");\n            }\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = \"PASS\";\n        (function f(b) {\n            switch (0) {\n            case 0:\n            case b = 1:\n                b && (c = \"FAIL\");\n            }\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3042_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        var a = [ 1, 2 ].map(function() {\n            return new f();\n        });\n        console.log(a[0].constructor === a[1].constructor);\n    }\n    expect: {\n        function f() {}\n        var a = [ 1, 2 ].map(function() {\n            return new f();\n        });\n        console.log(a[0].constructor === a[1].constructor);\n    }\n    expect_stdout: \"true\"\n}\n\nissue_3042_2: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function Foo() {\n            this.isFoo = function(o) {\n                return o instanceof Foo;\n            };\n        }\n        function FooCollection() {\n            this.foos = [1, 1].map(function() {\n                return new Foo();\n            });\n        }\n        var fooCollection = new FooCollection();\n        console.log(fooCollection.foos[0].isFoo(fooCollection.foos[0]));\n        console.log(fooCollection.foos[0].isFoo(fooCollection.foos[1]));\n        console.log(fooCollection.foos[1].isFoo(fooCollection.foos[0]));\n        console.log(fooCollection.foos[1].isFoo(fooCollection.foos[1]));\n    }\n    expect: {\n        function Foo() {\n            this.isFoo = function(o) {\n                return o instanceof Foo;\n            };\n        }\n        var fooCollection = new function() {\n            this.foos = [1, 1].map(function() {\n                return new Foo();\n            });\n        }();\n        console.log(fooCollection.foos[0].isFoo(fooCollection.foos[0]));\n        console.log(fooCollection.foos[0].isFoo(fooCollection.foos[1]));\n        console.log(fooCollection.foos[1].isFoo(fooCollection.foos[0]));\n        console.log(fooCollection.foos[1].isFoo(fooCollection.foos[1]));\n    }\n    expect_stdout: [\n        \"true\",\n        \"true\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nissue_3068_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function() {\n            do {\n                continue;\n                var b = \"defined\";\n            } while (b && b.c);\n        })();\n    }\n    expect: {\n        (function() {\n            do {\n                continue;\n                var b = \"defined\";\n            } while (b && b.c);\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_3068_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function() {\n            do {\n                try {\n                    while (\"\" == typeof a);\n                } finally {\n                    continue;\n                }\n                var b = \"defined\";\n            } while (b && b.c);\n        })();\n    }\n    expect: {\n        (function() {\n            do {\n                try {\n                    while (\"\" == typeof a);\n                } finally {\n                    continue;\n                }\n                var b = \"defined\";\n            } while (b && b.c);\n        })();\n    }\n    expect_stdout: true\n}\n\nissue_3110_1: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        passes: 3,\n        properties: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function foo() {\n                return isDev ? \"foo\" : \"bar\";\n            }\n            var isDev = true;\n            var obj = {\n                foo: foo\n            };\n            console.log(foo());\n            console.log(obj.foo());\n        })();\n    }\n    expect: {\n        console.log(\"foo\"),\n        console.log(\"foo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_3110_2: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        passes: 4,\n        properties: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function foo() {\n                return isDev ? \"foo\" : \"bar\";\n            }\n            var isDev = true;\n            console.log(foo());\n            var obj = {\n                foo: foo\n            };\n            console.log(obj.foo());\n        })();\n    }\n    expect: {\n        console.log(\"foo\"),\n        console.log(\"foo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"foo\",\n    ]\n}\n\nissue_3110_3: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        properties: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function foo() {\n                return isDev ? \"foo\" : \"bar\";\n            }\n            console.log(foo());\n            var isDev = true;\n            var obj = {\n                foo: foo\n            };\n            console.log(obj.foo());\n        })();\n    }\n    expect: {\n        (function() {\n            function foo() {\n                return isDev ? \"foo\" : \"bar\";\n            }\n            console.log(foo());\n            var isDev = true;\n            var obj = {\n                foo: foo\n            };\n            console.log(obj.foo());\n        })();\n    }\n    expect_stdout: [\n        \"bar\",\n        \"foo\",\n    ]\n}\n\nissue_3113_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            function f() {\n                while (g());\n            }\n            var a = f();\n            function g() {\n                a && a[c++];\n            }\n            g(a = 1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function() {\n            function f() {\n                while (g());\n            }\n            var a = f();\n            function g() {\n                a && a[c++];\n            }\n            g(a = 1);\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3113_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            function f() {\n                while (g());\n            }\n            var a = f();\n            function g() {\n                a && a[c++];\n            }\n            a = 1;\n            g();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function() {\n            function f() {\n                while (g());\n            }\n            var a = f();\n            function g() {\n                a && a[c++];\n            }\n            a = 1;\n            g();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3113_3: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var c = 0;\n        (function() {\n            function f() {\n                while (g());\n            }\n            var a;\n            function g() {\n                a && a[c++];\n            }\n            g(a = 1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        c++;\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3113_4: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        function f() {\n            b += a;\n        }\n        f(f(), ++a);\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 0;\n        function f() {\n            b += a;\n        }\n        f(f(), ++a);\n        console.log(a, b);\n    }\n    expect_stdout: \"1 1\"\n}\n\nissue_3113_5: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {\n            console.log(a);\n        }\n        function g() {\n            f();\n        }\n        while (g());\n        var a = 1;\n        f();\n    }\n    expect: {\n        function f() {\n            console.log(a);\n        }\n        function g() {\n            f();\n        }\n        while (g());\n        var a = 1;\n        f();\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"1\",\n    ]\n}\n\nconditional_nested_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var a = 1, b = 0;\n        (function f(c) {\n            function g() {\n                c && (c.a = 0);\n                c && (c.a = 0);\n                c && (c[b++] *= 0);\n            }\n            g(a-- && f(g(c = 42)));\n        })();\n        console.log(b);\n    }\n    expect: {\n        var a = 1, b = 0;\n        (function f(c) {\n            function g() {\n                c && (c.a = 0);\n                c && (c.a = 0);\n                c && (c[b++] *= 0);\n            }\n            g(a-- && f(g(c = 42)));\n        })();\n        console.log(b);\n    }\n    expect_stdout: \"2\"\n}\n\nconditional_nested_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var c = 0;\n        (function(a) {\n            function f() {\n                a && c++;\n            }\n            f(!c && f(), a = 1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        (function(a) {\n            function f() {\n                a && c++;\n            }\n            f(!c && f(), a = 1);\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nconditional_nested_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var n = 2, c = 0;\n        (function f(a) {\n            0 < n-- && g(a = 1);\n            function g() {\n                a && c++;\n            }\n            g();\n            0 < n-- && f();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var n = 2, c = 0;\n        (function f(a) {\n            0 < n-- && g(a = 1);\n            function g() {\n                a && c++;\n            }\n            g();\n            0 < n-- && f();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_2436: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var c;\n        console.log(((c = {\n            a: 1,\n            b: 2\n        }).a = 3, {\n            x: c.a,\n            y: c.b\n        }));\n    }\n    expect: {\n        var c;\n        console.log(((c = {\n            a: 1,\n            b: 2\n        }).a = 3, {\n            x: c.a,\n            y: c.b\n        }));\n    }\n    expect_stdout: true\n}\n\nissue_2916: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        (function(b) {\n            (function(d) {\n                d[0] = 1;\n            })(b);\n            +b && (c = \"PASS\");\n        })([]);\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        (function(b) {\n            b[0] = 1;\n            +b && (c = \"PASS\");\n        })([]);\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3125: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o;\n        console.log((function() {\n            this.p++;\n        }.call(o = {\n            p: 6\n        }), o.p));\n    }\n    expect: {\n        var o;\n        console.log((function() {\n            this.p++;\n        }.call(o = {\n            p: 6\n        }), o.p));\n    }\n    expect_stdout: \"7\"\n}\n\nissue_3140_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                this();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                this();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3140_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                var self = this;\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                self();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                this();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3140_3: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                var self = this;\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                (function() {\n                    return self;\n                })()();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                var self = this;\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                (function() {\n                    return self;\n                })()();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3140_4: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                var o = {\n                    p: this\n                };\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                o.p();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect: {\n        (function() {\n            var a;\n            function f() {\n            }\n            f.g = function g() {\n                var o = {\n                    p: this\n                };\n                function h() {\n                    console.log(a ? \"PASS\" : \"FAIL\");\n                }\n                a = true;\n                o.p();\n                a = false;\n                h.g = g;\n                return h;\n            };\n            return f;\n        })().g().g();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3140_5: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        var n = 1, c = 0;\n        (function(a) {\n            var b = function() {\n                this;\n                n-- && h();\n            }();\n            function h() {\n                b && c++;\n            }\n            h(b = 1);\n        })();\n        console.log(c);\n    }\n    expect: {\n        var n = 1, c = 0;\n        (function(a) {\n            var b = function() {\n                this;\n                n-- && h();\n            }();\n            function h() {\n                b && c++;\n            }\n            h(b = 1);\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_3240_1: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            f(1);\n            function f(a) {\n                console.log(a);\n                var g = function() {\n                    f(a - 1);\n                };\n                if (a) g();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            (function f(a) {\n                console.log(a);\n                var g = function() {\n                    f(a - 1);\n                };\n                if (a) g();\n            })(1);\n        })();\n    }\n    expect_stdout: [\n        \"1\",\n        \"0\",\n    ]\n}\n\nissue_3240_2: {\n    options = {\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            f(1);\n            function f(a) {\n                console.log(a);\n                var g = function() {\n                    f(a - 1);\n                };\n                if (a) g();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            (function f(a) {\n                console.log(a);\n                if (a) (function() {\n                    f(a - 1);\n                })();\n            })(1);\n        })();\n    }\n    expect_stdout: [\n        \"1\",\n        \"0\",\n    ]\n}\n\nissue_3240_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            f();\n            function f(b) {\n                if (!f.a) f.a = 0;\n                console.log(f.a.toString());\n                var g = function() {\n                    (b ? function() {} : function() {\n                        f.a++;\n                        f(1);\n                    })();\n                };\n                g();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            f();\n            function f(b) {\n                if (!f.a) f.a = 0;\n                console.log(f.a.toString());\n                (function() {\n                    (b ? function() {} : function() {\n                        f.a++;\n                        f(1);\n                    })();\n                })();\n            }\n        })();\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n    ]\n}\n\nissue_3240_4: {\n    options = {\n        passes: 2,\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            f();\n            function f(b) {\n                if (!f.a) f.a = 0;\n                console.log(f.a.toString());\n                var g = function() {\n                    (b ? function() {} : function() {\n                        f.a++;\n                        f(1);\n                    })();\n                };\n                g();\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            f();\n            function f(b) {\n                if (!f.a) f.a = 0;\n                console.log(f.a.toString());\n                (function() {\n                    (b ? function() {} : function() {\n                        f.a++;\n                        f(1);\n                    })();\n                })();\n            }\n        })();\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n    ]\n}\n\nissues_3267_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        negate_iife: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(x) {\n            x();\n        })(function() {\n            (function(i) {\n                if (i)\n                    return console.log(\"PASS\");\n                throw \"FAIL\";\n            })(Object());\n        });\n    }\n    expect: {\n        !function(x) {\n            if (Object())\n                return console.log(\"PASS\");\n            throw \"FAIL\";\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissues_3267_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        negate_iife: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(x) {\n            x();\n        })(function() {\n            (function(i) {\n                if (i)\n                    return console.log(\"PASS\");\n                throw \"FAIL\";\n            })(Object());\n        });\n    }\n    expect: {\n        !function() {\n            if (Object())\n                return console.log(\"PASS\");\n            throw \"FAIL\";\n        }();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissues_3267_3: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        (function(x) {\n            x();\n        })(function() {\n            (function(i) {\n                if (i)\n                    return console.log(\"PASS\");\n                throw \"FAIL\";\n            })(Object());\n        });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3297: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            function f() {\n                var a;\n                var b = function a() {\n                    console.log(a === b) && f();\n                };\n                b();\n            }\n            f();\n        })();\n    }\n    expect: {\n        (function() {\n            (function f() {\n                var b = function a() {\n                    console.log(a === b) && f();\n                };\n                b();\n            })();\n        })();\n    }\n    expect_stdout: \"true\"\n}\n\ndrop_side_effect_free: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 123;\n        \"\" + (a && (a.b = 0) || a);\n        console.log(a);\n    }\n    expect: {\n        var a = 123;\n        a.b = 0;\n        console.log(a);\n    }\n    expect_stdout: \"123\"\n}\n\nissue_3377: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function f() {\n            return f[0], (f = 42);\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            return f[0], (f = 42);\n        }());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3509: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function a() {\n            console.log(\"PASS\");\n        }\n        try {\n        } catch (a) {\n            var a;\n        }\n        a();\n    }\n    expect: {\n        try {\n        } catch (a) {\n            var a;\n        }\n        (function() {\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3622: {\n    options = {\n        evaluate: true,\n        inline: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var c = \"FAIL\";\n        !function(b, a) {\n            a && (c = \"PASS\");\n        }(42, this);\n        console.log(c);\n    }\n    expect: {\n        var c = \"FAIL\";\n        !void (this && (c = \"PASS\")),\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3631_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var c = 0;\n        L: do {\n            for (;;) continue L;\n            var b = 1;\n        } while (b && c++);\n        console.log(c);\n    }\n    expect: {\n        var c = 0;\n        L: do {\n            for (;;) continue L;\n            var b = 1;\n        } while (b && c++);\n        console.log(c);\n    }\n    expect_stdout: \"0\"\n}\n\nissue_3631_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        L: for (var a = 1; a--; console.log(b)) {\n            for (;;) continue L;\n            var b = \"FAIL\";\n        }\n    }\n    expect: {\n        L: for (var a = 1; a--; console.log(b)) {\n            for (;;) continue L;\n            var b = \"FAIL\";\n        }\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3666: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            var a = \"FAIL\";\n        } finally {\n            for (;!a;)\n                var c = a++;\n            var a = \"PASS\", b = c = \"PASS\";\n        }\n        console.log(a, b);\n    }\n    expect: {\n        try {\n            var a = \"FAIL\";\n        } finally {\n            for (;!a;)\n                a++;\n            a = \"PASS\";\n        }\n        console.log(a, \"PASS\");\n    }\n    expect_stdout: \"PASS PASS\"\n}\n\nissue_3774: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        var f = function() {\n            function g() {\n                if (!g.p) {\n                    g.p = 1;\n                    console.log(\"PASS\");\n                }\n            }\n            return function() {\n                g();\n            };\n        }();\n        f();\n        f();\n    }\n    expect: {\n        var f = function() {\n            function g() {\n                if (!g.p) {\n                    g.p = 1;\n                    console.log(\"PASS\");\n                }\n            }\n            return function() {\n                g();\n            };\n        }();\n        f();\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nflatten_iife: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        while (!console);\n        a++;\n        (function() {\n            while (!console);\n            a = \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a;\n        while (!console);\n        0;\n        (function() {\n            while (!console);\n            a = \"PASS\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3844: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(function() {\n            if (!console) switch (A = 0) {\n              case console.log(\"FAIL\"):\n                return;\n            }\n            return typeof A;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            if (!console) switch (A = 0) {\n              case console.log(\"FAIL\"):\n                return;\n            }\n            return typeof A;\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3866: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            {\n                return \"PASS\";\n                var a = 0;\n            }\n            return --a;\n        }());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3880: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            while (a.var ^= 1);\n            console.log(\"PASS\");\n        })(function() {});\n    }\n    expect: {\n        (function(a) {\n            while (a.var ^= 1);\n            console.log(\"PASS\");\n        })(function() {});\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3894: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function log(msg) {\n            console.log(msg ? \"FAIL\" : \"PASS\");\n        }\n        var a;\n        (function(b) {\n            a = 0,\n            log(b);\n        })(-0);\n    }\n    expect: {\n        function log(msg) {\n            console.log(msg ? \"FAIL\" : \"PASS\");\n        }\n        var a;\n        void log(-(a = 0));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3922: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var b;\n            b && b[c];\n            a |= this;\n            console.log(\"PASS\");\n            var c = a.undefined;\n        })();\n    }\n    expect: {\n        (function() {\n            0;\n            console.log(\"PASS\");\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3949_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        (function f(a) {\n            var a = void (a = 0, g);\n            function g() {\n                console.log(typeof a);\n            }\n            g();\n        })();\n    }\n    expect: {\n        (function f(a) {\n            var a = void (a = 0, g);\n            function g() {\n                console.log(typeof a);\n            }\n            g();\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3949_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            var a = void (a = 0, g);\n            function g() {\n                console.log(typeof a);\n            }\n            g();\n        })();\n    }\n    expect: {\n        (function(a) {\n            a = void (a = 0, g);\n            function g() {\n                console.log(typeof a);\n            }\n            g();\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_3949_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {}\n        for (var a, i = 3; 0 <= --i; ) {\n            a = f;\n            console.log(a === b);\n            var b = a;\n        }\n    }\n    expect: {\n        function f() {}\n        for (var a, i = 3; 0 <= --i; ) {\n            a = f;\n            console.log(a === b);\n            var b = a;\n        }\n    }\n    expect_stdout: [\n        \"false\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nissue_3949_4: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {}\n        for (var a, i = 3; 0 <= --i; ) {\n            a = f;\n            console.log(a === b);\n            var b = a;\n        }\n    }\n    expect: {\n        function f() {}\n        for (var a, i = 3; 0 <= --i; ) {\n            a = f;\n            console.log(a === b);\n            var b = a;\n        }\n    }\n    expect_stdout: [\n        \"false\",\n        \"true\",\n        \"true\",\n    ]\n}\n\nlocal_assignment_lambda: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        function f() {\n            a = \"PASS\";\n            console.log(a);\n        }\n        f();\n        f();\n    }\n    expect: {\n        function f() {\n            console.log(\"PASS\");\n        }\n        f(),\n        f();\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nlocal_assignment_loop: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        do {\n            a = \"PASS\";\n            console.log(a);\n        } while (!console);\n    }\n    expect: {\n        do {\n            console.log(\"PASS\");\n        } while (!console);\n    }\n    expect_stdout: \"PASS\"\n}\n\nlocal_assignment_modified: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a;\n        (a = a || {}).p = 42;\n        console.log(a.p);\n    }\n    expect: {\n        var a;\n        (a = {}).p = 42;\n        console.log(a.p);\n    }\n    expect_stdout: \"42\"\n}\n\nlocal_declaration: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a;\n        a || console.log(a = \"PASS\");\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nlocal_definition_modified: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = a || {};\n        a.p = 42;\n        console.log(a.p);\n    }\n    expect: {\n        var a = {};\n        a.p = 42;\n        console.log(a.p);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_3957_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        function f(a) {\n            while (a += console.log(a = 0))\n                a = 0;\n        }\n        f(\"FAIL\");\n    }\n    expect: {\n        function f(a) {\n            while (a += console.log(a = 0))\n                a = 0;\n        }\n        f(\"FAIL\");\n    }\n    expect_stdout: [\n        \"0\",\n        \"0\",\n    ]\n}\n\nissue_3957_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            while (a += console.log(a = 0))\n                a = 0;\n        }\n        f(\"FAIL\");\n    }\n    expect: {\n        function f(a) {\n            while (a += console.log(a = 0))\n                a = 0;\n        }\n        f(\"FAIL\");\n    }\n    expect_stdout: [\n        \"0\",\n        \"0\",\n    ]\n}\n\nissue_3958: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        (function(b) {\n            (function(c) {\n                console.log(c[0] = 1);\n            })(a = b);\n            --a;\n        })([]);\n        console.log(a);\n    }\n    expect: {\n        var a;\n        (function(b) {\n            (function(c) {\n                console.log(c[0] = 1);\n            })(a = []);\n            --a;\n        })();\n        console.log(a);\n    }\n    expect_stdout: [\n        \"1\",\n        \"0\",\n    ]\n}\n\nissue_3974: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        try {\n            var a = 0 in 0;\n            0 && a;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            var a = 0 in 0;\n            0 && a;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4030: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        {\n            delete (a = \"PASS\");\n            A = \"PASS\";\n        }\n        console.log(A);\n    }\n    expect: {\n        A = \"PASS\";\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n}\n\nglobal_assign: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        this.A = \"PASS\";\n        console.log(A);\n    }\n    expect: {\n        A = \"FAIL\";\n        this.A = \"PASS\";\n        console.log(A);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4188_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            try {\n                while (A)\n                    var a = function() {}, b = a;\n            } catch (a) {\n                console.log(function() {\n                    return typeof a;\n                }(), typeof b);\n            }\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                while (A)\n                    var a = function() {}, b = a;\n            } catch (a) {\n                console.log(function() {\n                    return typeof a;\n                }(), typeof b);\n            }\n        })();\n    }\n    expect_stdout: \"object undefined\"\n}\n\nissue_4188_2: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            try {\n                throw 42;\n            } catch (a) {\n                console.log(function() {\n                    return typeof a;\n                }(), typeof b);\n            }\n            while (!console)\n                var a = function() {}, b = a;\n        })();\n    }\n    expect: {\n        (function() {\n            try {\n                throw 42;\n            } catch (a) {\n                console.log(function() {\n                    return typeof a;\n                }(), typeof b);\n            }\n            while (!console)\n                var a = function() {}, b = a;\n        })();\n    }\n    expect_stdout: \"number undefined\"\n}\n\nissue_4568: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        loops: true,\n        passes: 2,\n        reduce_vars: true,\n        sequences: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            a && console.log(\"FAIL\");\n            if (1)\n                do {\n                    if (!console.log(\"PASS\")) break;\n                } while (1);\n        })(!(0 !== delete NaN));\n    }\n    expect: {\n        (function(a) {\n            for (a && console.log(\"FAIL\"), 1; console.log(\"PASS\"); ) 1;\n        })(!(0 !== delete NaN));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4937: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            while (console.log(\"PASS\"));\n        }\n        do {\n            function g() {\n                f();\n            }\n        } while (!g);\n        f();\n    }\n    expect: {\n        function f() {\n            while (console.log(\"PASS\"));\n        }\n        do {\n            function g() {\n                f();\n            }\n        } while (!g);\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4943_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a, b = 1;\n        (function f() {\n            a = \"foo\";\n            b-- && f();\n            console.log(a);\n            a = \"bar\";\n        })();\n    }\n    expect: {\n        var a, b = 1;\n        (function f() {\n            a = \"foo\";\n            b-- && f();\n            console.log(a);\n            a = \"bar\";\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_4943_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = 1;\n        (function f() {\n            a = \"foo\";\n            b-- && f();\n            console.log(a);\n            a = \"bar\";\n        })();\n    }\n    expect: {\n        var a, b = 1;\n        (function f() {\n            a = \"foo\";\n            b-- && f();\n            console.log(a);\n            a = \"bar\";\n        })();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n}\n\nissue_4949: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            a = 0;\n            console.log(a++, arguments[0]);\n        })(0);\n    }\n    expect: {\n        (function(a) {\n            a = 0;\n            console.log(a++, arguments[0]);\n        })(0);\n    }\n    expect_stdout: \"0 1\"\n}\n\nissue_5048: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = function() {\n                return a + 42;\n            };\n        }());\n    }\n    expect: {\n        console.log(function() {}());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5050: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {\n            console.log(a);\n        }\n        this;\n        var a = 1;\n        f(console.log(2), f(), a = 3);\n    }\n    expect: {\n        function f() {\n            console.log(a);\n        }\n        this;\n        var a = 1;\n        f(console.log(2), f(), a = 3);\n    }\n    expect_stdout: [\n        \"2\",\n        \"1\",\n        \"3\",\n    ]\n}\n\nissue_5055_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            console.log(a || \"FAIL\");\n        }\n        f(0 && (a = 0)(f(this)));\n    }\n    expect: {\n        var a = \"PASS\";\n        function f() {\n            console.log(a || \"FAIL\");\n        }\n        f(0);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5055_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            console.log(a || \"FAIL\");\n        }\n        f(0 && (a = 0)(f(this)));\n    }\n    expect: {\n        var a = \"PASS\";\n        function f() {\n            console.log(a || \"FAIL\");\n        }\n        f(0 && (a = 0)(f()));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5324: {\n    options = {\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = 0;\n        do {\n            var a, b = A;\n            for (a in b)\n                var c = b;\n        } while (function() {\n            var d;\n            console.log(d *= A);\n        }());\n    }\n    expect: {\n        A = 0;\n        do {\n            var a, b = A;\n            for (a in b);\n        } while (b = void 0, void console.log(b *= A));\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5434: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            for (var i = 0; i < 2; i++) {\n                var b = \"FAIL\";\n                f && f();\n                a = b;\n                var f = function() {\n                    b = \"PASS\";\n                };\n            }\n            return a;\n        }());\n    }\n    expect: {\n        console.log(function(a) {\n            for (var i = 0; i < 2; i++) {\n                var b = \"FAIL\";\n                f && f();\n                a = b;\n                var f = function() {\n                    b = \"PASS\";\n                };\n            }\n            return a;\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5623: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        function f() {\n            var b = a;\n            a = b;\n        }\n        f && f((a++ && a).toString());\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        function f() {\n            var b;\n            a = a;\n        }\n        f((a++ && a).toString());\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_5716_1: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var b = [ c, c ], c = function() {\n                return b++ + (a = b);\n            }();\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        c = [ c, c ],\n        void (c = ++c);\n        var c;\n        console.log(c);\n    }\n    expect_stdout: \"NaN\"\n}\n\nissue_5716_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var b = [ c, c ], c = function() {\n                return (b += 4) + (a = b += 2);\n            }();\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        void (c = c = (c = [ c, c ]) + 4 + 2);\n        var c;\n        console.log(c);\n    }\n    expect_stdout: \",42\"\n}\n\nissue_5716_3: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var b = [ c, c ], c = function() {\n                return (b = b + 4) + (a = b += 2);\n            }();\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        void (c = c = (c = [ c, c ]) + 4 + 2);\n        var c;\n        console.log(c);\n    }\n    expect_stdout: \",42\"\n}\n\nissue_5716_4: {\n    options = {\n        assignments: true,\n        collapse_vars: true,\n        inline: true,\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        function f() {\n            var b = [ c, c ], c = function() {\n                return (b = true | b) + (a = b *= 42);\n            }();\n        }\n        f();\n        console.log(a);\n    }\n    expect: {\n        void (c = c = ((c = [ c, c ]) | true) * 42);\n        var c;\n        console.log(c);\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5716_5: {\n    options = {\n        assignments: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function() {\n            return 0 || (a = 42 | a);\n            var a = function() {\n                return a;\n            };\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return 0 || (a |= 42);\n            var a = function() {\n                return a;\n            };\n        }());\n    }\n    expect_stdout: \"42\"\n}\n\nissue_5730_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        L: {\n            var f = function() {\n                console.log(a);\n            };\n        }\n        f();\n        a++;\n    }\n    expect: {\n        var a = \"PASS\";\n        var f = function() {\n            console.log(a);\n        };\n        f();\n        a++;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5730_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            var f = function() {\n                console.log(a);\n            };\n        } finally {}\n        f();\n        a++;\n    }\n    expect: {\n        var a = \"PASS\";\n        try {\n            var f = function() {\n                console.log(a);\n            };\n        } finally {}\n        f();\n        a++;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5730_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f, a = \"PASS\";\n        L: {\n            f = function() {\n                console.log(a);\n            };\n        }\n        f();\n        a++;\n    }\n    expect: {\n        var f, a = \"PASS\";\n        f = function() {\n            console.log(a);\n        };\n        f();\n        a++;\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5777_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            (function(a) {\n                function g() {\n                    h();\n                }\n                g();\n                a = function() {};\n                function h() {\n                    console.log(a);\n                }\n            })(\"PASS\");\n        }\n        f();\n    }\n    expect: {\n        function f() {\n            (function(a) {\n                (function() {\n                    h();\n                })();\n                a = function() {};\n                function h() {\n                    console.log(a);\n                }\n            })(\"PASS\");\n        }\n        f();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5777_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            (function() {\n                function g() {\n                    h();\n                }\n                g();\n                a = function() {};\n                function h() {\n                    console.log(a);\n                }\n            })();\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        (function(a) {\n            (function() {\n                (function() {\n                    h();\n                })();\n                a = function() {};\n                function h() {\n                    console.log(a);\n                }\n            })();\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1666: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect: {\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect_stdout: true\n}\n\nissue_1666_strict: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect: {\n        \"use strict\";\n        var x = 42;\n        {\n            x();\n            function x() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof x);\n    }\n    expect_stdout: true\n}\n\nissue_1666_undefined: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect: {\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect_stdout: true\n}\n\nissue_1666_undefined_strict: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect: {\n        \"use strict\";\n        var undefined = 42;\n        {\n            undefined();\n            function undefined() {\n                console.log(\"foo\");\n            }\n        }\n        console.log(typeof undefined);\n    }\n    expect_stdout: true\n}\n\nissue_5872_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 42;\n        try {\n            while (!function f() {\n                a.p;\n                a = null;\n            }(a.q)) {\n                a.r;\n                console.log(\"FAIL\");\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = 42;\n        try {\n            while (!function f() {\n                a.p;\n                a = null;\n            }(a.q)) {\n                a.r;\n                console.log(\"FAIL\");\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5872_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {\n            a.p;\n            a = null;\n        }\n\n        var a = 42;\n        try {\n            while (!f(a.q)) {\n                a.r;\n                console.log(\"FAIL\");\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        function f() {\n            a.p;\n            a = null;\n        }\n\n        var a = 42;\n        try {\n            while (!f(a.q)) {\n                a.r;\n                console.log(\"FAIL\");\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5872_3: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 42;\n        try {\n            while (new function() {\n                a.p;\n                a = null;\n            }(a.q)) {\n                a.r;\n                console.log(\"FAIL\");\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = 42;\n        try {\n            while (new function() {\n                a.p;\n                a = null;\n            }(a.q)) {\n                a.r;\n                console.log(\"FAIL\");\n            }\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5892: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        try {\n            var a = 42;\n            a.p;\n            if (console)\n                a = null;\n            a.q;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            var a = 42;\n            a.p;\n            if (console)\n                a = null;\n            a.q;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5915_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        f = void 0;\n        if (console) {\n            console.log(typeof f);\n            function f() {}\n        }\n    }\n    expect: {\n        f = void 0;\n        if (console) {\n            console.log(typeof f);\n            function f() {}\n        }\n    }\n    expect_stdout: true\n}\n\nissue_5915_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        f = void 0;\n        if (console) {\n            function f() {}\n            console.log(typeof f);\n        }\n    }\n    expect: {\n        f = void 0;\n        if (console) {\n            function f() {}\n            console.log(typeof f);\n        }\n    }\n    expect_stdout: true\n}\n\nissue_5915_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        f = void 0;\n        function f() {}\n        if (console) {\n            console.log(typeof f);\n        }\n    }\n    expect: {\n        void 0;\n        if (console)\n            console.log(\"undefined\");\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_5915_4: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        if (console) {\n            f = void 0;\n            function f() {}\n            console.log(typeof f);\n        }\n    }\n    expect: {\n        if (console) {\n            void 0;\n            console.log(\"undefined\");\n        }\n    }\n    expect_stdout: \"undefined\"\n}\n"
  },
  {
    "path": "test/compress/regexp.js",
    "content": "regexp_simple: {\n    input: {\n        /rx/ig\n    }\n    expect_exact: \"/rx/gi;\"\n}\n\nregexp_slashes: {\n    input: {\n        /\\\\\\/rx\\/\\\\/ig\n    }\n    expect_exact: \"/\\\\\\\\\\\\/rx\\\\/\\\\\\\\/gi;\"\n}\n\nregexp_1: {\n    input: {\n        console.log(JSON.stringify(\"COMPASS? Overpass.\".match(/([Sap]+)/ig)));\n    }\n    expect: {\n        console.log(JSON.stringify(\"COMPASS? Overpass.\".match(/([Sap]+)/gi)));\n    }\n    expect_stdout: '[\"PASS\",\"pass\"]'\n}\n\nregexp_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(JSON.stringify(\"COMPASS? Overpass.\".match(new RegExp(\"([Sap]+)\", \"ig\"))));\n    }\n    expect: {\n        console.log(JSON.stringify(\"COMPASS? Overpass.\".match(/([Sap]+)/gi)));\n    }\n    expect_stdout: '[\"PASS\",\"pass\"]'\n}\n\nregexp_properties: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(/abc/g.source, /abc/g.global, /abc/g.ignoreCase, /abc/g.lastIndex, /abc/g.multiline);\n    }\n    expect: {\n        console.log(\"abc\", true, false, /abc/g.lastIndex, false);\n    }\n    expect_stdout: \"abc true false 0 false\"\n}\n\ninstanceof_1: {\n    input: {\n        console.log(/foo/ instanceof RegExp);\n    }\n    expect_exact: \"console.log(/foo/ instanceof RegExp);\"\n    expect_stdout: \"true\"\n}\n\ninstanceof_2: {\n    input: {\n        console.log(42 + /foo/ instanceof Object);\n    }\n    expect_exact: \"console.log(42+/foo/ instanceof Object);\"\n    expect_stdout: \"false\"\n}\n\nissue_3434_1: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        var o = {\n            \"\\n\": RegExp(\"\\n\"),\n            \"\\r\": RegExp(\"\\r\"),\n            \"\\t\": RegExp(\"\\t\"),\n            \"\\b\": RegExp(\"\\b\"),\n            \"\\f\": RegExp(\"\\f\"),\n            \"\\0\": RegExp(\"\\0\"),\n            \"\\x0B\": RegExp(\"\\x0B\"),\n            \"\\u2028\": RegExp(\"\\u2028\"),\n            \"\\u2029\": RegExp(\"\\u2029\"),\n        };\n        for (var c in o)\n            console.log(o[c].test(\"\\\\\"), o[c].test(c));\n    }\n    expect_exact: [\n        \"var o = {\",\n        '    \"\\\\n\": /\\\\n/,',\n        '    \"\\\\r\": /\\\\r/,',\n        '    \"\\\\t\": /\\t/,',\n        '    \"\\\\b\": /\\b/,',\n        '    \"\\\\f\": /\\f/,',\n        '    \"\\\\0\": /\\0/,',\n        '    \"\\\\v\": /\\v/,',\n        '    \"\\\\u2028\": /\\\\u2028/,',\n        '    \"\\\\u2029\": /\\\\u2029/',\n        \"};\",\n        \"\",\n        'for (var c in o) console.log(o[c].test(\"\\\\\\\\\"), o[c].test(c));',\n    ]\n    expect_stdout: [\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n    ]\n}\n\nissue_3434_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        var o = {\n            \"\\n\": RegExp(\"\\\\\\n\"),\n            \"\\r\": RegExp(\"\\\\\\r\"),\n            \"\\t\": RegExp(\"\\\\\\t\"),\n            \"\\b\": RegExp(\"\\\\\\b\"),\n            \"\\f\": RegExp(\"\\\\\\f\"),\n            \"\\0\": RegExp(\"\\\\\\0\"),\n            \"\\x0B\": RegExp(\"\\\\\\x0B\"),\n            \"\\u2028\": RegExp(\"\\\\\\u2028\"),\n            \"\\u2029\": RegExp(\"\\\\\\u2029\"),\n        };\n        for (var c in o)\n            console.log(o[c].test(\"\\\\\"), o[c].test(c));\n    }\n    expect_exact: [\n        \"var o = {\",\n        '    \"\\\\n\": /\\\\n/,',\n        '    \"\\\\r\": /\\\\r/,',\n        '    \"\\\\t\": /\\t/,',\n        '    \"\\\\b\": /\\b/,',\n        '    \"\\\\f\": /\\f/,',\n        '    \"\\\\0\": /\\0/,',\n        '    \"\\\\v\": /\\v/,',\n        '    \"\\\\u2028\": /\\\\u2028/,',\n        '    \"\\\\u2029\": /\\\\u2029/',\n        \"};\",\n        \"\",\n        'for (var c in o) console.log(o[c].test(\"\\\\\\\\\"), o[c].test(c));',\n    ]\n    expect_stdout: [\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n    ]\n}\n\nissue_3434_3: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        RegExp(\"\\n\");\n        RegExp(\"\\r\");\n        RegExp(\"\\\\n\");\n        RegExp(\"\\\\\\n\");\n        RegExp(\"\\\\\\\\n\");\n        RegExp(\"\\\\\\\\\\n\");\n        RegExp(\"\\\\\\\\\\\\n\");\n        RegExp(\"\\\\\\\\\\\\\\n\");\n        RegExp(\"\\u2028\");\n        RegExp(\"\\u2029\");\n        RegExp(\"\\n\\r\\u2028\\u2029\");\n        RegExp(\"\\\\\\nfo\\n[\\n]o\\\\bbb\");\n    }\n    expect: {\n        /\\n/;\n        /\\r/;\n        /\\n/;\n        /\\n/;\n        /\\\\n/;\n        /\\\\\\n/;\n        /\\\\\\n/;\n        /\\\\\\n/;\n        /\\u2028/;\n        /\\u2029/;\n        /\\n\\r\\u2028\\u2029/;\n        /\\nfo\\n[\\n]o\\bbb/;\n    }\n}\n\nissue_3434_4: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        [\n            [ \"\", RegExp(\"\") ],\n            [ \"/\", RegExp(\"/\") ],\n            [ \"//\", RegExp(\"//\") ],\n            [ \"\\/\", RegExp(\"\\\\/\") ],\n            [ \"///\", RegExp(\"///\") ],\n            [ \"/\\/\", RegExp(\"/\\\\/\") ],\n            [ \"\\//\", RegExp(\"\\\\//\") ],\n            [ \"\\\\/\", RegExp(\"\\\\\\\\/\") ],\n            [ \"////\", RegExp(\"////\") ],\n            [ \"//\\/\", RegExp(\"//\\\\/\") ],\n            [ \"/\\//\", RegExp(\"/\\\\//\") ],\n            [ \"/\\\\/\", RegExp(\"/\\\\\\\\/\") ],\n            [ \"\\///\", RegExp(\"\\\\///\") ],\n            [ \"\\/\\/\", RegExp(\"\\\\/\\\\/\") ],\n            [ \"\\\\//\", RegExp(\"\\\\\\\\//\") ],\n            [ \"\\\\\\/\", RegExp(\"\\\\\\\\\\\\/\") ],\n        ].forEach(function(test) {\n            console.log(test[1].test(\"\\\\\"), test[1].test(test[0]));\n        });\n    }\n    expect: {\n        [\n            [ \"\", /(?:)/ ],\n            [ \"/\", /\\// ],\n            [ \"//\", /\\/\\// ],\n            [ \"/\", /\\// ],\n            [ \"///\", /\\/\\/\\// ],\n            [ \"//\", /\\/\\// ],\n            [ \"//\", /\\/\\// ],\n            [ \"\\\\/\", /\\\\\\// ],\n            [ \"////\", /\\/\\/\\/\\// ],\n            [ \"///\", /\\/\\/\\// ],\n            [ \"///\", /\\/\\/\\// ],\n            [ \"/\\\\/\", /\\/\\\\\\// ],\n            [ \"///\", /\\/\\/\\// ],\n            [ \"//\", /\\/\\// ],\n            [ \"\\\\//\", /\\\\\\/\\// ],\n            [ \"\\\\/\", /\\\\\\// ],\n        ].forEach(function(test) {\n            console.log(test[1].test(\"\\\\\"), test[1].test(test[0]));\n        });\n    }\n    expect_stdout: [\n        \"true true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n        \"false true\",\n    ]\n}\n\nexec: {\n    options = {\n        evaluate: true,\n        loops: true,\n        unsafe: true,\n    }\n    input: {\n        while (/a/.exec(\"AAA\"))\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect: {\n        for (;null;)\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nexec_global: {\n    options = {\n        evaluate: true,\n        loops: true,\n        unsafe: true,\n    }\n    input: {\n        while (/a/g.exec(\"AAA\"))\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect: {\n        for (;null;)\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ntest: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        while (/a/.test(\"AAA\"))\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect: {\n        while (false)\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ntest_global: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        while (/a/g.test(\"AAA\"))\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect: {\n        while (false)\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nvar_exec: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var r = /a/;\n        while (r.exec(\"AAA\"))\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect: {\n        var r = /a/;\n        for (;null;)\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nvar_exec_global: {\n    options = {\n        evaluate: true,\n        loops: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var r = /a/g;\n        while (r.exec(\"aaa\"))\n            console.log(\"PASS\");\n    }\n    expect: {\n        var r = /a/g;\n        for (;r.exec(\"aaa\");)\n            console.log(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nvar_test: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var r = /a/;\n        while (r.test(\"AAA\"))\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect: {\n        var r = /a/;\n        while (false)\n            console.log(\"FAIL\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nvar_test_global: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var r = /a/g;\n        while (r.test(\"aaa\"))\n            console.log(\"PASS\");\n    }\n    expect: {\n        var r = /a/g;\n        while (r.test(\"aaa\"))\n            console.log(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nlazy_boolean: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        /b/.exec({}) && console.log(\"PASS\");\n        /b/.test({}) && console.log(\"PASS\");\n        /b/g.exec({}) && console.log(\"PASS\");\n        /b/g.test({}) && console.log(\"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n        console.log(\"PASS\");\n        console.log(\"PASS\");\n        console.log(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n}\n\nreset_state_between_evaluate: {\n    options = {\n        evaluate: true,\n        passes: 2,\n        unsafe: true,\n    }\n    input: {\n        console.log(function() {\n            for (var a in /[abc4]/g.exec(\"a\"))\n                return \"PASS\";\n            return \"FAIL\";\n        }());\n    }\n    expect: {\n        console.log(function() {\n            for (var a in /[abc4]/g.exec(\"a\"))\n                return \"PASS\";\n            return \"FAIL\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5878: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        console.log(\"PASS\");\n        /b/.exec({});\n    }\n    expect_exact: 'console.log(\"PASS\");/b/.exec({})\\n'\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/rename.js",
    "content": "mangle_catch: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(o){a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_ie8: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(args){a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(o){var a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var_ie8: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"FAIL\";try{throw 1}catch(args){var a=\"PASS\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_toplevel: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var c=\"FAIL\";try{throw 1}catch(o){c=\"PASS\"}console.log(c);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_ie8_toplevel: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"FAIL\";try{throw 1}catch(c){o=\"PASS\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var_toplevel: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var r=\"FAIL\";try{throw 1}catch(o){var r=\"PASS\"}console.log(r);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_var_ie8_toplevel: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            throw 1;\n        } catch (args) {\n            var a = \"PASS\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"FAIL\";try{throw 1}catch(r){var o=\"PASS\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"PASS\";try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1_ie8: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var a=\"PASS\";try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1_toplevel: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"PASS\";try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_1_ie8_toplevel: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'var o=\"PASS\";try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"PASS\"\n}\n\nmangle_catch_redef_2: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: false,\n    }\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_2_ie8: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: false,\n    }\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(a){var a=\"FAIL2\"}console.log(a);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_2_toplevel: {\n    rename = true\n    options = {\n        ie: false,\n        toplevel: true,\n    }\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"undefined\"\n}\n\nmangle_catch_redef_2_ie8_toplevel: {\n    rename = true\n    options = {\n        ie: true,\n        toplevel: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            throw \"FAIL1\";\n        } catch (a) {\n            var a = \"FAIL2\";\n        }\n        console.log(a);\n    }\n    expect_exact: 'try{throw\"FAIL1\"}catch(o){var o=\"FAIL2\"}console.log(o);'\n    expect_stdout: \"undefined\"\n}\n\nissue_2120_1: {\n    rename = true\n    mangle = {\n        ie: false,\n    }\n    input: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (c) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (c) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (t) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (t) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_2120_2: {\n    rename = true\n    mangle = {\n        ie: true,\n    }\n    input: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (c) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (c) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect: {\n        \"aaaaaaaa\";\n        var a = 1, b = \"FAIL\";\n        try {\n            throw 1;\n        } catch (c) {\n            try {\n                throw 0;\n            } catch (a) {\n                if (c) b = \"PASS\";\n            }\n        }\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n}\nfunction_iife_catch: {\n    rename = true\n    mangle = {\n        ie: false,\n    }\n    input: {\n        function f(n) {\n            !function() {\n                try {\n                    throw 0;\n                } catch (n) {\n                    var a = 1;\n                    console.log(n, a);\n                }\n            }();\n        }\n        f();\n    }\n    expect_exact: \"function f(o){!function(){try{throw 0}catch(o){var c=1;console.log(o,c)}}()}f();\"\n    expect_stdout: \"0 1\"\n}\n\nfunction_iife_catch_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n    }\n    input: {\n        function f(n) {\n            !function() {\n                try {\n                    throw 0;\n                } catch (n) {\n                    var a = 1;\n                    console.log(n, a);\n                }\n            }();\n        }\n        f();\n    }\n    expect_exact: \"function f(c){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();\"\n    expect_stdout: \"0 1\"\n}\n\nfunction_catch_catch: {\n    rename = true\n    mangle = {\n        ie: false,\n    }\n    input: {\n        var o = 0;\n        function f() {\n            try {\n                throw 1;\n            } catch (c) {\n                try {\n                    throw 2;\n                } catch (o) {\n                    var o = 3;\n                    console.log(o);\n                }\n            }\n            console.log(o);\n        }\n        f();\n    }\n    expect_exact: \"var o=0;function f(){try{throw 1}catch(o){try{throw 2}catch(c){var c=3;console.log(c)}}console.log(c)}f();\"\n    expect_stdout: [\n        \"3\",\n        \"undefined\",\n    ]\n}\n\nfunction_catch_catch_ie8: {\n    rename = true\n    mangle = {\n        ie: true,\n    }\n    input: {\n        var o = 0;\n        function f() {\n            try {\n                throw 1;\n            } catch (c) {\n                try {\n                    throw 2;\n                } catch (o) {\n                    var o = 3;\n                    console.log(o);\n                }\n            }\n            console.log(o);\n        }\n        f();\n    }\n    expect_exact: \"var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();\"\n    expect_stdout: [\n        \"3\",\n        \"undefined\",\n    ]\n}\n\nfunction_do_catch_ie8: {\n    rename = true\n    options = {\n        ie: true,\n        side_effects: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 1, b = 1, c = 0;\n        function d(e) {\n            var f, g, h, i;\n            do {\n                try {\n                    try {\n                        var j = function q(){}();\n                    } catch (r) {\n                        --a && w(\"ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy\");\n                        var k, l, m, n, o;\n                        --m;\n                        --n;\n                        --o;\n                    }\n                    try {\n                        i[1];\n                    } catch (s) {\n                        var p;\n                        switch (function t() {\n                            c++;\n                        }()) {\n                          case j + --p:\n                        }\n                    }\n                } catch (u) {}\n            } while (--i);\n            b--;\n        }\n        d();\n        console.log(b, c);\n    }\n    expect: {\n        var u = 1, y = 1, a = 0;\n        function c(c) {\n            var d;\n            do {\n                try {\n                    try {\n                        var e = void 0;\n                    } catch (i) {\n                        --u && w(\"ddddddddeeeeeeegggggggggiiiiilllllllnnnnntuuuuuuuuyyyyyyy\");\n                        0;\n                        0;\n                        0;\n                    }\n                    try {\n                        d[1];\n                    } catch (l) {\n                        var g;\n                        switch (function n() {\n                            a++;\n                        }()) {\n                        case e + --g:\n                        }\n                    }\n                } catch (t) {}\n            } while (--d);\n            y--;\n        }\n        c();\n        console.log(y, a);\n    }\n    expect_stdout: \"0 1\"\n}\n\nissue_3480: {\n    rename = true,\n    mangle = {\n        ie: false,\n        toplevel: false,\n    }\n    input: {\n        var d, a, b, c = \"FAIL\";\n        (function b() {\n            (function() {\n                try {\n                    c = \"PASS\";\n                } catch (b) {\n                }\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var d, a, b, c = \"FAIL\";\n        (function n() {\n            (function() {\n                try {\n                    c = \"PASS\";\n                } catch (c) {}\n            })();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3480_ie8: {\n    rename = true,\n    mangle = {\n        ie: true,\n        toplevel: false,\n    }\n    input: {\n        var d, a, b, c = \"FAIL\";\n        (function b() {\n            (function() {\n                try {\n                    c = \"PASS\";\n                } catch (b) {\n                }\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var d, a, b, c = \"FAIL\";\n        (function b() {\n            (function() {\n                try {\n                    c = \"PASS\";\n                } catch (b) {}\n            })();\n        })();\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3480_toplevel: {\n    rename = true,\n    mangle = {\n        ie: false,\n        toplevel: true,\n    }\n    input: {\n        var d, a, b, c = \"FAIL\";\n        (function b() {\n            (function() {\n                try {\n                    c = \"PASS\";\n                } catch (b) {\n                }\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c, n, o, t = \"FAIL\";\n        (function c() {\n            (function() {\n                try {\n                    t = \"PASS\";\n                } catch (c) {}\n            })();\n        })();\n        console.log(t);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3480_ie8_toplevel: {\n    rename = true,\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        var d, a, b, c = \"FAIL\";\n        (function b() {\n            (function() {\n                try {\n                    c = \"PASS\";\n                } catch (b) {\n                }\n            })();\n        })();\n        console.log(c);\n    }\n    expect: {\n        var c, n, o, t = \"FAIL\";\n        (function o() {\n            (function() {\n                try {\n                    t = \"PASS\";\n                } catch (o) {}\n            })();\n        })();\n        console.log(t);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5787_1: {\n    rename = true\n    input: {\n        console.log(function() {\n            const a = 42;\n            switch (a) {\n              case 42:\n                const a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            const a = 42;\n            switch (a) {\n              case 42:\n                const a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect_stdout: true\n}\n\nissue_5787_2: {\n    rename = true\n    input: {\n        console.log(function() {\n            let a = 42;\n            switch (a) {\n              case 42:\n                // Node.js v4 (vm): SyntaxError: Identifier 'a' has already been declared\n                let a = \"PASS\";\n                return a;\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            let a = 42;\n            switch (a) {\n              case 42:\n                let b = \"PASS\";\n                return b;\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n"
  },
  {
    "path": "test/compress/rests.js",
    "content": "arrow_1: {\n    input: {\n        console.log.apply(console, ((...a) => a)(\"PASS\", 42));\n    }\n    expect_exact: 'console.log.apply(console,((...a)=>a)(\"PASS\",42));'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\narrow_2: {\n    input: {\n        console.log.apply(console, ((a, ...b) => b)(\"FAIL\", \"PASS\", 42));\n    }\n    expect_exact: 'console.log.apply(console,((a,...b)=>b)(\"FAIL\",\"PASS\",42));'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\narrow_destructured_array_1: {\n    input: {\n        console.log.apply(console, (([ ...a ]) => a)(\"PASS\"));\n    }\n    expect_exact: 'console.log.apply(console,(([...a])=>a)(\"PASS\"));'\n    expect_stdout: \"P A S S\"\n    node_version: \">=6\"\n}\n\narrow_destructured_array_2: {\n    input: {\n        console.log.apply(console, (([ a, ...b ]) => b)([ \"FAIL\", \"PASS\", 42 ]));\n    }\n    expect_exact: 'console.log.apply(console,(([a,...b])=>b)([\"FAIL\",\"PASS\",42]));'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\narrow_destructured_array_3: {\n    input: {\n        console.log((([ [ ...a ] = \"FAIL\" ]) => a)([ \"PASS\" ]).join(\"|\"));\n    }\n    expect_exact: 'console.log((([[...a]=\"FAIL\"])=>a)([\"PASS\"]).join(\"|\"));'\n    expect_stdout: \"P|A|S|S\"\n    node_version: \">=6\"\n}\n\narrow_destructured_object_1: {\n    input: {\n        var f = ({ ...a }) => a, o = f({ PASS: 42 });\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_exact: \"var f=({...a})=>a,o=f({PASS:42});for(var k in o)console.log(k,o[k]);\"\n    expect_stdout: \"PASS 42\"\n    node_version: \">=8.3.0\"\n}\n\narrow_destructured_object_2: {\n    input: {\n        var f = ({ FAIL: a, ...b }) => b, o = f({ PASS: 42, FAIL: null });\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_exact: \"var f=({FAIL:a,...b})=>b,o=f({PASS:42,FAIL:null});for(var k in o)console.log(k,o[k]);\"\n    expect_stdout: \"PASS 42\"\n    node_version: \">=8.3.0\"\n}\n\narrow_destructured_object_3: {\n    input: {\n        var f = ([ { ...a } = [ \"FAIL\" ] ]) => a;\n        var o = f([ \"PASS\" ]);\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_exact: 'var f=([{...a}=[\"FAIL\"]])=>a;var o=f([\"PASS\"]);for(var k in o)console.log(k,o[k]);'\n    expect_stdout: [\n        \"0 P\",\n        \"1 A\",\n        \"2 S\",\n        \"3 S\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nfunarg_1: {\n    input: {\n        console.log.apply(console, function(...a) {\n            return a;\n        }(\"PASS\", 42));\n    }\n    expect_exact: 'console.log.apply(console,function(...a){return a}(\"PASS\",42));'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nfunarg_2: {\n    input: {\n        console.log.apply(console, function(a, ...b) {\n            return b;\n        }(\"FAIL\", \"PASS\", 42));\n    }\n    expect_exact: 'console.log.apply(console,function(a,...b){return b}(\"FAIL\",\"PASS\",42));'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\ndestructured_array_1: {\n    input: {\n        var [ ...a ] = [ \"PASS\", 42 ];\n        console.log.apply(console, a);\n    }\n    expect_exact: 'var[...a]=[\"PASS\",42];console.log.apply(console,a);'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\ndestructured_array_2: {\n    input: {\n        var [ a, ...b ] = [ \"FAIL\", \"PASS\", 42 ];\n        console.log.apply(console, b);\n    }\n    expect_exact: 'var[a,...b]=[\"FAIL\",\"PASS\",42];console.log.apply(console,b);'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\ndestructured_object_1: {\n    input: {\n        var { ...a } = [ \"FAIL\", \"PASS\", 42 ];\n        console.log(a[1], a[2]);\n    }\n    expect_exact: 'var{...a}=[\"FAIL\",\"PASS\",42];console.log(a[1],a[2]);'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=8.3.0\"\n}\n\ndestructured_object_2: {\n    input: {\n        var { 0: a, ...b } = [ \"FAIL\", \"PASS\", 42 ];\n        console.log(b[1], b[2]);\n    }\n    expect_exact: 'var{0:a,...b}=[\"FAIL\",\"PASS\",42];console.log(b[1],b[2]);'\n    expect_stdout: \"PASS 42\"\n    node_version: \">=8.3.0\"\n}\n\ndrop_fargs: {\n    options = {\n        keep_fargs: false,\n        rests: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, ...b) {\n            return b[0];\n        }(\"FAIL\", \"PASS\"));\n    }\n    expect: {\n        console.log(function(b) {\n            return b[0];\n        }([ \"PASS\" ]));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ninline: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(function(a, ...[ b, c ]) {\n            return c + b + a;\n        }(\"SS\", \"A\", \"P\"));\n    }\n    expect: {\n        console.log(([ a, ...[ b, c ] ] = [ \"SS\", \"A\", \"P\" ], c + b + a));\n        var a, b, c;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nretain_var: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var [ ...a ] = [ \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect: {\n        var [ ...a ] = [ \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_destructured_array: {\n    options = {\n        reduce_vars: true,\n        rests: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var [ ...a ] = [ \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect: {\n        console.log([ \"PASS\" ][0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_destructured_object: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var { ...a } = [ \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect: {\n        var { ...a } = [ \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nretain_destructured_array: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var [ a, ...b ] = [ \"FAIL\", \"PASS\", 42 ];\n        console.log.apply(console, b);\n    }\n    expect: {\n        var [ ...b ] = [ \"PASS\", 42 ];\n        console.log.apply(console, b);\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nretain_destructured_object_1: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var { 0: a, ...b } = [ \"FAIL\", \"PASS\", 42 ];\n        for (var k in b)\n            console.log(k, b[k]);\n    }\n    expect: {\n        var { 0: a, ...b } = [ \"FAIL\", \"PASS\", 42 ];\n        for (var k in b)\n            console.log(k, b[k]);\n    }\n    expect_stdout: [\n        \"1 PASS\",\n        \"2 42\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nretain_destructured_object_2: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var { foo: [ a ], ...b } = { foo: [ \"FAIL\" ], bar: \"PASS\", baz: 42 };\n        for (var k in b)\n            console.log(k, b[k]);\n    }\n    expect: {\n        var { foo: {}, ...b } = { foo: 0, bar: \"PASS\", baz: 42 };\n        for (var k in b)\n            console.log(k, b[k]);\n    }\n    expect_stdout: [\n        \"bar PASS\",\n        \"baz 42\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nretain_funarg_destructured_array_1: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        console.log((([ ...a ]) => a)([ \"PASS\" ])[0]);\n    }\n    expect: {\n        console.log((([ ...a ]) => a)([ \"PASS\" ])[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nretain_funarg_destructured_array_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function([ a, ...b ]) {\n            return b;\n        }(\"bar\")[1]);\n    }\n    expect: {\n        console.log(function([ , ...b ]) {\n            return b;\n        }(\"bar\")[1]);\n    }\n    expect_stdout: \"r\"\n    node_version: \">=6\"\n}\n\nretain_funarg_destructured_object_1: {\n    options = {\n        inline: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        console.log((({ ...a }) => a)([ \"PASS\" ])[0]);\n    }\n    expect: {\n        console.log((({ ...a }) => a)([ \"PASS\" ])[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nretain_funarg_destructured_object_2: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        console.log(function({ p: a, ... b }) {\n            return b;\n        }({ p: \"FAIL\" }).p || \"PASS\");\n    }\n    expect: {\n        console.log(function({ p: a, ... b }) {\n            return b;\n        }({}).p || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\ndrop_unused_call_args_1: {\n    options = {\n        rests: true,\n        unused: true,\n    }\n    input: {\n        (function(...a) {\n            console.log(a[0]);\n        })(42, console.log(\"PASS\"));\n    }\n    expect: {\n        (function(a) {\n            console.log(a[0]);\n        })([ 42, console.log(\"PASS\") ]);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=6\"\n}\n\ndrop_unused_call_args_2: {\n    options = {\n        keep_fargs: false,\n        rests: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a, ...b) {\n            return b;\n        }(console).length);\n    }\n    expect: {\n        console.log(function(b) {\n            return b;\n        }((console, [])).length);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=6\"\n}\n\nmaintain_position: {\n    options = {\n        unused: true,\n    }\n    input: {\n        A = \"FAIL\";\n        var [ , ...a ] = [ A, \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect: {\n        A = \"FAIL\";\n        var [ , ...a ] = [ A, \"PASS\" ];\n        console.log(a[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nmerge_funarg: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function(...a) {\n            var b = a.length;\n            console.log(b);\n        })();\n    }\n    expect: {\n        (function(...a) {\n            var a = a.length;\n            console.log(a);\n        })();\n    }\n    expect_stdout: \"0\"\n    node_version: \">=6\"\n}\n\nmerge_funarg_destructured_array: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function([ ...a ]) {\n            var b = a.length;\n            console.log(b);\n        })([]);\n    }\n    expect: {\n        (function([ ...a ]) {\n            var a = a.length;\n            console.log(a);\n        })([]);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=6\"\n}\n\nmerge_funarg_destructured_object: {\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        (function({ ...a }) {\n            var b = a[0];\n            console.log(b);\n        })([ \"PASS\" ]);\n    }\n    expect: {\n        (function({ ...a }) {\n            var a = a[0];\n            console.log(a);\n        })([ \"PASS\" ]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nkeep_arguments: {\n    options = {\n        arguments: true,\n        keep_fargs: false,\n    }\n    input: {\n        (function(...[ {} ]) {\n            console.log(arguments[0]);\n        })(\"PASS\");\n    }\n    expect: {\n        (function(...[ {} ]) {\n            console.log(arguments[0]);\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_rest_array: {\n    options = {\n        rests: true,\n    }\n    input: {\n        var [ ...[ a ] ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect: {\n        var [ a ] = [ \"PASS\" ];\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_rest_arrow: {\n    options = {\n        arrows: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n    }\n    input: {\n        console.log(((...[ a ]) => a)(\"PASS\"));\n    }\n    expect: {\n        console.log((a => a)(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_rest_lambda: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n        toplevel: true,\n    }\n    input: {\n        function f(...[ a ]) {\n            return a;\n        }\n        console.log(f(\"PASS\"), f(42));\n    }\n    expect: {\n        function f(a) {\n            return a;\n        }\n        console.log(f(\"PASS\"), f(42));\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nkeep_rest_array: {\n    options = {\n        rests: true,\n    }\n    input: {\n        var [ ...[ ...a ] ] = \"PASS\";\n        console.log(a.join(\"\"));\n    }\n    expect: {\n        var [ ...a ] = \"PASS\";\n        console.log(a.join(\"\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nkeep_rest_arrow: {\n    options = {\n        arrows: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n    }\n    input: {\n        console.log(((...[ ...a ]) => a.join(\"\"))(\"PASS\"));\n    }\n    expect: {\n        console.log(((...a) => a.join(\"\"))(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nkeep_rest_lambda_1: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n        toplevel: true,\n    }\n    input: {\n        function f(...[ ...a ]) {\n            return a.join(\"\");\n        }\n        console.log(f(\"PASS\"), f([ 42 ]));\n    }\n    expect: {\n        function f(...a) {\n            return a.join(\"\");\n        }\n        console.log(f(\"PASS\"), f([ 42 ]));\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\nkeep_rest_lambda_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        function f(...[ ...a ]) {\n            return a.join(\"\");\n        }\n        console.log(f(\"PASS\"), f([ 42 ]));\n    }\n    expect: {\n        function f(...[ ...a ]) {\n            return a.join(\"\");\n        }\n        console.log(f(\"PASS\"), f([ 42 ]));\n    }\n    expect_stdout: \"PASS 42\"\n    node_version: \">=6\"\n}\n\ndrop_new_function: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        new function(...{\n            [console.log(\"PASS\")]: a,\n        }) {}();\n    }\n    expect: {\n        void ([ ... {\n            [console.log(\"PASS\")]: [][0],\n        }] = []);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4525_1: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        console.log(function(a, ...[]) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(function(a, ...[]) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4525_2: {\n    options = {\n        unused: true,\n    }\n    input: {\n        console.log(function(a, ...[]) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log(function(a, ...[]) {\n            a = \"FAIL\";\n            return arguments[0];\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4538: {\n    options = {\n        rests: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function f(...a) {\n            return a.p, f;\n        }()());\n    }\n    expect: {\n        console.log(typeof function f(...a) {\n            return a.p, f;\n        }()());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_4544_1: {\n    options = {\n        keep_fnames: true,\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function f(...[ {} ]) {})();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [ ...[ {} ] ] = [];\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4544_2: {\n    options = {\n        keep_fnames: true,\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function f(a, ...[ {} ]) {})([]);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [ , ...[ {} ] ] = [ [] ];\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4560_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0;\n        (function(...{\n            [a++]: {},\n        }) {})(2);\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function(...{\n            [a++]: {},\n        }) {})(2);\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n    node_version: \">=6\"\n}\n\nissue_4560_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        (function(...{\n            [a++]: {},\n        }) {})(2);\n        console.log(a);\n    }\n    expect: {\n        var a = 0;\n        (function(...{\n            [a++]: {},\n        }) {})(2);\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n    node_version: \">=6\"\n}\n\nissue_4560_3: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = 0, b;\n        [ ...{\n            [a++]: b,\n        } ] = [ \"PASS\" ];\n        console.log(b);\n    }\n    expect: {\n        var a = 0, b;\n        [ ...{\n            [a++]: b,\n        } ] = [ \"PASS\" ];\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4562: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        rests: true,\n        unsafe: true,\n    }\n    input: {\n        console.log((([ ...[ a ] ]) => a)(\"foo\"));\n    }\n    expect: {\n        console.log((([ a ]) => a)(\"foo\"));\n    }\n    expect_stdout: \"f\"\n    node_version: \">=6\"\n}\n\nissue_4575: {\n    options = {\n        collapse_vars: true,\n        ie: true,\n        reduce_vars: true,\n        rests: true,\n        unused: true,\n    }\n    input: {\n        (function(a) {\n            var b = a;\n            var c = function a(...d) {\n                console.log(d.length);\n            }();\n        })();\n    }\n    expect: {\n        (function(a) {\n            (function(d) {\n                console.log(d.length);\n            })([]);\n        })();\n    }\n    expect_stdout: \"0\"\n    node_version: \">=6\"\n}\n\nissue_4621: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (function f(a, ...{\n            [console.log(a)]: b,\n        }) {})(\"PASS\");\n    }\n    expect: {\n        (function f(a, ...{\n            [console.log(a)]: b,\n        }) {})(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4644_1: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function f(b, ...{\n            [a = \"PASS\"]: c,\n        }) {\n            return b;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function f(b, ...{\n            [a = \"PASS\"]: c,\n        }) {\n            return b;\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4644_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(...a) {\n            return a[1];\n        }(\"FAIL\", \"PASS\"), function(...b) {\n            return b.length;\n        }(), function(c, ...d) {\n            return d[0];\n        }(\"FAIL\"));\n    }\n    expect: {\n        console.log(\"PASS\", 0, function(c, ...d) {\n            return d[0];\n        }(\"FAIL\"));\n    }\n    expect_stdout: \"PASS 0 undefined\"\n    node_version: \">=6\"\n}\n\nissue_4666: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        rests: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        var o = ((...c) => a++ + c)(b);\n        for (var k in o)\n            b++;\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 0;\n        var o = (c => +a + c)([ b ]);\n        for (var k in o)\n            b++;\n        console.log(1, b);\n    }\n    expect_stdout: \"1 2\"\n    node_version: \">=6\"\n}\n\nissue_5089_1: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var {\n            p: [] = 42,\n            ...o\n        } = {\n            p: [],\n        };\n        console.log(o.p);\n    }\n    expect: {\n        var {\n            p: {},\n            ...o\n        } = {\n            p: 0,\n        };\n        console.log(o.p);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=8.3.0\"\n}\n\nissue_5089_2: {\n    options = {\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var {\n            p: {} = null,\n            ...o\n        } = {\n            p: {},\n        };\n        console.log(o.p);\n    }\n    expect: {\n        var {\n            p: {},\n            ...o\n        } = {\n            p: 0,\n        };\n        console.log(o.p);\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=8.3.0\"\n}\n\nissue_5100_1: {\n    options = {\n        passes: 2,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        [ {\n            p: {},\n            ...a\n        } ] = [ {\n            p: {\n                q: a,\n            } = 42,\n            r: \"PASS\",\n        } ];\n        console.log(a.r);\n    }\n    expect: {\n        var a;\n        ({\n            p: {},\n            ...a\n        } = [ {\n            p: {\n                q: a,\n            } = 42,\n            r: \"PASS\",\n        } ][0]);\n        console.log(a.r);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_5100_2: {\n    options = {\n        passes: 2,\n        pure_getters: \"strict\",\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        [ {\n            p: {},\n            ...a\n        } ] = [ {\n            p: (console.log(\"PASS\"), {\n                q: a,\n            } = 42),\n        } ];\n    }\n    expect: {\n        var a;\n        ({\n            p: {},\n            ...a\n        } = [ {\n            p: (console.log(\"PASS\"), {\n                q: a,\n            } = 42),\n        } ][0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10.22.0\"\n}\n\nissue_5108: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        console.log(function([ ...[ a ] ]) {\n            return a;\n        }([ \"PASS\", \"FAIL\" ]));\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5128_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function() {\n            return function f(...[ a ]) {\n                return a;\n            }(\"PASS\");\n        }());\n    }\n    expect: {\n        console.log(function f(...[ a ]) {\n            return a;\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5128_2: {\n    options = {\n        inline: true,\n        keep_fnames: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            return function f(...[ a ]) {\n                return a;\n            }(\"PASS\");\n        }());\n    }\n    expect: {\n        console.log(function f(...[ a ]) {\n            return a;\n        }(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5165_1: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        rests: true,\n        side_effects: true,\n        switches: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function([ ...a ]) {\n            switch (a) {\n              case a:\n                return \"PASS\";\n            }\n        }([]));\n    }\n    expect: {\n        console.log(function([ ...a ]) {\n            return \"PASS\";\n        }([]));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5165_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        rests: true,\n        side_effects: true,\n        switches: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(...a) {\n            switch (a) {\n              case a:\n                return \"PASS\";\n            }\n        }());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5246_1: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function([ , ...a ]) {\n            return this && a;\n        }([ , function(){} ])[0]);\n    }\n    expect: {\n        console.log(typeof function() {\n            return this && [ function(){} ];\n        }()[0]);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=6\"\n}\n\nissue_5246_2: {\n    options = {\n        keep_fargs: false,\n        reduce_vars: true,\n        rests: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        A = [ , \"PASS\", \"FAIL\" ];\n        var  [ , ...a ] = [ ... A ];\n        console.log(a[0]);\n    }\n    expect: {\n        A = [ , \"PASS\", \"FAIL\" ];\n        var  [ , ...a ] = [ ... A ];\n        console.log(a[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5246_3: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        (function f(...[ [ a ] ]) {\n            console.log(a);\n        })([ \"PASS\" ]);\n    }\n    expect: {\n        (function(...[ a ]) {\n            console.log(a);\n        })([ \"PASS\" ][0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5360: {\n    options = {\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        unused: true,\n    }\n    input: {\n        var a;\n        console.log(function({ p: {}, ...b }) {\n            return b.q;\n        }({\n            p: ~a && ([ a ] = []),\n            q: \"PASS\",\n        }));\n    }\n    expect: {\n        var a;\n        console.log(function({ p: {}, ...b }) {\n            return b.q;\n        }({\n            p: ~a && ([ a ] = []),\n            q: \"PASS\",\n        }));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_5370: {\n    options = {\n        dead_code: true,\n        ie: true,\n        unused: true,\n    }\n    input: {\n        console.log(function arguments(...a) {\n            return arguments;\n            try {} catch (e) {\n                var arguments;\n            }\n        }());\n    }\n    expect: {\n        console.log(function arguments(...a) {\n            return arguments;\n            var arguments;\n        }());\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_5391: {\n    options = {\n        evaluate: true,\n        keep_fargs: false,\n        objects: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a, b = function f({\n            p: {},\n            ...c\n        }) {\n            while (c.q);\n        }({\n            p: {\n                r: a++,\n                r: 0,\n            }\n        });\n        console.log(a);\n    }\n    expect: {\n        (function({\n            p: {},\n            ...c\n        }) {\n            while (c.q);\n        })({\n            p: 0,\n        });\n        console.log(NaN);\n    }\n    expect_stdout: \"NaN\"\n    node_version: \">=8.3.0\"\n}\n\nissue_5533_1_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(...b) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_1_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(...b) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_2_keep_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: true,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(...[ b ]) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5533_2_drop_fargs: {\n    options = {\n        evaluate: true,\n        inline: true,\n        join_vars: true,\n        keep_fargs: false,\n        loops: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        try {\n            (function() {\n                var a;\n                for (; 1;)\n                    a = function() {\n                        (function f(...[ b ]) {\n                            b;\n                            throw \"PASS\";\n                        })();\n                    }();\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect: {\n        \"use strict\";\n        try {\n            (function() {\n                for (;;)\n                    throw \"PASS\";\n            })();\n        } catch (e) {\n            console.log(e);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5552_1: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var a = f, b = log();\n        function f(...[ c = a = \"PASS\" ]) {}\n        f((a = \"FAIL\", b));\n        log(a);\n    }\n    expect: {\n        var log = console.log;\n        var a = f, b = log();\n        function f(...[ c = a = \"PASS\" ]) {}\n        f((a = \"FAIL\", b));\n        log(a);\n    }\n    expect_stdout: [\n        \"\",\n        \"PASS\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5552_2: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var log = console.log;\n        var a = f;\n        function f(...{ [a = \"PASS\"]: b }) {}\n        f((a = \"FAIL\", 42));\n        log(a);\n    }\n    expect: {\n        var log = console.log;\n        var a = f;\n        function f(...{ [a = \"PASS\"]: b }) {}\n        f((a = \"FAIL\", 42));\n        log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5552_3: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = [ \"FAIL\", \"PASS\" ];\n        console.log(function(b, ...[ c = a.pop() ]) {\n            return b;\n        }(a.pop()));\n    }\n    expect: {\n        var a = [ \"FAIL\", \"PASS\" ];\n        console.log(function(b, ...[ c = a.pop() ]) {\n            return b;\n        }(a.pop()));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5552_4: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = [ \"FAIL\", \"PASS\" ];\n        console.log(function(b, ...{ [a.pop()]: c }) {\n            return b;\n        }(a.pop()));\n    }\n    expect: {\n        var a = [ \"FAIL\", \"PASS\" ];\n        console.log(function(b, ...{ [a.pop()]: c }) {\n            return b;\n        }(a.pop()));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5705: {\n    options = {\n        reduce_vars: true,\n        rests: true,\n        unused: true,\n    }\n    input: {\n        (function(...a) {\n            var b = { ...a };\n        })(console.log(\"PASS\"));\n    }\n    expect: {\n        (function() {})(console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n"
  },
  {
    "path": "test/compress/return_undefined.js",
    "content": "return_undefined: {\n    options = {\n        booleans: true,\n        comparisons: true,\n        conditionals: true,\n        dead_code: true,\n        drop_debugger: true,\n        evaluate: true,\n        hoist_funs: true,\n        hoist_vars: true,\n        if_return: true,\n        join_vars: true,\n        keep_fargs: true,\n        keep_fnames: false,\n        loops: true,\n        negate_iife: true,\n        properties: true,\n        sequences: false,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        function f0() {\n        }\n        function f1() {\n            return undefined;\n        }\n        function f2() {\n            return void 0;\n        }\n        function f3() {\n            return void 123;\n        }\n        function f4() {\n            return;\n        }\n        function f5(a, b) {\n            console.log(a, b);\n            baz(a);\n            return;\n        }\n        function f6(a, b) {\n            console.log(a, b);\n            if (a) {\n                foo(b);\n                baz(a);\n                return a + b;\n            }\n            return undefined;\n        }\n        function f7(a, b) {\n            console.log(a, b);\n            if (a) {\n                foo(b);\n                baz(a);\n                return void 0;\n            }\n            return a + b;\n        }\n        function f8(a, b) {\n            foo(a);\n            bar(b);\n            return void 0;\n        }\n        function f9(a, b) {\n            foo(a);\n            bar(b);\n            return undefined;\n        }\n        function f10() {\n            return false;\n        }\n        function f11() {\n            return null;\n        }\n        function f12() {\n            return 0;\n        }\n    }\n    expect: {\n        function f0() {}\n        function f1() {}\n        function f2() {}\n        function f3() {}\n        function f4() {}\n        function f5(a, b) {\n            console.log(a, b);\n            baz(a);\n        }\n        function f6(a, b) {\n            console.log(a, b);\n            if (a) {\n                foo(b);\n                baz(a);\n                return a + b;\n            }\n        }\n        function f7(a, b) {\n            console.log(a, b);\n            if (!a)\n                return a + b;\n            foo(b);\n            baz(a);\n        }\n        function f8(a, b) {\n            foo(a);\n            bar(b);\n        }\n        function f9(a, b) {\n            foo(a);\n            bar(b);\n        }\n        function f10() {\n            return !1;\n        }\n        function f11() {\n            return null;\n        }\n        function f12() {\n            return 0;\n        }\n    }\n}\n\nreturn_void: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                h();\n            }\n            return g();\n        }\n    }\n    expect: {\n        function f() {\n            h();\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/sandbox.js",
    "content": "console_log: {\n    input: {\n        console.log(\"%% %s\");\n        console.log(\"%% %s\", \"%s\");\n    }\n    expect: {\n        console.log(\"%% %s\");\n        console.log(\"%% %s\", \"%s\");\n    }\n    expect_stdout: [\n        \"%% %s\",\n        \"% %s\",\n    ]\n}\n\nconsole_log_console: {\n    input: {\n        var log = console.log;\n        log(console);\n        log(typeof console.log);\n    }\n    expect: {\n        var log = console.log;\n        log(console);\n        log(typeof console.log);\n    }\n    expect_stdout: [\n        \"{ log: 'function(){}' }\",\n        \"function\",\n    ]\n}\n\ntypeof_arguments: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var arguments;\n        console.log((typeof arguments).length);\n    }\n    expect: {\n        var arguments;\n        console.log((typeof arguments).length);\n    }\n    expect_stdout: \"6\"\n}\n\ntypeof_arguments_assigned: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var arguments = void 0;\n        console.log((typeof arguments).length);\n    }\n    expect: {\n        console.log(\"undefined\".length);\n    }\n    expect_stdout: \"9\"\n}\n\ntoplevel_Infinity_NaN_undefined: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var Infinity = \"foo\";\n        var NaN = 42;\n        var undefined = null;\n        console.log(Infinity, NaN, undefined);\n    }\n    expect: {\n        console.log(\"foo\", 42, null);\n    }\n    expect_stdout: \"foo 42 null\"\n}\n\nlog_global: {\n    input: {\n        console.log(function() {\n            return this;\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return this;\n        }());\n    }\n    expect_stdout: \"[object global]\"\n}\n\nlog_nested: {\n    options = {\n        unused: true,\n    }\n    input: {\n        var o = { p: 42 };\n        for (var i = 0; i < 10; i++)\n            o = {\n                p: o,\n                q: function foo() {},\n            };\n        console.log(o);\n    }\n    expect: {\n        var o = { p: 42 };\n        for (var i = 0; i < 10; i++)\n            o = {\n                p: o,\n                q: function() {},\n            };\n        console.log(o);\n    }\n    expect_stdout: true\n}\n\ntimers: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var count = 0, interval = 1000, duration = 3210;\n        var timer = setInterval(function() {\n            if (!count++) setTimeout(function() {\n                clearInterval(timer);\n                console.log(count <= 4 ? \"PASS\" : \"FAIL\");\n            }, duration);\n        }, interval);\n    }\n    expect: {\n        var count = 0;\n        var timer = setInterval(function() {\n            if (!count++) setTimeout(function() {\n                clearInterval(timer);\n                console.log(count <= 4 ? \"PASS\" : \"FAIL\");\n            }, 3210);\n        }, 1000);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=0.12\"\n}\n\nissue_4054: {\n    input: {\n        console.log({\n            set p(v) {\n                throw \"FAIL\";\n            },\n        });\n    }\n    expect: {\n        console.log({\n            set p(v) {\n                throw \"FAIL\";\n            },\n        });\n    }\n    expect_stdout: \"{ p: [Setter] }\"\n}\n\nissue_4811_1: {\n    input: {\n        for (var PASS in this);\n        console.log(PASS, this, {} < this);\n    }\n    expect: {\n        for (var PASS in this);\n        console.log(PASS, this, {} < this);\n    }\n    expect_stdout: \"PASS [object global] true\"\n}\n\nissue_4811_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (async function() {});\n        for (var PASS in this);\n        console.log(PASS, this, {} < this);\n    }\n    expect: {\n        for (var PASS in this);\n        console.log(PASS, this, {} < this);\n    }\n    expect_stdout: \"PASS [object global] true\"\n    node_version: \">=8\"\n}\n\nissue_5197: {\n    rename = true\n    input: {\n        function f(async) {\n            async(\")=>{}\");\n        }\n        console.log(\"\" + this.__proto__);\n    }\n    expect: {\n        function f(a) {\n            a(\")=>{}\");\n        }\n        console.log(\"\" + this.__proto__);\n    }\n    expect_stdout: \"[object global]\"\n}\n"
  },
  {
    "path": "test/compress/sequences.js",
    "content": "make_sequences_1: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        foo();\n        bar();\n        baz();\n    }\n    expect: {\n        foo(),bar(),baz();\n    }\n}\n\nmake_sequences_2: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        if (boo) {\n            foo();\n            bar();\n            baz();\n        } else {\n            x();\n            y();\n            z();\n        }\n    }\n    expect: {\n        if (boo) foo(),bar(),baz();\n        else x(),y(),z();\n    }\n}\n\nmake_sequences_3: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        function f() {\n            foo();\n            bar();\n            return baz();\n        }\n        function g() {\n            foo();\n            bar();\n            throw new Error();\n        }\n    }\n    expect: {\n        function f() {\n            return foo(), bar(), baz();\n        }\n        function g() {\n            throw foo(), bar(), new Error();\n        }\n    }\n}\n\nmake_sequences_4: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        x = 5;\n        if (y) z();\n\n        x = 5;\n        for (i = 0; i < 5; i++) console.log(i);\n\n        x = 5;\n        for (; i < 5; i++) console.log(i);\n\n        x = 5;\n        switch (y) {}\n\n        x = 5;\n        with (obj) {}\n    }\n    expect: {\n        if (x = 5, y) z();\n        for (x = 5, i = 0; i < 5; i++) console.log(i);\n        for (x = 5; i < 5; i++) console.log(i);\n        switch (x = 5, y) {}\n        with (x = 5, obj);\n    }\n    expect_stdout: true\n}\n\nlift_sequences_1: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        var foo, x, y, bar;\n        foo = !(x(), y(), bar());\n    }\n    expect: {\n        var foo, x, y, bar;\n        x(), y(), foo = !bar();\n    }\n}\n\nlift_sequences_2: {\n    options = {\n        evaluate: true,\n        sequences: true,\n    }\n    input: {\n        var foo = 1, bar;\n        foo.x = (foo = {}, 10);\n        bar = (bar = {}, 10);\n        console.log(foo, bar);\n    }\n    expect: {\n        var foo = 1, bar;\n        foo.x = (foo = {}, 10),\n        bar = {}, bar = 10,\n        console.log(foo, bar);\n    }\n    expect_stdout: true\n}\n\nlift_sequences_3: {\n    options = {\n        conditionals: true,\n        sequences: true,\n    }\n    input: {\n        var x, foo, bar, baz;\n        x = (foo(), bar(), baz()) ? 10 : 20;\n    }\n    expect: {\n        var x, foo, bar, baz;\n        foo(), bar(), x = baz() ? 10 : 20;\n    }\n}\n\nlift_sequences_4: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var x, foo, bar, baz;\n        x = (foo, bar, baz);\n    }\n    expect: {\n        var x, foo, bar, baz;\n        x = baz;\n    }\n}\n\nlift_sequences_5: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        var a = 2, b;\n        a *= (b, a = 4, 3);\n        console.log(a);\n    }\n    expect: {\n        var a = 2, b;\n        b, a *= (a = 4, 3),\n        console.log(a);\n    }\n    expect_stdout: \"6\"\n}\n\nfor_sequences: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        // 1\n        foo();\n        bar();\n        for (; false;);\n        // 2\n        foo();\n        bar();\n        for (x = 5; false;);\n        // 3\n        x = (foo in bar);\n        for (; false;);\n        // 4\n        x = (foo in bar);\n        for (y = 5; false;);\n        // 5\n        x = function() {\n            foo in bar;\n        };\n        for (y = 5; false;);\n    }\n    expect: {\n        // 1\n        for (foo(), bar(); false;);\n        // 2\n        for (foo(), bar(), x = 5; false;);\n        // 3\n        x = (foo in bar);\n        for (; false;);\n        // 4\n        x = (foo in bar);\n        for (y = 5; false;);\n        // 5\n        for (x = function() {\n            foo in bar;\n        }, y = 5; false;);\n    }\n}\n\nlimit_1: {\n    options = {\n        sequences: 3,\n    }\n    input: {\n        a;\n        b;\n        c;\n        d;\n        e;\n        f;\n        g;\n        h;\n        i;\n        j;\n        k;\n    }\n    expect: {\n        a, b, c;\n        d, e, f;\n        g, h, i;\n        j, k;\n    }\n}\n\nlimit_2: {\n    options = {\n        sequences: 3,\n    }\n    input: {\n        a, b;\n        c, d;\n        e, f;\n        g, h;\n        i, j;\n        k;\n    }\n    expect: {\n        a, b, c, d;\n        e, f, g, h;\n        i, j, k;\n    }\n}\n\nnegate_iife_for: {\n    options = {\n        negate_iife: true,\n        sequences: true,\n    }\n    input: {\n        (function() {})();\n        for (i = 0; i < 5; i++) console.log(i);\n        (function() {})();\n        for (; i < 10; i++) console.log(i);\n    }\n    expect: {\n        for (!function() {}(), i = 0; i < 5; i++) console.log(i);\n        for (!function() {}(); i < 10; i++) console.log(i);\n    }\n    expect_stdout: true\n}\n\niife: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        x = 42;\n        (function a() {})();\n        !function b() {}();\n        ~function c() {}();\n        +function d() {}();\n        -function e() {}();\n        void function f() {}();\n        typeof function g() {}();\n    }\n    expect: {\n        x = 42,\n        function a() {}(),\n        !function b() {}(),\n        ~function c() {}(),\n        +function d() {}(),\n        -function e() {}(),\n        void function f() {}(),\n        typeof function g() {}();\n    }\n}\n\niife_drop_side_effect_free: {\n    options = {\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        x = 42;\n        (function a() {})();\n        !function b() {}();\n        ~function c() {}();\n        +function d() {}();\n        -function e() {}();\n        void function f() {}();\n        typeof function g() {}();\n    }\n    expect: {\n        x = 42;\n    }\n}\n\nunsafe_undefined: {\n    options = {\n        conditionals: true,\n        if_return: true,\n        sequences: true,\n        side_effects: true,\n        unsafe_undefined: true,\n    }\n    input: {\n        function f(undefined) {\n            if (a)\n                return b;\n            if (c)\n                return d;\n        }\n        function g(undefined) {\n            if (a)\n                return b;\n            if (c)\n                return d;\n            e();\n        }\n    }\n    expect: {\n        function f(undefined) {\n            return a ? b : c ? d : undefined;\n        }\n        function g(undefined) {\n            return a ? b : c ? d : void e();\n        }\n    }\n}\n\nissue_1685: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        function f() {\n            var a = (a--, delete a && --b);\n        }\n        f();\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        function f() {\n            var a = (a--, delete a && --b);\n        }\n        f();\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\nfunc_def_1: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            return f = 0, !!f;\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            return !!(f = 0);\n        }\n        console.log(f());\n    }\n    expect_stdout: \"false\"\n}\n\nfunc_def_2: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function f() {\n            return f = 0, !!f;\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            return f = 0, !!f;\n        }());\n    }\n    expect_stdout: \"true\"\n}\n\nfunc_def_3: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            function g() {}\n            return g = 0, !!g;\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            function g() {}\n            return !!(g = 0);\n        }\n        console.log(f());\n    }\n    expect_stdout: \"false\"\n}\n\nfunc_def_4: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            function g() {\n                return g = 0, !!g;\n            }\n            return g();\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            function g() {\n                return !!(g = 0);\n            }\n            return g();\n        }\n        console.log(f());\n    }\n    expect_stdout: \"false\"\n}\n\nfunc_def_5: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {\n            return function g(){\n                return g = 0, !!g;\n            }();\n        }\n        console.log(f());\n    }\n    expect: {\n        function f() {\n            return function g(){\n                return g = 0, !!g;\n            }();\n        }\n        console.log(f());\n    }\n    expect_stdout: \"true\"\n}\n\nissue_1758: {\n    options = {\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function(c) {\n            var undefined = 42;\n            return function() {\n                c--;\n                c--, c.toString();\n                return;\n            }();\n        }());\n    }\n    expect: {\n        console.log(function(c) {\n            var undefined = 42;\n            return function() {\n                return c--, c--, void c.toString();\n            }();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\ndelete_seq_1: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (1, undefined));\n        console.log(delete (1, void 0));\n        console.log(delete (1, Infinity));\n        console.log(delete (1, 1 / 0));\n        console.log(delete (1, NaN));\n        console.log(delete (1, 0 / 0));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\ndelete_seq_2: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (1, 2, undefined));\n        console.log(delete (1, 2, void 0));\n        console.log(delete (1, 2, Infinity));\n        console.log(delete (1, 2, 1 / 0));\n        console.log(delete (1, 2, NaN));\n        console.log(delete (1, 2, 0 / 0));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\ndelete_seq_3: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        keep_infinity: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(delete (1, 2, undefined));\n        console.log(delete (1, 2, void 0));\n        console.log(delete (1, 2, Infinity));\n        console.log(delete (1, 2, 1 / 0));\n        console.log(delete (1, 2, NaN));\n        console.log(delete (1, 2, 0 / 0));\n    }\n    expect: {\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\ndelete_seq_4: {\n    options = {\n        booleans: true,\n        evaluate: false,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {}\n        console.log(delete (f(), undefined));\n        console.log(delete (f(), void 0));\n        console.log(delete (f(), Infinity));\n        console.log(delete (f(), 1 / 0));\n        console.log(delete (f(), NaN));\n        console.log(delete (f(), 0 / 0));\n    }\n    expect: {\n        function f() {}\n        console.log(delete void f()),\n        console.log(delete void f()),\n        console.log((f(), delete (1 / 0))),\n        console.log((f(), delete (1 / 0))),\n        console.log(delete (f(), NaN)),\n        console.log((f(), delete(0 / 0)));\n    }\n    expect_stdout: true\n}\n\ndelete_seq_4_evaluate: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {}\n        console.log(delete (f(), undefined));\n        console.log(delete (f(), void 0));\n        console.log(delete (f(), Infinity));\n        console.log(delete (f(), 1 / 0));\n        console.log(delete (f(), NaN));\n        console.log(delete (f(), 0 / 0));\n    }\n    expect: {\n        function f() {}\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0));\n    }\n    expect_stdout: true\n}\n\ndelete_seq_5: {\n    options = {\n        booleans: true,\n        evaluate: false,\n        keep_infinity: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {}\n        console.log(delete (f(), undefined));\n        console.log(delete (f(), void 0));\n        console.log(delete (f(), Infinity));\n        console.log(delete (f(), 1 / 0));\n        console.log(delete (f(), NaN));\n        console.log(delete (f(), 0 / 0));\n    }\n    expect: {\n        function f() {}\n        console.log(delete void f()),\n        console.log(delete void f()),\n        console.log(delete (f(), Infinity)),\n        console.log((f(), delete (1 / 0))),\n        console.log(delete (f(), NaN)),\n        console.log((f(), delete (0 / 0)));\n    }\n    expect_stdout: true\n}\n\ndelete_seq_5_evaluate: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        keep_infinity: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f() {}\n        console.log(delete (f(), undefined));\n        console.log(delete (f(), void 0));\n        console.log(delete (f(), Infinity));\n        console.log(delete (f(), 1 / 0));\n        console.log(delete (f(), NaN));\n        console.log(delete (f(), 0 / 0));\n    }\n    expect: {\n        function f() {}\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0)),\n        console.log((f(), !0));\n    }\n    expect_stdout: true\n}\n\ndelete_seq_6: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        var a;\n        console.log(delete (1, a));\n    }\n    expect: {\n        var a;\n        console.log(!0);\n    }\n    expect_stdout: true\n}\n\nside_effects: {\n    options = {\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        0, a(), 1, b(), 2, c(), 3;\n    }\n    expect: {\n        a(), b(), c();\n    }\n}\n\nside_effects_cascade_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            a -= 42;\n            if (a < 0) a = 0;\n            b.a = a;\n        }\n        var m = {}, n = {};\n        f(13, m);\n        f(\"foo\", n);\n        console.log(m.a, n.a);\n    }\n    expect: {\n        function f(a, b) {\n            b.a = a = (a -= 42) < 0 ? 0 : a;\n        }\n        var m = {}, n = {};\n        f(13, m),\n        f(\"foo\", n),\n        console.log(m.a, n.a);\n    }\n    expect_stdout: \"0 NaN\"\n}\n\nside_effects_cascade_2: {\n    options = {\n        collapse_vars: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            b = a,\n            !a + (b += a) || (b += a),\n            b = a,\n            b;\n        }\n    }\n    expect: {\n        function f(a, b) {\n            !(b = a) + (b += a) || (b += a),\n            b = a;\n        }\n    }\n}\n\nside_effects_cascade_3: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        function f(a, b) {\n            \"foo\" ^ (b += a),\n            b ? false : (b = a) ? -1 : (b -= a) - (b ^= a),\n            a-- || !a,\n            a;\n        }\n    }\n    expect: {\n        function f(a, b) {\n            (b += a) || (b = a) || (b = b - a ^ a),\n            a--;\n        }\n    }\n}\n\nissue_27: {\n    options = {\n        collapse_vars: true,\n        passes: 2,\n        sequences: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function(jQuery) {\n            var $;\n            $ = jQuery;\n            $(\"body\").addClass(\"foo\");\n        })(jQuery);\n    }\n    expect: {\n        (function(jQuery) {\n            jQuery(\"body\").addClass(\"foo\");\n        })(jQuery);\n    }\n}\n\nissue_2062: {\n    options = {\n        booleans: true,\n        collapse_vars: true,\n        conditionals: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 1;\n        if ([ a || a++ + a--, a++ + a--, a && a.var ]);\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        a || (a++, a--), a++, --a && a.var;\n        console.log(a);\n    }\n    expect_stdout: \"1\"\n}\n\nissue_2313: {\n    options = {\n        collapse_vars: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 0, b = 0;\n        var foo = {\n            get c() {\n                a++;\n                return 42;\n            },\n            set c(c) {\n                b++;\n            },\n            d: function() {\n                this.c++;\n                if (this.c) console.log(a, b);\n            }\n        }\n        foo.d();\n    }\n    expect: {\n        var a = 0, b = 0;\n        var foo = {\n            get c() {\n                return a++, 42;\n            },\n            set c(c) {\n                b++;\n            },\n            d: function() {\n                if (this.c++, this.c) console.log(a, b);\n            }\n        }\n        foo.d();\n    }\n    expect_stdout: \"2 1\"\n}\n\ncascade_assignment_in_return: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        function f(a, b) {\n            return a = x(), b(a);\n        }\n    }\n    expect: {\n        function f(a, b) {\n            return b(x());\n        }\n    }\n}\n\nhoist_defun: {\n    options = {\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        x();\n        function f() {}\n        y();\n    }\n    expect: {\n        function f() {}\n        x(), y();\n    }\n}\n\nhoist_decl: {\n    options = {\n        join_vars: true,\n        sequences: true,\n    }\n    input: {\n        var a;\n        w();\n        var b = x();\n        y();\n        for (var c; 0;) z();\n        var d;\n    }\n    expect: {\n        var a, b = (w(), x()), c, d;\n        for (y(); 0;) z();\n    }\n}\n\nfor_init_var: {\n    options = {\n        join_vars: true,\n        unused: false,\n    }\n    input: {\n        var a = \"PASS\";\n        (function() {\n            var b = 42;\n            for (var c = 5; c > 0;) c--;\n            a = \"FAIL\";\n            var a;\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function() {\n            for (var b = 42, c = 5, a; c > 0;) c--;\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nforin_1: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        var o = [];\n        o.push(\"PASS\");\n        for (var a in o)\n            console.log(o[a]);\n    }\n    expect: {\n        var o = [];\n        for (var a in o.push(\"PASS\"), o)\n            console.log(o[a]);\n    }\n    expect_stdout: \"PASS\"\n}\n\nforin_2: {\n    options = {\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var o = {\n            p: 1,\n            q: 2,\n        };\n        var k = \"k\";\n        for ((console.log(\"exp\"), o)[function() {\n            console.log(\"prop\");\n            return k;\n        }()] in function() {\n            console.log(\"obj\");\n            return o;\n        }())\n            console.log(o.k, o[o.k]);\n    }\n    expect: {\n        var o = {\n            p: 1,\n            q: 2,\n        };\n        for ((console.log(\"exp\"), o)[console.log(\"prop\"), \"k\"] in console.log(\"obj\"), o)\n            console.log(o.k, o[o.k]);\n    }\n    expect_stdout: [\n        \"obj\",\n        \"exp\",\n        \"prop\",\n        \"p 1\",\n        \"exp\",\n        \"prop\",\n        \"q 2\",\n    ]\n}\n\ncall: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        var a = function() {\n            return this;\n        }();\n        function b() {\n            console.log(\"foo\");\n        }\n        b.c = function() {\n            console.log(this === b ? \"bar\" : \"baz\");\n        };\n        (a, b)();\n        (a, b).c();\n        (a, b.c)();\n        (a, b)[\"c\"]();\n        (a, b[\"c\"])();\n        (a, function() {\n            console.log(this === a);\n        })();\n        new (a, b)();\n        new (a, b).c();\n        new (a, b.c)();\n        new (a, b)[\"c\"]();\n        new (a, b[\"c\"])();\n        new (a, function() {\n            console.log(this === a);\n        })();\n        console.log(typeof (a, b).c);\n        console.log(typeof (a, b)[\"c\"]);\n    }\n    expect: {\n        var a = function() {\n            return this;\n        }();\n        function b() {\n            console.log(\"foo\");\n        }\n        b.c = function() {\n            console.log(this === b ? \"bar\" : \"baz\");\n        },\n        a,\n        b(),\n        a,\n        b.c(),\n        (a, b.c)(),\n        a,\n        b[\"c\"](),\n        (a, b[\"c\"])(),\n        a,\n        function() {\n            console.log(this === a);\n        }(),\n        a,\n        new b(),\n        a,\n        new b.c(),\n        a,\n        new b.c(),\n        a,\n        new b[\"c\"](),\n        a,\n        new b[\"c\"](),\n        a,\n        new function() {\n            console.log(this === a);\n        }(),\n        console.log((a, typeof b.c)),\n        console.log((a, typeof b[\"c\"]));\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"bar\",\n        \"baz\",\n        \"true\",\n        \"foo\",\n        \"baz\",\n        \"baz\",\n        \"baz\",\n        \"baz\",\n        \"false\",\n        \"function\",\n        \"function\",\n    ]\n}\n\ncall_drop_side_effect_free: {\n    options = {\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = function() {\n            return this;\n        }();\n        function b() {\n            console.log(\"foo\");\n        }\n        b.c = function() {\n            console.log(this === b ? \"bar\" : \"baz\");\n        };\n        (a, b)();\n        (a, b).c();\n        (a, b.c)();\n        (a, b)[\"c\"]();\n        (a, b[\"c\"])();\n        (a, function() {\n            console.log(this === a);\n        })();\n        new (a, b)();\n        new (a, b).c();\n        new (a, b.c)();\n        new (a, b)[\"c\"]();\n        new (a, b[\"c\"])();\n        new (a, function() {\n            console.log(this === a);\n        })();\n        console.log(typeof (a, b).c);\n        console.log(typeof (a, b)[\"c\"]);\n    }\n    expect: {\n        var a = function() {\n            return this;\n        }();\n        function b() {\n            console.log(\"foo\");\n        }\n        b.c = function() {\n            console.log(this === b ? \"bar\" : \"baz\");\n        },\n        b(),\n        b.c(),\n        (0, b.c)(),\n        b[\"c\"](),\n        (0, b[\"c\"])(),\n        function() {\n            console.log(this === a);\n        }(),\n        new b(),\n        new b.c(),\n        new b.c(),\n        new b[\"c\"](),\n        new b[\"c\"](),\n        new function() {\n            console.log(this === a);\n        }(),\n        console.log(typeof b.c),\n        console.log(typeof b[\"c\"]);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"bar\",\n        \"baz\",\n        \"true\",\n        \"foo\",\n        \"baz\",\n        \"baz\",\n        \"baz\",\n        \"baz\",\n        \"false\",\n        \"function\",\n        \"function\",\n    ]\n}\n\nmissing_link: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        sequences: true,\n    }\n    input: {\n        var a = 100;\n        a;\n        a++ + (0 ? 2 : 1);\n        console.log(a);\n    }\n    expect: {\n        var a = 100;\n        a,\n        a++ + (0, 1),\n        console.log(a);\n    }\n}\n\nmissing_link_drop_side_effect_free: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        var a = 100;\n        a;\n        a++ + (0 ? 2 : 1);\n        console.log(a);\n    }\n    expect: {\n        var a = 100;\n        a++,\n        console.log(a);\n    }\n}\n\nangularjs_chain: {\n    options = {\n        conditionals: true,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function nonComputedMember(left, right, context, create) {\n            var lhs = left();\n            if (create && create !== 1) {\n                if (lhs && lhs[right] == null) {\n                    lhs[right] = {};\n                }\n            }\n            var value = lhs != null ? lhs[right] : undefined;\n            if (context) {\n                return { context: lhs, name: right, value: value };\n            } else {\n                return value;\n            }\n        }\n    }\n    expect: {\n        function nonComputedMember(left, right, context, create) {\n            var lhs = left();\n            create && 1 !== create && lhs && null == lhs[right] && (lhs[right] = {});\n            var value = null != lhs ? lhs[right] : void 0;\n            return context ? {\n                context: lhs,\n                name: right,\n                value: value\n            } : value;\n        }\n    }\n}\n\nissue_3490_1: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        inline: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 42, c = \"FAIL\";\n        if ({\n            3: function() {\n                var a;\n                return (a && a.p) < this;\n            }(),\n        }) c = \"PASS\";\n        if (b) while (\"\" == typeof d);\n        console.log(c, b);\n    }\n    expect: {\n        var b = 42, c = \"FAIL\";\n        var a;\n        if (a && a.p, c = \"PASS\", b) while (\"\" == typeof d);\n        console.log(c, b);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nissue_3490_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var b = 42, c = \"FAIL\";\n        if ({\n            3: function() {\n                var a;\n                return (a && a.p) < this;\n            }(),\n        }) c = \"PASS\";\n        if (b) for (; \"\" == typeof d;);\n        console.log(c, b);\n    }\n    expect: {\n        var b = 42, c = \"FAIL\";\n        var a;\n        for (c = \"PASS\"; \"\" == typeof d;);\n        console.log(c, b);\n    }\n    expect_stdout: \"PASS 42\"\n}\n\nissue_3703: {\n    options = {\n        evaluate: true,\n        sequences: true,\n        unsafe: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        while ((a = \"PASS\", 0).foo = 0);\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        while (a = \"PASS\", (0).foo = 0);\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4079: {\n    options = {\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        try {\n            typeof (0, A);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            A;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/side_effects.js",
    "content": "accessor: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            get a() {},\n            set a(v){\n                this.b = 2;\n            },\n            b: 1\n        });\n    }\n    expect: {}\n}\n\nissue_2233_1: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        Array.isArray;\n        Boolean;\n        console.log;\n        Date;\n        decodeURI;\n        decodeURIComponent;\n        encodeURI;\n        encodeURIComponent;\n        Error.name;\n        escape;\n        eval;\n        EvalError;\n        Function.length;\n        isFinite;\n        isNaN;\n        JSON;\n        Math.random;\n        Number.isNaN;\n        parseFloat;\n        parseInt;\n        RegExp;\n        Object.defineProperty;\n        String.fromCharCode;\n        RangeError;\n        ReferenceError;\n        SyntaxError;\n        TypeError;\n        unescape;\n        URIError;\n    }\n    expect: {}\n    expect_stdout: true\n}\n\nglobal_timeout_and_interval_symbols: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        // These global symbols do not exist in the test sandbox\n        // and must be tested separately.\n        clearInterval;\n        clearTimeout;\n        setInterval;\n        setTimeout;\n    }\n    expect: {}\n}\n\nissue_2233_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var RegExp;\n        Array.isArray;\n        RegExp;\n        UndeclaredGlobal;\n        function foo() {\n            var Number;\n            AnotherUndeclaredGlobal;\n            Math.sin;\n            Number.isNaN;\n        }\n    }\n    expect: {\n        var RegExp;\n        UndeclaredGlobal;\n        function foo() {\n            AnotherUndeclaredGlobal;\n            (void 0).isNaN;\n        }\n    }\n}\n\nissue_2233_3: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_funcs: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        var RegExp;\n        Array.isArray;\n        RegExp;\n        UndeclaredGlobal;\n        function foo() {\n            var Number;\n            AnotherUndeclaredGlobal;\n            Math.sin;\n            Number.isNaN;\n        }\n    }\n    expect: {\n        UndeclaredGlobal;\n    }\n}\n\nglobal_fns: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        Boolean(1, 2);\n        decodeURI(1, 2);\n        decodeURIComponent(1, 2);\n        Date(1, 2);\n        encodeURI(1, 2);\n        encodeURIComponent(1, 2);\n        Error(1, 2);\n        escape(1, 2);\n        EvalError(1, 2);\n        isFinite(1, 2);\n        isNaN(1, 2);\n        Number(1, 2);\n        Object(1, 2);\n        parseFloat(1, 2);\n        parseInt(1, 2);\n        RangeError(1, 2);\n        ReferenceError(1, 2);\n        String(1, 2);\n        SyntaxError(1, 2);\n        TypeError(1, 2);\n        unescape(1, 2);\n        URIError(1, 2);\n        try {\n            Function(1, 2);\n        } catch (e) {\n            console.log(e.name);\n        }\n        try {\n            RegExp(1, 2);\n        } catch (e) {\n            console.log(e.name);\n        }\n        try {\n            Array(NaN);\n        } catch (e) {\n            console.log(e.name);\n        }\n    }\n    expect: {\n        try {\n            Function(1, 2);\n        } catch (e) {\n            console.log(e.name);\n        }\n        try {\n            RegExp(1, 2);\n        } catch (e) {\n            console.log(e.name);\n        }\n        try {\n            Array(NaN);\n        } catch (e) {\n            console.log(e.name);\n        }\n    }\n    expect_stdout: [\n        \"SyntaxError\",\n        \"SyntaxError\",\n        \"RangeError\",\n    ]\n}\n\nglobal_constructors: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        Map;\n        new Map(console.log(\"foo\"));\n        Set;\n        new Set(console.log(\"bar\"));\n        WeakMap;\n        new WeakMap(console.log(\"baz\"));\n        WeakSet;\n        new WeakSet(console.log(\"moo\"));\n    }\n    expect: {\n        console.log(\"foo\");\n        console.log(\"bar\");\n        console.log(\"baz\");\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"moo\",\n    ]\n    node_version: \">=0.12\"\n}\n\nunsafe_builtin_1: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        (!w).constructor(x);\n        Math.abs(y);\n        [ 1, 2, z ].valueOf();\n    }\n    expect: {\n        w, x;\n        y;\n        z;\n    }\n}\n\nunsafe_builtin_2: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        var o = {};\n        constructor.call(o, 42);\n        __defineGetter__.call(o, \"foo\", function() {\n            return o.p;\n        });\n        __defineSetter__.call(o, void 0, function(a) {\n            o.p = a;\n        });\n        console.log(typeof o, o.undefined = \"PASS\", o.foo);\n    }\n    expect: {\n        var o = {};\n        constructor.call(o, 42);\n        __defineGetter__.call(o, \"foo\", function() {\n            return o.p;\n        });\n        __defineSetter__.call(o, void 0, function(a) {\n            o.p = a;\n        });\n        console.log(typeof o, o.undefined = \"PASS\", o.foo);\n    }\n    expect_stdout: \"object PASS PASS\"\n}\n\nunsafe_builtin_3: {\n    options = {\n        conditionals: true,\n        side_effects: true,\n        toplevel: true,\n        unsafe: true,\n    }\n    input: {\n        var o = {};\n        if (42 < Math.random())\n            o.p = \"FAIL\";\n        else\n            o.p = \"PASS\";\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {};\n        o.p = 42 < Math.random() ? \"FAIL\" : \"PASS\";\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: \"p PASS\"\n}\n\nunsafe_string_replace: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        \"foo\".replace(\"f\", function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect: {\n        \"foo\".replace(\"f\", function() {\n            console.log(\"PASS\");\n        });\n    }\n    expect_stdout: \"PASS\"\n}\n\nunsafe_Object_call: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        var o = {\n            f: function(a) {\n                console.log(a ? this.p : \"FAIL 1\");\n            },\n            p: \"FAIL 2\",\n        }, p = \"PASS\";\n        Object(o.f)(42);\n    }\n    expect: {\n        var o = {\n            f: function(a) {\n                console.log(a ? this.p : \"FAIL 1\");\n            },\n            p: \"FAIL 2\",\n        }, p = \"PASS\";\n        (0, o.f)(42);\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_value: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        (1, [2, foo()], 3, {a:1, b:bar()});\n    }\n    expect: {\n        foo(), bar();\n    }\n}\n\noperator_in: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            \"foo\" in true;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            0 in true;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3983_1: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            g && g();\n        }\n        f();\n        function g() {\n            0 ? a : 0;\n        }\n        var b = a;\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3983_2: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f() {\n            g && g();\n        }\n        f();\n        function g() {\n            0 ? a : 0;\n        }\n        var b = a;\n        console.log(a);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4008: {\n    options = {\n        collapse_vars: true,\n        evaluate: true,\n        inline: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\";\n        function f(b, b) {\n            console.log(b);\n        }\n        f && f(a && a[a]);\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        function f(b, b) {\n            console.log(b);\n        }\n        f(a[a]);\n        console.log(a);\n    }\n    expect_stdout: [\n        \"undefined\",\n        \"PASS\",\n    ]\n}\n\ntrim_new: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        new function(a) {\n            console.log(a);\n        }(\"PASS\");\n    }\n    expect: {\n        (function(a) {\n            console.log(a);\n        })(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4325: {\n    options = {\n        keep_fargs: false,\n        passes: 2,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        (function f() {\n            (function(b, c) {\n                try {\n                    c.p = 0;\n                } catch (e) {\n                    console.log(\"PASS\");\n                    return b;\n                }\n                c;\n            })(f++);\n        })();\n    }\n    expect: {\n        (function() {\n            (function(c) {\n                try {\n                    c.p = 0;\n                } catch (e) {\n                    console.log(\"PASS\");\n                    return;\n                }\n            })(void 0);\n        })();\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4366_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            p: 42,\n            get p() {},\n            q: console.log(\"PASS\"),\n        });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4366_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            set p(v) {},\n            q: console.log(\"PASS\"),\n            p: 42,\n        });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4668: {\n    options = {\n        conditionals: true,\n        keep_fargs: false,\n        keep_fnames: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b, c;\n            function g() {\n                return a = 0 + a, !d || (a = 0);\n            }\n            c = g();\n        }\n        console.log(f());\n        var d = 0;\n    }\n    expect: {\n        console.log(function f() {\n            (function g() {\n                0;\n            })();\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\ndrop_side_effect_free_call: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        function f(a) {\n            return \"PA\" + a;\n        }\n        f(42);\n        console.log(f(\"SS\"));\n    }\n    expect: {\n        function f(a) {\n            return \"PA\" + a;\n        }\n        console.log(f(\"SS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4730_1: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var a;\n        console.log(\"PASS\") + (a && a[a.p]);\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\"),\n        a && a[a.p];\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4730_2: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var a;\n        !console.log(\"PASS\") || a && a[a.p];\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\") && a && a[a.p];\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_4751: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            },\n        };\n        o && o.p;\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            },\n        };\n        o && o.p;\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_instanceof: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        42 instanceof function() {};\n        console.log(\"PASS\");\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_instanceof_reference: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        function f() {}\n        42 instanceof f;\n        console.log(\"PASS\");\n    }\n    expect: {\n        function f() {}\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nretain_instanceof: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            42 instanceof \"foo\";\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            0 instanceof \"foo\";\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_access: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {};\n        o.p;\n        try {\n            (function() {\n                o.q;\n            })();\n            console.log(\"PASS\");\n        } catch (e) {\n            console.log(\"FAIL\");\n        }\n    }\n    expect: {\n        var o = {};\n        o.p;\n        try {\n            console.log(\"PASS\");\n        } catch (e) {\n            console.log(\"FAIL\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nkeep_access: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {};\n        o.p;\n        o = null;\n        try {\n            (function() {\n                o.q;\n            })();\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var o = {};\n        o.p;\n        o = null;\n        try {\n            (function() {\n                o.q;\n            })();\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nkeep_access_after_call: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var o = {};\n        o.p;\n        o.q;\n        f();\n        try {\n            o.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        function f() {\n            o = null;\n        }\n    }\n    expect: {\n        var o = {};\n        o.p;\n        f();\n        try {\n            o.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n        function f() {\n            o = null;\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5860_drop_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a.p;\n        var a;\n        a.q;\n        console.log(\"PASS\");\n    }\n    expect: {\n        var a = {};\n        a.p;\n        var a;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5860_drop_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        a = {};\n        a.p;\n        var a;\n        a.q;\n        console.log(\"PASS\");\n    }\n    expect: {\n        a = {};\n        a.p;\n        var a;\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5860_keep_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a.p;\n        a.q;\n        var a = null;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a.p;\n        var a = null;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5860_keep_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        a = {};\n        a.p;\n        a.q;\n        var a = null;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        a = {};\n        a.p;\n        var a = null;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5860_keep_3: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a.p;\n        a.q;\n        a = null;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a.p;\n        a = null;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5912_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a = a.p;\n        console || a.q;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a = a.p;\n        console || a.q;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5912_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a = a.p;\n        if (!console) a.q;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a = a.p;\n        if (!console) a.q;\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5912_3: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a = a.p;\n        try {\n            console;\n        } catch (e) {\n            a.q;\n        }\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a = a.p;\n        try {\n            console;\n        } catch (e) {\n            a.q;\n        }\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/spreads.js",
    "content": "decimal: {\n    input: {\n        console.log({... 0.42});\n    }\n    expect_exact: \"console.log({....42});\"\n    expect_stdout: \"{}\"\n    node_version: \">=8.3.0\"\n}\n\ncollapse_vars_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a;\n        [ ...a = \"PASS\", \"PASS\" ].slice();\n        console.log(a);\n    }\n    expect: {\n        var a;\n        [ ...a = \"PASS\", \"PASS\" ].slice();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            [ ...42, \"PASS\" ].slice();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            a = \"PASS\";\n            [ ...42, \"PASS\" ].slice();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        try {\n            [ ...(a = \"PASS\", 42), \"PASS\" ].slice();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = \"FAIL\";\n        try {\n            [ ...(a = \"PASS\", 42), \"PASS\" ].slice();\n        } catch (e) {\n            console.log(a);\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ncollapse_vars_4: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a;\n        }(...[ \"PASS\", \"FAIL\" ]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a;\n        }(...[ \"PASS\", \"FAIL\" ]));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nconditionals_farg_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        function log(msg) {\n            console.log(msg);\n        }\n        var a = 42, b = [ \"PASS\" ], c = [ \"FAIL\" ];\n        a ? log(...b) : log(...c);\n    }\n    expect: {\n        function log(msg) {\n            console.log(msg);\n        }\n        var a = 42, b = [ \"PASS\" ], c = [ \"FAIL\" ];\n        log(...a ? b : c);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nconditionals_farg_2: {\n    options = {\n        conditionals: true,\n        pure_getters: \"strict\",\n        reduce_vars: true,\n    }\n    input: {\n        var log = console.log;\n        (function(a) {\n            return a.length ? log(...a) : log(\"FAIL\");\n        })([ \"PASS\" ]);\n    }\n    expect: {\n        var log = console.log;\n        (function(a) {\n            return a.length ? log(...a) : log(\"FAIL\");\n        })([ \"PASS\" ]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndont_inline: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a;\n        }(...[ \"PASS\", \"FAIL\" ]));\n    }\n    expect: {\n        console.log(function(a) {\n            return a;\n        }(...[ \"PASS\", \"FAIL\" ]));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndo_inline_1: {\n    options = {\n        inline: true,\n        spreads: true,\n    }\n    input: {\n        console.log(function(a) {\n            return a;\n        }(...[ \"PASS\", \"FAIL\" ]));\n    }\n    expect: {\n        console.log((\"FAIL\", \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndo_inline_2: {\n    options = {\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        (function() {\n            (function() {\n                console.log(\"PASS\");\n            })(...\"\");\n        })();\n    }\n    expect: {\n        [] = [ ...\"\" ],\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndo_inline_3: {\n    options = {\n        if_return: true,\n        inline: true,\n    }\n    input: {\n        (function() {\n            (function() {\n                while (console.log(\"PASS\"));\n            })(...\"\");\n        })();\n    }\n    expect: {\n        var [] = [ ...\"\" ];\n        while (console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_empty_call_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function() {})(...null);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [ ...null ];\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\ndrop_empty_call_2: {\n    options = {\n        side_effects: true,\n        spreads: true,\n    }\n    input: {\n        (function() {})(...[ console.log(\"PASS\") ]);\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nconvert_hole_array: {\n    options = {\n        spreads: true,\n    }\n    input: {\n        [ ...[ \"PASS\", , 42 ] ].forEach(function(a) {\n            console.log(a);\n        });\n    }\n    expect: {\n        [ \"PASS\", void 0, 42 ].forEach(function(a) {\n            console.log(a);\n        });\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n        \"42\",\n    ]\n    node_version: \">=6\"\n}\n\nconvert_hole_call: {\n    options = {\n        spreads: true,\n    }\n    input: {\n        console.log(...[ \"PASS\", , 42 ]);\n    }\n    expect: {\n        console.log(\"PASS\", void 0, 42);\n    }\n    expect_stdout: \"PASS undefined 42\"\n    node_version: \">=6\"\n}\n\nkeep_property_access: {\n    options = {\n        properties: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(function() {\n            return [ ...\"foo\" ][0];\n        }());\n    }\n    expect: {\n        console.log(function() {\n            return [ ...\"foo\" ][0];\n        }());\n    }\n    expect_stdout: \"f\"\n    node_version: \">=6\"\n}\n\nkeep_fargs: {\n    options = {\n        keep_fargs: false,\n        unused: true,\n    }\n    input: {\n        var a = [ \"PASS\" ];\n        (function(b, c) {\n            console.log(c);\n        })(console, ...a);\n    }\n    expect: {\n        var a = [ \"PASS\" ];\n        (function(b, c) {\n            console.log(c);\n        })(console, ...a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_vars_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function(b, c) {\n            return c ? \"PASS\" : \"FAIL\";\n        }(...\"foo\"));\n    }\n    expect: {\n        console.log(function(b, c) {\n            return c ? \"PASS\" : \"FAIL\";\n        }(...\"foo\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_vars_2: {\n    options = {\n        conditionals: true,\n        evaluate: true,\n        reduce_vars: true,\n    }\n    input: {\n        console.log(function(b, c) {\n            return c ? \"PASS\" : \"FAIL\";\n        }(...\"foo\"));\n    }\n    expect: {\n        console.log(function(b, c) {\n            return c ? \"PASS\" : \"FAIL\";\n        }(...\"foo\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nreduce_vars_3: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function f() {}\n        function g() {\n            return (a => a)(...[ f ]);\n        }\n        console.log(g() === g() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        function f() {}\n        function g() {\n            return (a => a)(...[ f ]);\n        }\n        console.log(g() === g() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nconvert_setter: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            ...{\n                set PASS(v) {},\n            },\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            PASS: void 0,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: \"PASS undefined\"\n    node_version: \">=8.3.0\"\n}\n\nkeep_getter_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            ...{\n                get p() {\n                    console.log(\"PASS\");\n                },\n            },\n            get q() {\n                console.log(\"FAIL\");\n            },\n        });\n    }\n    expect: {\n        ({\n            ...{\n                get p() {\n                    console.log(\"PASS\");\n                },\n            },\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nkeep_getter_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            ...(console.log(\"foo\"), {\n                get p() {\n                    console.log(\"bar\");\n                },\n            }),\n        });\n    }\n    expect: {\n        ({\n            ...(console.log(\"foo\"), {\n                get p() {\n                    console.log(\"bar\");\n                },\n            }),\n        });\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nkeep_getter_3: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            ...function() {\n                return {\n                    get p() {\n                        console.log(\"PASS\");\n                    },\n                };\n            }(),\n        });\n    }\n    expect: {\n        ({\n            ...function() {\n                return {\n                    get p() {\n                        console.log(\"PASS\");\n                    },\n                };\n            }(),\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nkeep_getter_4: {\n    options = {\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            },\n        };\n        ({\n            q: o,\n            ...o,\n        });\n    }\n    expect: {\n        var o = {\n            get p() {\n                console.log(\"PASS\");\n            },\n        };\n        ({\n            ...o,\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nkeep_accessor: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            ...{\n                get p() {\n                    console.log(\"GET\");\n                    return this.r;\n                },\n                set q(v) {\n                    console.log(\"SET\", v);\n                },\n                r: 42,\n            },\n            r: null,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            ...{\n                get p() {\n                    console.log(\"GET\");\n                    return this.r;\n                },\n                set q(v) {\n                    console.log(\"SET\", v);\n                },\n                r: 42,\n            },\n            r: null,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"GET\",\n        \"p 42\",\n        \"q undefined\",\n        \"r null\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nobject_key_order_1: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            ...{},\n            a: 1,\n            b: 2,\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            a: (1, 3),\n            b: 2,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"a 3\",\n        \"b 2\",\n    ]\n    node_version: \">=8.3.0 <=10\"\n}\n\nobject_key_order_2: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            ...{},\n            b: 2,\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            a: (1, 3),\n            b: 2,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"a 3\",\n        \"b 2\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nobject_key_order_3: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n            ...{},\n            a: 3,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            a: (1, 3),\n            b: 2,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"a 3\",\n        \"b 2\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nobject_key_order_4: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            a: 1,\n            b: 2,\n            a: 3,\n            ...{},\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            a: (1, 3),\n            b: 2,\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"a 3\",\n        \"b 2\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nobject_spread_array: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            ...[ \"foo\", \"bar\" ],\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            ...[ \"foo\", \"bar\" ],\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"0 foo\",\n        \"1 bar\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nobject_spread_string: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            ...\"foo\",\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            ...\"foo\",\n        };\n        for (var k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"0 f\",\n        \"1 o\",\n        \"2 o\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nunused_var_side_effects: {\n    options = {\n        unused: true,\n    }\n    input: {\n        (function f(a) {\n            var b = {\n                ...a,\n            };\n        })({\n            get p() {\n                console.log(\"PASS\");\n            },\n        });\n    }\n    expect: {\n        (function(a) {\n            ({\n                ...a,\n            });\n        })({\n            get p() {\n                console.log(\"PASS\");\n            },\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nunsafe_join_1: {\n    options = {\n        unsafe: true,\n    }\n    input: {\n        console.log([ ...\"foo\" ].join());\n    }\n    expect: {\n        console.log([ ...\"foo\" ].join());\n    }\n    expect_stdout: \"f,o,o\"\n    node_version: \">=6\"\n}\n\nunsafe_join_2: {\n    options = {\n        evaluate: true,\n        unsafe: true,\n    }\n    input: {\n        console.log([ \"foo\", ...\"bar\" ].join(\"\"));\n    }\n    expect: {\n        console.log([ \"foo\", ...\"bar\" ].join(\"\"));\n    }\n    expect_stdout: \"foobar\"\n    node_version: \">=6\"\n}\n\nunsafe_join_3: {\n    options = {\n        unsafe: true,\n    }\n    input: {\n        try {\n            [].join(...console);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [].join(...console);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4329: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        console.log({\n            ...{\n                get 0() {\n                    return \"FAIL\";\n                },\n                ...{\n                    0: \"PASS\",\n                },\n            },\n        }[0]);\n    }\n    expect: {\n        console.log({\n            ...{\n                get 0() {\n                    return \"FAIL\";\n                },\n                [0]: \"PASS\",\n            },\n        }[0]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_4331: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n    }\n    input: {\n        var a = \"PASS\", b;\n        console,\n        b = a;\n        (function() {\n            a++;\n        })(...a);\n        console.log(b);\n    }\n    expect: {\n        var a = \"PASS\", b;\n        console;\n        (function() {\n            a++;\n        })(...b = a);\n        console.log(b);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4342: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        try {\n            new function() {}(...42);\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            [ ...42 ];\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_4345: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        console.log({\n            ...{\n                get 42() {\n                    return \"FAIL\";\n                },\n                ...{},\n                42: \"PASS\",\n            },\n        }[42]);\n    }\n    expect: {\n        console.log({\n            ...{\n                get 42() {\n                    return \"FAIL\";\n                },\n                [42]: \"PASS\",\n            },\n        }[42]);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_4361: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = console.log(\"foo\");\n            console;\n            var b = {\n                ...a,\n            };\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a = console.log(\"foo\");\n            console;\n            ({\n                ...a,\n            });\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nissue_4363: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        ({\n            ...{\n                set [console.log(\"PASS\")](v) {},\n            },\n        });\n    }\n    expect: {\n        ({\n            [console.log(\"PASS\")]: void 0,\n        });\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_4556: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var a = \"\" + [ a++ ];\n            var b = [ ...a ];\n        }());\n    }\n    expect: {\n        console.log(function() {\n            var a;\n        }());\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=6\"\n}\n\nissue_4614: {\n    options = {\n        pure_getters: \"strict\",\n        side_effects: true,\n    }\n    input: {\n        try {\n            (function(...[]) {\n                var arguments;\n                arguments[0];\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            (function(...[]) {\n                var arguments;\n                arguments[0];\n            })();\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: true\n    node_version: \">=6\"\n}\n\nissue_4849: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        while (function() {\n            while (!console);\n        }(new function(a) {\n            console.log(typeof { ...a });\n        }(function() {})));\n    }\n    expect: {\n        while (function() {\n            while (!console);\n        }(function(a) {\n            console.log(typeof { ...function() {} });\n        }()));\n    }\n    expect_stdout: \"object\"\n    node_version: \">=8.3.0\"\n}\n\nissue_4882_1: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            p: \"PASS\",\n            ... {\n                __proto__: {\n                    p: \"FAIL 1\",\n                    q: \"FAIL 2\",\n                },\n            },\n        };\n        console.log(o.p);\n        console.log(o.q);\n    }\n    expect: {\n        var o = {\n            p: \"PASS\",\n        };\n        console.log(o.p);\n        console.log(o.q);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nissue_4882_2: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        console.log(null == Object.getPrototypeOf({\n            ... {\n                __proto__: (console.log(42), null),\n            },\n        }) ? \"FAIL\" : \"PASS\");\n    }\n    expect: {\n        console.log(null == Object.getPrototypeOf({\n            ... {\n                __proto__: (console.log(42), null),\n            },\n        }) ? \"FAIL\" : \"PASS\");\n    }\n    expect_stdout: [\n        \"42\",\n        \"PASS\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nissue_4882_3: {\n    options = {\n        objects: true,\n        spreads: true,\n    }\n    input: {\n        var o = {\n            __proto__: { p: 42 },\n            ... {\n                set __proto__(v) {},\n            },\n        };\n        console.log(o.__proto__ === Object.getPrototypeOf(o) ? \"FAIL\" : \"PASS\");\n        console.log(o.p);\n    }\n    expect: {\n        var o = {\n            __proto__: { p: 42 },\n            [\"__proto__\"]: void 0,\n        };\n        console.log(o.__proto__ === Object.getPrototypeOf(o) ? \"FAIL\" : \"PASS\");\n        console.log(o.p);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=8.3.0\"\n}\n\nissue_5006: {\n    options = {\n        arguments: true,\n    }\n    input: {\n        console.log(function(b, c) {\n            c = \"FAIL 2\";\n            return arguments[1];\n        }(...[], \"FAIL 1\") || \"PASS\");\n    }\n    expect: {\n        console.log(function(b, c) {\n            c = \"FAIL 2\";\n            return arguments[1];\n        }(...[], \"FAIL 1\") || \"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5382: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        ({\n            f() {\n                ({ ...this });\n            },\n            get p() {\n                console.log(\"PASS\");\n            },\n        }).f();\n    }\n    expect: {\n        ({\n            f() {\n                ({ ...this });\n            },\n            get p() {\n                console.log(\"PASS\");\n            },\n        }).f();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=8.3.0\"\n}\n\nissue_5602: {\n    options = {\n        collapse_vars: true,\n        conditionals: true,\n        evaluate: true,\n        if_return: true,\n        inline: true,\n        passes: 2,\n        sequences: true,\n        spreads: true,\n        unused: true,\n    }\n    input: {\n        (function() {\n            try {\n                var b = function(c) {\n                    if (c)\n                        return FAIL;\n                    var d = 42;\n                }(...[ null, A = 0 ]);\n            } catch (e) {\n                b();\n            }\n        })();\n        console.log(A);\n    }\n    expect: {\n        (function() {\n            try {\n                var b = void (A = 0);\n            } catch (e) {\n                b();\n            }\n        })(),\n        console.log(A);\n    }\n    expect_stdout: \"0\"\n    expect_warnings: [\n        \"INFO: Dropping unused variable d [test/compress/spreads.js:6,24]\",\n        \"INFO: Collapsing c [test/compress/spreads.js:4,24]\",\n        \"INFO: Dropping unused variable c [test/compress/spreads.js:3,33]\",\n        \"INFO: pass 0: last_count: Infinity, count: 27\",\n        \"WARN: Condition always false [test/compress/spreads.js:4,20]\",\n        \"INFO: Collapsing null [test/compress/spreads.js:7,23]\",\n        \"INFO: Collapsing 0 [test/compress/spreads.js:3,24]\",\n        \"INFO: pass 1: last_count: 27, count: 22\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5850: {\n    options = {\n        evaluate: true,\n        join_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = [ ...\"FAIL\" ];\n        a[0] = \"P\";\n        a[2] = a[3] = \"S\";\n        console.log(a.join(\"\"));\n    }\n    expect: {\n        var a = [ ...\"FAIL\" ];\n        a[0] = \"P\";\n        a[2] = a[3] = \"S\";\n        console.log(a.join(\"\"));\n    }\n    node_version: \">=6\"\n}\n"
  },
  {
    "path": "test/compress/string-literal.js",
    "content": "octal_escape_sequence: {\n    input: {\n        var boundaries = \"\\0\\7\\00\\07\\70\\77\\000\\077\\300\\377\";\n        var border_check = \"\\400\\700\\0000\\3000\";\n    }\n    expect: {\n        var boundaries = \"\\x00\\x07\\x00\\x07\\x38\\x3f\\x00\\x3f\\xc0\\xff\";\n        var border_check = \"\\x20\\x30\\x38\\x30\\x00\\x30\\xc0\\x30\";\n    }\n}\n\nissue_1929: {\n    input: {\n        function f(s) {\n            return s.split(/[\\\\/]/);\n        }\n        console.log(JSON.stringify(f(\"A/B\\\\C\\\\D/E\\\\F\")));\n    }\n    expect: {\n        function f(s) {\n            return s.split(/[\\\\/]/);\n        }\n        console.log(JSON.stringify(f(\"A/B\\\\C\\\\D/E\\\\F\")));\n    }\n    expect_stdout: '[\"A\",\"B\",\"C\",\"D\",\"E\",\"F\"]'\n}\n"
  },
  {
    "path": "test/compress/switches.js",
    "content": "constant_switch_1: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        switch (1+1) {\n          case 1: foo(); break;\n          case 1+1: bar(); break;\n          case 1+1+1: baz(); break;\n        }\n    }\n    expect: {\n        bar();\n    }\n}\n\nconstant_switch_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        switch (1) {\n          case 1: foo();\n          case 1+1: bar(); break;\n          case 1+1+1: baz();\n        }\n    }\n    expect: {\n        foo();\n        bar();\n    }\n}\n\nconstant_switch_3: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        switch (10) {\n          case 1: foo();\n          case 1+1: bar(); break;\n          case 1+1+1: baz();\n          default:\n            def();\n        }\n    }\n    expect: {\n        def();\n    }\n}\n\nconstant_switch_4: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        switch (2) {\n          case 1:\n            x();\n            if (foo) break;\n            y();\n            break;\n          case 1+1:\n            bar();\n          default:\n            def();\n        }\n    }\n    expect: {\n        bar();\n        def();\n    }\n}\n\nconstant_switch_5: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        switch (1) {\n          case 1:\n            x();\n            if (foo) break;\n            y();\n            break;\n          case 1+1:\n            bar();\n          default:\n            def();\n        }\n    }\n    expect: {\n        // the break inside the if ruins our job\n        // we can still get rid of irrelevant cases.\n        switch (1) {\n          default:\n            x();\n            if (foo) break;\n            y();\n        }\n        // XXX: we could optimize this better by inventing an outer\n        // labeled block, but that's kinda tricky.\n    }\n}\n\nconstant_switch_6: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        OUT: {\n            foo();\n            switch (1) {\n              case 1:\n                x();\n                if (foo) break OUT;\n                y();\n              case 1+1:\n                bar();\n                break;\n              default:\n                def();\n            }\n        }\n    }\n    expect: {\n        OUT: {\n            foo();\n            x();\n            if (foo) break OUT;\n            y();\n            bar();\n        }\n    }\n}\n\nconstant_switch_7: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        OUT: {\n            foo();\n            switch (1) {\n              case 1:\n                x();\n                if (foo) break OUT;\n                for (var x = 0; x < 10; x++) {\n                    if (x > 5) break; // this break refers to the for, not to the switch; thus it\n                                      // shouldn't ruin our optimization\n                    console.log(x);\n                }\n                y();\n              case 1+1:\n                bar();\n                break;\n              default:\n                def();\n            }\n        }\n    }\n    expect: {\n        OUT: {\n            foo();\n            x();\n            if (foo) break OUT;\n            for (var x = 0; x < 10; x++) {\n                if (x > 5) break;\n                console.log(x);\n            }\n            y();\n            bar();\n        }\n    }\n}\n\nconstant_switch_8: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        OUT: switch (1) {\n          case 1:\n            x();\n            for (;;) break OUT;\n            y();\n            break;\n          case 1+1:\n            bar();\n          default:\n            def();\n        }\n    }\n    expect: {\n        OUT: {\n            x();\n            for (;;) break OUT;\n            y();\n        }\n    }\n}\n\nconstant_switch_9: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        OUT: switch (1) {\n          case 1:\n            x();\n            for (;;) if (foo) break OUT;\n            y();\n          case 1+1:\n            bar();\n          default:\n            def();\n        }\n    }\n    expect: {\n        OUT: {\n            x();\n            for (;;) if (foo) break OUT;\n            y();\n            bar();\n            def();\n        }\n    }\n}\n\ndrop_default_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case \"bar\": baz();\n          default:\n        }\n    }\n    expect: {\n        switch (foo) {\n          case \"bar\": baz();\n        }\n    }\n}\n\ndrop_default_2: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case \"bar\": baz(); break;\n          default:\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case \"bar\": baz();\n        }\n    }\n}\n\ndrop_default_3: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        function f() {\n            console.log(\"PASS\");\n            return 42;\n        }\n        switch (42) {\n          case f():\n            break;\n          case void console.log(\"FAIL\"):\n          default:\n        }\n    }\n    expect: {\n        function f() {\n            console.log(\"PASS\");\n            return 42;\n        }\n        switch (42) {\n          case f():\n          case void console.log(\"FAIL\"):\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nkeep_default: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case \"bar\": baz();\n          default:\n            something();\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case \"bar\": baz();\n          default:\n            something();\n        }\n    }\n}\n\nissue_1663: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        function f() {\n            switch (1) {\n              case 1:\n                b = a++;\n                return ++b;\n              default:\n                var b;\n            }\n        }\n        f();\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        function f() {\n            var b;\n            b = a++;\n            return ++b;\n        }\n        f();\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\ndrop_case_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case \"bar\": baz(); break;\n          case \"moo\":\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case \"bar\": baz();\n        }\n    }\n}\n\ndrop_case_2: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case \"bar\":\n            bar();\n            break;\n          default:\n          case \"moo\":\n            moo();\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case \"bar\":\n            bar();\n            break;\n          default:\n            moo();\n        }\n    }\n}\n\ndrop_case_3: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var c = \"PASS\";\n        switch ({}.p) {\n          default:\n          case void 0:\n            break;\n          case c = \"FAIL\":\n        }\n        console.log(c);\n    }\n    expect: {\n        var c = \"PASS\";\n        switch ({}.p) {\n          default:\n          case void 0:\n          case c = \"FAIL\":\n        }\n        console.log(c);\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_case_4: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (0) {\n          case [ a, typeof b ]:\n          default:\n            var a;\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        switch (0) {\n          case [ a, typeof b ]:\n            var a;\n        }\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_case_5: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (42) {\n          case void console.log(\"PASS 1\"):\n            console.log(\"FAIL 1\");\n          case 42:\n          case console.log(\"FAIL 2\"):\n            console.log(\"PASS 2\");\n        }\n    }\n    expect: {\n        switch (42) {\n          default:\n            void console.log(\"PASS 1\");\n            console.log(\"PASS 2\");\n        }\n    }\n    expect_stdout: [\n        \"PASS 1\",\n        \"PASS 2\",\n    ]\n}\n\ndrop_case_6: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (console.log(\"PASS 1\"), 2) {\n          case 0:\n            console.log(\"FAIL 1\");\n          case (console.log(\"PASS 2\"), 1):\n            console.log(\"FAIL 2\");\n        }\n    }\n    expect: {\n        switch (console.log(\"PASS 1\"), 2) {\n          case (console.log(\"PASS 2\"), 1):\n        }\n    }\n    expect_stdout: [\n        \"PASS 1\",\n        \"PASS 2\",\n    ]\n}\n\ndrop_case_7: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (2) {\n          case 0:\n            console.log(\"FAIL 1\");\n          case (console.log(\"PASS 1\"), 1):\n            console.log(\"FAIL 2\");\n          case 2:\n            console.log(\"PASS 2\");\n        }\n    }\n    expect: {\n        switch (2) {\n          default:\n            console.log(\"PASS 1\"), 1;\n            console.log(\"PASS 2\");\n        }\n    }\n    expect_stdout: [\n        \"PASS 1\",\n        \"PASS 2\",\n    ]\n}\n\ndrop_case_8: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        function log(msg) {\n            console.log(msg);\n            return msg;\n        }\n        switch (log(\"foo\")) {\n          case \"bar\":\n            log(\"moo\");\n            break;\n          case log(\"baz\"):\n            log(\"moo\");\n            break;\n          default:\n            log(\"moo\");\n        }\n    }\n    expect: {\n        function log(msg) {\n            console.log(msg);\n            return msg;\n        }\n        switch (log(\"foo\")) {\n          case \"bar\":\n          case log(\"baz\"):\n          default:\n            log(\"moo\");\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"moo\",\n    ]\n}\n\ndrop_case_9: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        function log(msg) {\n            console.log(msg);\n            return msg;\n        }\n        switch (log(\"foo\")) {\n          case log(\"bar\"):\n            log(\"moo\");\n            break;\n          case \"baz\":\n            log(\"moo\");\n            break;\n          default:\n            log(\"moo\");\n        }\n    }\n    expect: {\n        function log(msg) {\n            console.log(msg);\n            return msg;\n        }\n        switch (log(\"foo\")) {\n          default:\n            log(\"bar\");\n            log(\"moo\");\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n    ]\n}\n\nkeep_case_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case \"bar\": baz(); break;\n          case moo:\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case \"bar\": baz(); break;\n          case moo:\n        }\n    }\n}\n\nkeep_case_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (\"foo\") {\n          case console.log(\"bar\"):\n          case console.log(\"baz\"), \"moo\":\n        }\n    }\n    expect: {\n        switch (\"foo\") {\n          case console.log(\"bar\"):\n          case console.log(\"baz\"), \"moo\":\n        }\n    }\n    expect_stdout: [\n        \"bar\",\n        \"baz\",\n    ]\n}\n\nkeep_case_3: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a;\n        switch (void console.log(\"PASS\")) {\n          case a:\n          case console.log(\"FAIL\"), 42:\n        }\n    }\n    expect: {\n        var a;\n        switch (void console.log(\"PASS\")) {\n          case a:\n          case console.log(\"FAIL\"), 42:\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nkeep_case_4: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a;\n        switch (void console.log(\"PASS\")) {\n          case a:\n          case void console.log(\"FAIL\"):\n        }\n    }\n    expect: {\n        var a;\n        switch (void console.log(\"PASS\")) {\n          case a:\n          case void console.log(\"FAIL\"):\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_376: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (true) {\n          case boolCondition:\n            console.log(1);\n            break;\n          case false:\n            console.log(2);\n            break;\n        }\n    }\n    expect: {\n        switch (true) {\n          case boolCondition:\n            console.log(1);\n        }\n    }\n}\n\nissue_441_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case bar:\n            qux();\n            break;\n          case baz:\n            qux();\n            break;\n          default:\n            qux();\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case bar:\n          case baz:\n          default:\n            qux();\n        }\n    }\n}\n\nissue_441_2: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          case bar:\n            // TODO: Fold into the case below\n            qux();\n            break;\n          case fall:\n          case baz:\n            qux();\n            break;\n          default:\n            qux();\n            break;\n        }\n    }\n    expect: {\n        switch (foo) {\n          case bar:\n            qux();\n            break;\n          case fall:\n          case baz:\n          default:\n            qux();\n        }\n    }\n}\n\nissue_1674: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        switch (0) {\n          default:\n            console.log(\"FAIL\");\n            break;\n          case 0:\n            console.log(\"PASS\");\n            break;\n        }\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1679: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        function f() {\n            switch (--b) {\n              default:\n              case !function x() {}:\n                break;\n              case b--:\n                switch (0) {\n                  default:\n                  case a--:\n                }\n                break;\n              case (a++):\n                break;\n            }\n        }\n        f();\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        function f() {\n            switch (--b) {\n              default:\n              case !function x() {}:\n                break;\n              case b--:\n                switch (0) {\n                  default:\n                  case a--:\n                }\n                break;\n              case (a++):\n            }\n        }\n        f();\n        console.log(a, b);\n    }\n    expect_stdout: \"99 8\"\n}\n\nissue_1680_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        function f(x) {\n            console.log(x);\n            return x + 1;\n        }\n        switch (2) {\n          case f(0):\n          case f(1):\n            f(2);\n          case 2:\n          case f(3):\n          case f(4):\n            f(5);\n        }\n    }\n    expect: {\n        function f(x) {\n            console.log(x);\n            return x + 1;\n        }\n        switch (2) {\n          case f(0):\n          case f(1):\n            f(2);\n          default:\n            f(5);\n        }\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n        \"2\",\n        \"5\",\n    ]\n}\n\nissue_1680_2: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var a = 100, b = 10;\n        switch (b) {\n          case a--:\n            break;\n          case b:\n            var c;\n            break;\n          case a:\n            break;\n          case a--:\n            break;\n        }\n        console.log(a, b);\n    }\n    expect: {\n        var a = 100, b = 10;\n        switch (b) {\n          case a--:\n            break;\n          case b:\n            var c;\n            break;\n          case a:\n          case a--:\n        }\n        console.log(a, b);\n    }\n    expect_stdout: true\n}\n\nissue_1690_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (console.log(\"PASS\")) {}\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_1690_2: {\n    options = {\n        dead_code: false,\n        switches: true,\n    }\n    input: {\n        switch (console.log(\"PASS\")) {}\n    }\n    expect: {\n        switch (console.log(\"PASS\")) {}\n    }\n    expect_stdout: \"PASS\"\n}\n\nif_switch_typeof: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        if (a) switch(typeof b) {}\n    }\n    expect: {\n        a;\n    }\n}\n\nissue_1698: {\n    options = {\n        side_effects: true,\n        switches: true,\n    }\n    input: {\n        var a = 1;\n        !function() {\n            switch (a++) {}\n        }();\n        console.log(a);\n    }\n    expect: {\n        var a = 1;\n        !function() {\n            switch (a++) {}\n        }();\n        console.log(a);\n    }\n    expect_stdout: \"2\"\n}\n\nissue_1705_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var a = 0;\n        switch (a) {\n          default:\n            console.log(\"FAIL\");\n          case 0:\n            break;\n        }\n    }\n    expect: {\n        var a = 0;\n        switch (a) {\n          default:\n            console.log(\"FAIL\");\n          case 0:\n        }\n    }\n    expect_stdout: true\n}\n\nissue_1705_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_funcs: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        switches: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = 0;\n        switch (a) {\n          default:\n            console.log(\"FAIL\");\n          case 0:\n            break;\n        }\n    }\n    expect: {\n    }\n    expect_stdout: true\n}\n\nissue_1705_3: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (a) {\n          case 0:\n            break;\n          default:\n            break;\n        }\n    }\n    expect: {\n        a;\n    }\n    expect_stdout: true\n}\n\nbeautify: {\n    beautify = {\n        beautify: true,\n    }\n    input: {\n        switch (a) {\n          case 0:\n          case 1:\n            break;\n          case 2:\n          default:\n        }\n        switch (b) {\n          case 3:\n            foo();\n            bar();\n          default:\n            break;\n        }\n    }\n    expect_exact: [\n        \"switch (a) {\",\n        \"  case 0:\",\n        \"  case 1:\",\n        \"    break;\",\n        \"\",\n        \"  case 2:\",\n        \"  default:\",\n        \"}\",\n        \"\",\n        \"switch (b) {\",\n        \"  case 3:\",\n        \"    foo();\",\n        \"    bar();\",\n        \"\",\n        \"  default:\",\n        \"    break;\",\n        \"}\",\n    ]\n}\n\nissue_1758: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var a = 1, b = 2;\n        switch (a--) {\n          default:\n            b++;\n        }\n        console.log(a, b);\n    }\n    expect: {\n        var a = 1, b = 2;\n        a--;\n        b++;\n        console.log(a, b);\n    }\n    expect_stdout: \"0 3\"\n}\n\nissue_2535: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch(w(), 42) {\n          case 13: x();\n          case 42: y();\n          default: z();\n        }\n    }\n    expect: {\n        w(), 42;\n        y();\n        z();\n    }\n}\n\nissue_1750: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a = 0, b = 1;\n        switch (true) {\n          case a, true:\n          default:\n            b = 2;\n          case true:\n        }\n        console.log(a, b);\n    }\n    expect: {\n        var a = 0, b = 1;\n        true;\n        b = 2;\n        console.log(a, b);\n    }\n    expect_stdout: \"0 2\"\n}\n\ndrop_switch_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          default:\n            break;\n          case \"bar\":\n            break;\n        }\n    }\n    expect: {\n        foo;\n    }\n}\n\ndrop_switch_2: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (foo) {\n          default:\n          case \"bar\":\n            baz();\n        }\n    }\n    expect: {\n        foo;\n        baz();\n    }\n}\n\ndrop_switch_3: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        console.log(function() {\n            switch (0) {\n              default:\n                return \"PASS\";\n              case 1:\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            switch (0) {\n              default:\n                return \"PASS\";\n              case 1:\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_switch_4: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        switch (0) {\n          default:\n          case a:\n            var b = a = \"PASS\";\n            break;\n        }\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        0;\n        var b = a = \"PASS\";\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n}\n\ndrop_switch_5: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (A) {\n          case B:\n            x();\n          default:\n        }\n        switch (C) {\n          default:\n            y();\n          case D:\n        }\n    }\n    expect: {\n        A === B && x();\n        C !== D && y();\n    }\n}\n\ndrop_switch_6: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (A) {\n          case B:\n          default:\n            x();\n        }\n        switch (C) {\n          default:\n          case D:\n            y();\n        }\n    }\n    expect: {\n        A;\n        B;\n        x();\n        C !== D;\n        y();\n    }\n}\n\ndrop_switch_7: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (A) {\n          case B:\n            w();\n          default:\n            x();\n        }\n        switch (C) {\n          default:\n            y();\n          case D:\n            z();\n        }\n    }\n    expect: {\n        A === B && w();\n        x();\n        C !== D && y();\n        z();\n    }\n}\n\ndrop_switch_8: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        switch (A) {\n          case B:\n            w();\n            break;\n          default:\n            x();\n        }\n        switch (C) {\n          default:\n            y();\n            break;\n          case D:\n            z();\n        }\n    }\n    expect: {\n        (A === B ? w : x)();\n        (C !== D ? y : z)();\n    }\n}\n\nissue_4059: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (0) {\n          default:\n          case 1:\n            break;\n          case a:\n            break;\n            var a;\n        }\n        console.log(\"PASS\");\n    }\n    expect: {\n        switch (0) {\n          default:\n            break;\n          case a:\n            break;\n            var a;\n        }\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5008_1: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        switches: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function f() {\n            switch (f) {\n              case f:\n                return \"PASS\";\n              default:\n                return \"FAIL\";\n            }\n        }());\n    }\n    expect: {\n        console.log(function f() {\n            switch (f) {\n              default:\n                return \"PASS\";\n            }\n        }());\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5008_2: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        switches: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(a) {\n            switch (a) {\n              case a:\n                return \"PASS\";\n              default:\n                return \"FAIL\";\n            }\n        }([]));\n    }\n    expect: {\n        console.log(function(a) {\n            switch (a) {\n              default:\n                return \"PASS\";\n            }\n        }([]));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5008_3: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        switches: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(function(a) {\n            switch (a) {\n              case a:\n                return \"PASS\";\n              default:\n                return \"FAIL\";\n            }\n        }({}));\n    }\n    expect: {\n        console.log(function(a) {\n            switch (a) {\n              default:\n                return \"PASS\";\n            }\n        }({}));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5008_4: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        reduce_vars: true,\n        switches: true,\n    }\n    input: {\n        console.log(function(a) {\n            switch (a) {\n              case a:\n                return \"PASS\";\n              default:\n                return \"FAIL\";\n            }\n        }(/foo/));\n    }\n    expect: {\n        console.log(function(a) {\n            switch (a) {\n              default:\n                return \"PASS\";\n            }\n        }(/foo/));\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5010: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        var a;\n        switch (42) {\n          case console.log(\"PASS\"):\n          case a:\n            console.log(\"FAIL\");\n          case 42:\n        }\n    }\n    expect: {\n        var a;\n        switch (42) {\n          case console.log(\"PASS\"):\n          case a:\n            console.log(\"FAIL\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5012: {\n    options = {\n        dead_code: true,\n        evaluate: true,\n        switches: true,\n    }\n    input: {\n        switch (void 0) {\n          case console.log(\"PASS\"):\n            break;\n          case void 0:\n          case 42:\n            console.log(\"FAIL\");\n        }\n    }\n    expect: {\n        switch (void 0) {\n          case console.log(\"PASS\"):\n            break;\n          default:\n            console.log(\"FAIL\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5543_1: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var a;\n        switch (a) {\n          default:\n            switch (42) {\n              case a:\n              case console.log(\"PASS\"):\n            }\n            break;\n          case null:\n            switch (false) {\n              case a:\n              case console.log(\"FAIL\"):\n            }\n        }\n    }\n    expect: {\n        var a;\n        switch (a) {\n          default:\n            switch (42) {\n              case a:\n              case console.log(\"PASS\"):\n            }\n            break;\n          case null:\n            switch (false) {\n              case a:\n              case console.log(\"FAIL\"):\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5543_2: {\n    options = {\n        dead_code: true,\n        switches: true,\n    }\n    input: {\n        var a;\n        switch (a) {\n          default:\n            switch (42) {\n              case a:\n              case console.log(\"PASS\"):\n            }\n            break;\n          case null:\n            switch (42) {\n              case a:\n              case console.log(\"FAIL\"):\n            }\n        }\n    }\n    expect: {\n        var a;\n        switch (a) {\n          default:\n            switch (42) {\n              case a:\n              case console.log(\"PASS\"):\n            }\n            break;\n          case null:\n            switch (42) {\n              case a:\n              case console.log(\"FAIL\"):\n            }\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5890: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a.p;\n        try {\n            switch (42) {\n              default:\n                a = null;\n              case false:\n                a.q;\n            }\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a.p;\n        try {\n            switch (42) {\n              default:\n                a = null;\n              case false:\n                a.q;\n            }\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5892_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            switch (42) {\n              case null:\n                var a = \"foo\";\n              default:\n                a.p;\n            }\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            switch (42) {\n              case null:\n                var a = \"foo\";\n              default:\n                a.p;\n            }\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5892_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n    }\n    input: {\n        try {\n            switch (42) {\n              case null:\n                var a = \"foo\";\n              default:\n                a.p;\n            }\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        try {\n            switch (42) {\n              case null:\n                var a = \"foo\";\n              default:\n                a.p;\n            }\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5912_1: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a = {};\n        a = a.p;\n        switch (console) {\n          case 42:\n            a.q;\n        }\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a = {};\n        a = a.p;\n        switch (console) {\n          case 42:\n            a.q;\n        }\n        try {\n            a.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_5912_2: {\n    options = {\n        pure_getters: \"strict\",\n        reduce_vars: true,\n        side_effects: true,\n    }\n    input: {\n        var a, b = {};\n        b = b.p;\n        switch (a) {\n          case void 0:\n          case b.q:\n        }\n        try {\n            b.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect: {\n        var a, b = {};\n        b = b.p;\n        switch (a) {\n          case void 0:\n          case b.q:\n        }\n        try {\n            b.r;\n            console.log(\"FAIL\");\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/templates.js",
    "content": "simple: {\n    input: {\n        console.log(`foo\n        bar\\nbaz`);\n    }\n    expect_exact: \"console.log(`foo\\n        bar\\\\nbaz`);\"\n    expect_stdout: [\n        \"foo\",\n        \"        bar\",\n        \"baz\",\n    ]\n    node_version: \">=4\"\n}\n\nplaceholder: {\n    input: {\n        console.log(`foo ${ function(a, b) {\n            return a * b;\n        }(6, 7) }`);\n    }\n    expect_exact: \"console.log(`foo ${function(a,b){return a*b}(6,7)}`);\"\n    expect_stdout: \"foo 42\"\n    node_version: \">=4\"\n}\n\nnested: {\n    input: {\n        console.log(`P${`A${\"S\"}`}S`);\n    }\n    expect_exact: 'console.log(`P${`A${\"S\"}`}S`);'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ntagged: {\n    input: {\n        console.log(String.raw`foo\\nbar`);\n    }\n    expect_exact: \"console.log(String.raw`foo\\\\nbar`);\"\n    expect_stdout: \"foo\\\\nbar\"\n    node_version: \">=4\"\n}\n\ntagged_chain: {\n    input: {\n        function f(strings) {\n            return strings.join(\"\") || f;\n        }\n        console.log(f```${42}``pass`.toUpperCase());\n    }\n    expect_exact: 'function f(strings){return strings.join(\"\")||f}console.log(f```${42}``pass`.toUpperCase());'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ntag_parentheses_arrow: {\n    input: {\n        console.log((s => s.raw[0])`\\tPASS`.slice(2));\n    }\n    expect_exact: \"console.log((s=>s.raw[0])`\\\\tPASS`.slice(2));\"\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ntag_parentheses_binary: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var f = function() {\n            console.log(\"PASS\");\n        } || console\n        f``;\n    }\n    expect_exact: '(function(){console.log(\"PASS\")}||console)``;'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ntag_parentheses_new: {\n    input: {\n        (new function() {\n            return console.log;\n        })`foo`;\n    }\n    expect_exact: \"(new function(){return console.log})`foo`;\"\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\ntag_parentheses_sequence: {\n    input: {\n        var o = {\n            f() {\n                console.log(this === o ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (42, o.f)``;\n    }\n    expect_exact: 'var o={f(){console.log(this===o?\"FAIL\":\"PASS\")}};(42,o.f)``;'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ntag_parentheses_unary: {\n    input: {\n        var a;\n        try {\n            (~a)``;\n            (a++)``;\n        } catch (e) {\n            console.log(\"PASS\");\n        }\n    }\n    expect_exact: 'var a;try{(~a)``;(a++)``}catch(e){console.log(\"PASS\")}'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nmalformed_escape: {\n    input: {\n        (function(s) {\n            s.forEach((c, i) => console.log(i, c, s.raw[i]));\n            return () => console.log(arguments);\n        })`\\uFo${42}`();\n    }\n    expect_exact: \"(function(s){s.forEach((c,i)=>console.log(i,c,s.raw[i]));return()=>console.log(arguments)})`\\\\uFo${42}`();\"\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nbooleans: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        var a;\n        console.log(`$${a}${a}` ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        var a;\n        console.log(\"$\" + a + a ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nescape_placeholder_1: {\n    options = {\n        templates: true,\n    }\n    input: {\n        console.log(`\\${\\n`);\n    }\n    expect: {\n        console.log(`\\${\n`);\n    }\n    expect_stdout: [\n        \"${\",\n        \"\",\n    ]\n    node_version: \">=4\"\n}\n\nescape_placeholder_2: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`\\n${\"${\"}\\n`);\n    }\n    expect: {\n        console.log(`\n\\${\n`);\n    }\n    expect_stdout: [\n        \"\",\n        \"${\",\n        \"\",\n    ]\n    node_version: \">=4\"\n}\n\nescape_placeholder_3: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`\\n$${\"{\"}\\n`);\n    }\n    expect: {\n        console.log(`\n\\${\n`);\n    }\n    expect_stdout: [\n        \"\",\n        \"${\",\n        \"\",\n    ]\n    node_version: \">=4\"\n}\n\nescape_placeholder_4: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`\\n${\"$\"}${\"{\"}\\n`);\n    }\n    expect: {\n        console.log(`\n\\${\n`);\n    }\n    expect_stdout: [\n        \"\",\n        \"${\",\n        \"\",\n    ]\n    node_version: \">=4\"\n}\n\nevaluate: {\n    options = {\n        evaluate: true,\n        templates: false,\n    }\n    input: {\n        console.log(`foo ${ function(a, b) {\n            return a * b;\n        }(6, 7) }`);\n    }\n    expect: {\n        console.log(`foo ${42}`);\n    }\n    expect_stdout: \"foo 42\"\n    node_version: \">=4\"\n}\n\nevaluate_templates: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`foo ${ function(a, b) {\n            return a * b;\n        }(6, 7) }`);\n    }\n    expect: {\n        console.log(\"foo 42\");\n    }\n    expect_stdout: \"foo 42\"\n    node_version: \">=4\"\n}\n\npartial_evaluate: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`${6 * 7} foo ${console ? `PA` + \"SS\" : `FA` + `IL`}`);\n    }\n    expect: {\n        console.log(\"42 foo \" + (console ? \"PASS\" : \"FAIL\"));\n    }\n    expect_stdout: \"42 foo PASS\"\n    node_version: \">=4\"\n}\n\nmalformed_evaluate_1: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`\\67 ${6 * 7}`);\n    }\n    expect: {\n        console.log(`\\67 42`);\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nmalformed_evaluate_2: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`\\u0${0}b${5}`);\n    }\n    expect: {\n        console.log(`\\u00b` + 5);\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nmalformed_evaluate_3: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`\\u${0}b${5}`);\n    }\n    expect: {\n        console.log(`\\u0b5`);\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nmalformed_evaluate_4: {\n    options = {\n        evaluate: true,\n        templates: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(String.raw`\\u0${0}b${5}`);\n    }\n    expect: {\n        console.log(\"\\\\u00b5\");\n    }\n    expect_stdout: \"\\\\u00b5\"\n    node_version: \">=8.10.0\"\n}\n\nunsafe_evaluate: {\n    options = {\n        evaluate: true,\n        templates: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(String.raw`\\uFo`);\n    }\n    expect: {\n        console.log(\"\\\\uFo\");\n    }\n    expect_stdout: \"\\\\uFo\"\n    node_version: \">=8.10.0\"\n}\n\nside_effects_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        `42`;\n        `${console.log(\"foo\")}`;\n        console.log`\\nbar`;\n    }\n    expect: {\n        console.log(\"foo\");\n        console.log`\\nbar`;\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nside_effects_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        var o = {\n            f() {\n                console.log(this === o ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (42, o.f)``;\n    }\n    expect: {\n        var o = {\n            f() {\n                console.log(this === o ? \"FAIL\" : \"PASS\");\n            },\n        };\n        (0, o.f)``;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nunsafe_side_effects: {\n    options = {\n        side_effects: true,\n        unsafe: true,\n    }\n    input: {\n        `42`;\n        `${console.log(\"foo\")}`;\n        String.raw`\\nbar`;\n    }\n    expect: {\n        console.log(\"foo\");\n    }\n    expect_stdout: \"foo\"\n    node_version: \">=4\"\n}\n\npure_funcs: {\n    options = {\n        pure_funcs: \"Math.random\",\n        side_effects: true,\n    }\n    input: {\n        Math.random`${console.log(\"PASS\")}`;\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nascii_only: {\n    beautify = {\n        ascii_only: true,\n        module: false,\n    }\n    options = {\n        templates: false,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`\\\\ud801\\\\udc37\\\\ud801\\\\ud801\\\\udc37${42}\\\\u{10437}`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nascii_only_ecma: {\n    beautify = {\n        ascii_only: true,\n        module: true,\n    }\n    options = {\n        templates: false,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`\\\\ud801\\\\udc37\\\\ud801\\\\u{10437}${42}\\\\u{10437}`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nascii_only_templates: {\n    beautify = {\n        ascii_only: true,\n        module: false,\n    }\n    options = {\n        templates: true,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`\\\\ud801\\\\udc37\\\\ud801\\\\ud801\\\\udc37${42}\\\\ud801\\\\udc37`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nascii_only_templates_ecma: {\n    beautify = {\n        ascii_only: true,\n        module: true,\n    }\n    options = {\n        templates: true,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`\\\\u{10437}\\\\ud801\\\\u{10437}${42}\\\\u{10437}`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nunicode: {\n    beautify = {\n        ascii_only: false,\n        module: false,\n    }\n    options = {\n        templates: false,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`\\\\ud801\\\\udc37\\\\ud801𐐷${42}\\\\u{10437}`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nunicode_ecma: {\n    beautify = {\n        ascii_only: false,\n        module: true,\n    }\n    options = {\n        templates: false,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`\\\\ud801\\\\udc37\\\\ud801𐐷${42}\\\\u{10437}`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nunicode_templates: {\n    beautify = {\n        ascii_only: false,\n        module: false,\n    }\n    options = {\n        templates: true,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`𐐷\\\\ud801𐐷${42}𐐷`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nunicode_templates_ecma: {\n    beautify = {\n        ascii_only: false,\n        module: true,\n    }\n    options = {\n        templates: true,\n    }\n    input: {\n        console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);\n    }\n    expect_exact: \"console.log(`𐐷\\\\ud801𐐷${42}𐐷`);\"\n    expect_stdout: \"𐐷\\ud801𐐷42𐐷\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nissue_4604: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = 0, log = console.log;\n        a = \"FAIL\";\n        (function() {\n            a = \"PASS\";\n        })``;\n        log(a);\n    }\n    expect: {\n        var a = 0, log = console.log;\n        a = \"FAIL\";\n        (function() {\n            a = \"PASS\";\n        })``;\n        log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4606: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`${typeof A} ${\"\\r\"} ${\"\\\\\"} ${\"`\"}`);\n    }\n    expect: {\n        console.log(typeof A + \" \\r \\\\ `\");\n    }\n    expect_stdout: \"undefined \\r \\\\ `\"\n    node_version: \">=4\"\n}\n\nissue_4630: {\n    options = {\n        evaluate: true,\n        templates: true,\n    }\n    input: {\n        console.log(`${/PASS/}`);\n    }\n    expect: {\n        console.log(\"/PASS/\");\n    }\n    expect_stdout: \"/PASS/\"\n    node_version: \">=4\"\n}\n\nissue_4676: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        templates: true,\n        toplevel: true,\n        unsafe: true,\n        unused: true,\n    }\n    input: {\n        function f(a) {\n            var b = `foo${a = \"PASS\"}`;\n            for (var c in f && b)\n                b.p;\n            return a;\n        }\n        console.log(f(\"FAIL\"));\n    }\n    expect: {\n        console.log(function f(a) {\n            var b = \"fooPASS\";\n            for (var c in f, b)\n                b.p;\n            return \"PASS\";\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4931: {\n    options = {\n        evaluate: true,\n        templates: true,\n        unsafe: true,\n    }\n    input: {\n        console.log(String.raw`${typeof A} ${\"\\r\"}`);\n        console.log(String.raw`${\"\\\\\"} ${\"`\"}`);\n    }\n    expect: {\n        console.log(String.raw`${typeof A} ${\"\\r\"}`);\n        console.log(\"\\\\ `\");\n    }\n    expect_stdout: [\n        \"undefined \\r\",\n        \"\\\\ `\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5125_1: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`PASS ${typeof A}`);\n    }\n    expect: {\n        console.log(\"PASS \" + typeof A);\n    }\n    expect_stdout: \"PASS undefined\"\n    node_version: \">=4\"\n}\n\nissue_5125_2: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`PASS\n${typeof A}`);\n    }\n    expect: {\n        console.log(`PASS\n` + typeof A);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5125_3: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`PASS\\n${typeof A}`);\n    }\n    expect: {\n        console.log(`PASS\n` + typeof A);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5125_4: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`PASS\n\n${typeof A}`);\n    }\n    expect: {\n        console.log(`PASS\n\n` + typeof A);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5125_5: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`PASS\\n\\n${typeof A}`);\n    }\n    expect: {\n        console.log(`PASS\n\n` + typeof A);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5125_6: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`${typeof A} ${typeof B} PASS`);\n    }\n    expect: {\n        console.log(typeof A + ` ${typeof B} PASS`);\n    }\n    expect_stdout: \"undefined undefined PASS\"\n    node_version: \">=4\"\n}\n\nissue_5125_7: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`${typeof A} ${typeof B} ${typeof C} PASS`);\n    }\n    expect: {\n        console.log(typeof A + ` ${typeof B} ${typeof C} PASS`);\n    }\n    expect_stdout: \"undefined undefined undefined PASS\"\n    node_version: \">=4\"\n}\n\nissue_5125_8: {\n    options = {\n        evaluate: true,\n        strings: true,\n        templates: true,\n    }\n    input: {\n        console.log(`${typeof A}${typeof B}${typeof C} PASS`);\n    }\n    expect: {\n        console.log(typeof A + typeof B + typeof C + \" PASS\");\n    }\n    expect_stdout: \"undefinedundefinedundefined PASS\"\n    node_version: \">=4\"\n}\n\nissue_5136: {\n    options = {\n        templates: true,\n    }\n    input: {\n        console.log(`${A = []}${A[0] = 42}`);\n    }\n    expect: {\n        console.log(`` + (A = []) + (A[0] = 42));\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nissue_5145_1: {\n    options = {\n        strings: true,\n        templates: true,\n    }\n    input: {\n        var a = [];\n        console.log(`${a}${a[0] = 42}\n`);\n    }\n    expect: {\n        var a = [];\n        console.log(`${a}${a[0] = 42}\n`);\n    }\n    expect_stdout: [\n        \"42\",\n        \"\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5145_2: {\n    options = {\n        strings: true,\n        templates: true,\n    }\n    input: {\n        var a = [];\n        console.log(`${a}${a}${a[0] = 42}\n`);\n    }\n    expect: {\n        var a = [];\n        console.log(\"\" + a + a + (a[0] = 42) + `\n`);\n    }\n    expect_stdout: [\n        \"42\",\n        \"\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5199: {\n    options = {\n        collapse_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function() {\n            console.log(typeof b);\n        }``;\n        {\n            const b = a;\n        }\n    }\n    expect: {\n        var a = function() {\n            console.log(typeof b);\n        }``;\n        {\n            const b = a;\n        }\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_5878: {\n    beautify = {\n        semicolons: false,\n    }\n    input: {\n        console.log(\"PASS\");\n        `42`;\n    }\n    expect_exact: 'console.log(\"PASS\");`42`\\n'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n"
  },
  {
    "path": "test/compress/transform.js",
    "content": "booleans_evaluate: {\n    options = {\n        booleans: true,\n        evaluate: true,\n    }\n    input: {\n        console.log(typeof void 0 != \"undefined\");\n        console.log(1 == 1, 1 === 1)\n        console.log(1 != 1, 1 !== 1)\n    }\n    expect: {\n        console.log(!1);\n        console.log(!0, !0);\n        console.log(!1, !1);\n    }\n    expect_stdout: true\n}\n\nbooleans_global_defs: {\n    options = {\n        booleans: true,\n        evaluate: true,\n        global_defs: {\n            A: true,\n        },\n    }\n    input: {\n        console.log(A == 1);\n    }\n    expect: {\n        console.log(!0);\n    }\n}\n\ncondition_evaluate: {\n    options = {\n        booleans: true,\n        dead_code: false,\n        evaluate: true,\n        loops: false,\n    }\n    input: {\n        while (1 === 2);\n        for (; 1 == true;);\n        if (void 0 == null);\n    }\n    expect: {\n        while (0);\n        for (; 1;);\n        if (1);\n    }\n}\n\nif_else_empty: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if ({} ? a : b); else {}\n    }\n    expect: {\n        ({}), a;\n    }\n}\n\nlabel_if_break: {\n    options = {\n        conditionals: true,\n        dead_code: true,\n        evaluate: true,\n        side_effects: true,\n        unused: true,\n    }\n    input: {\n        L: if (true) {\n            a;\n            break L;\n        }\n    }\n    expect: {\n        a;\n    }\n}\n\nwhile_if_break: {\n    options = {\n        conditionals: true,\n        loops: true,\n        sequences: true,\n    }\n    input: {\n        while (a) {\n            if (b) if(c) d;\n            if (e) break;\n        }\n    }\n    expect: {\n        for (; a && (b && c && d, !e););\n    }\n}\n\nif_return: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        if_return: true,\n        passes: 2,\n        sequences: true,\n        side_effects: true,\n    }\n    input: {\n        function f(w, x, y, z) {\n            if (x) return;\n            if (w) {\n                if (y) return;\n            } else if (z) return;\n            if (x == y) return true;\n\n            if (x) w();\n            if (y) z();\n            return true;\n        }\n    }\n    expect: {\n        function f(w, x, y, z) {\n            if (!x) {\n                if (w) {\n                    if (y) return;\n                } else if (z) return;\n                return x != y && (x && w(), y) && z(), !0;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "test/compress/typeof.js",
    "content": "typeof_evaluation: {\n    options = {\n        evaluate: true,\n        typeofs: true,\n    }\n    input: {\n        a = typeof 1;\n        b = typeof 'test';\n        c = typeof [];\n        d = typeof {};\n        e = typeof /./;\n        f = typeof false;\n        g = typeof function(){};\n        h = typeof undefined;\n    }\n    expect: {\n        a='number';\n        b='string';\n        c=typeof[];\n        d=typeof{};\n        e=typeof/./;\n        f='boolean';\n        g='function';\n        h='undefined';\n    }\n}\n\ntypeof_in_boolean_context: {\n    options = {\n        booleans: true,\n        conditionals: true,\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        function f1(x) { return typeof x ? \"yes\" : \"no\"; }\n        function f2() { return typeof g()? \"Yes\" : \"No\"; }\n        typeof 0 ? foo() : bar();\n        !typeof console.log(1);\n        var a = !typeof console.log(2);\n        if (typeof (1 + foo()));\n    }\n    expect: {\n        function f1(x) { return \"yes\"; }\n        function f2() { return g(), \"Yes\"; }\n        foo();\n        console.log(1);\n        var a = !(console.log(2), 1);\n        foo();\n    }\n}\n\nissue_1668: {\n    options = {\n        booleans: true,\n    }\n    input: {\n        if (typeof bar);\n    }\n    expect: {\n        if (1);\n    }\n}\n\ntypeof_defun_1: {\n    options = {\n        evaluate: true,\n        inline: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        function f() {\n            console.log(\"YES\");\n        }\n        function g() {\n            h = 42;\n            console.log(\"NOPE\");\n        }\n        function h() {\n            console.log(\"YUP\");\n        }\n        g = 42;\n        \"function\" == typeof f && f();\n        \"function\" == typeof g && g();\n        \"function\" == typeof h && h();\n    }\n    expect: {\n        function h() {\n            console.log(\"YUP\");\n        }\n        console.log(\"YES\");\n        h();\n    }\n    expect_stdout: [\n        \"YES\",\n        \"YUP\",\n    ]\n}\n\ntypeof_defun_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n    }\n    input: {\n        var f = function() {\n            console.log(x);\n        };\n        var x = 0;\n        x++ < 2 && typeof f == \"function\" && f();\n        x++ < 2 && typeof f == \"function\" && f();\n        x++ < 2 && typeof f == \"function\" && f();\n    }\n    expect: {\n        var f = function() {\n            console.log(x);\n        };\n        var x = 0;\n        x++ < 2 && f();\n        x++ < 2 && f();\n        x++ < 2 && f();\n    }\n    expect_stdout: [\n        \"1\",\n        \"2\",\n    ]\n}\n\nduplicate_defun_arg_name: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        function long_name(long_name) {\n            return typeof long_name;\n        }\n        console.log(typeof long_name, long_name());\n    }\n    expect: {\n        function long_name(long_name) {\n            return typeof long_name;\n        }\n        console.log(typeof long_name, long_name());\n    }\n    expect_stdout: \"function undefined\"\n}\n\nduplicate_lambda_arg_name: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        console.log(function long_name(long_name) {\n            return typeof long_name;\n        }());\n    }\n    expect: {\n        console.log(\"undefined\");\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_2728_1: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        (function arguments() {\n            console.log(typeof arguments);\n        })();\n    }\n    expect: {\n        (function arguments() {\n            console.log(typeof arguments);\n        })();\n    }\n    expect_stdout: \"object\"\n}\n\nissue_2728_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        function arguments() {\n            return typeof arguments;\n        }\n        console.log(typeof arguments, arguments());\n    }\n    expect: {\n        function arguments() {\n            return typeof arguments;\n        }\n        console.log(typeof arguments, arguments());\n    }\n    expect_stdout: \"function object\"\n}\n\nissue_2728_3: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        (function() {\n            function arguments() {\n            }\n            console.log(typeof arguments);\n        })();\n    }\n    expect: {\n        (function() {\n            function arguments() {\n            }\n            console.log(\"function\");\n        })();\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2728_4: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n    }\n    input: {\n        function arguments() {\n        }\n        console.log(typeof arguments);\n    }\n    expect: {\n        function arguments() {\n        }\n        console.log(\"function\");\n    }\n    expect_stdout: \"function\"\n}\n\nissue_2728_5: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        (function arguments(arguments) {\n            console.log(typeof arguments);\n        })();\n    }\n    expect: {\n        (function arguments(arguments) {\n            console.log(typeof arguments);\n        })();\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_2728_6: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        function arguments(arguments) {\n            return typeof arguments;\n        }\n        console.log(typeof arguments, arguments());\n    }\n    expect: {\n        function arguments(arguments) {\n            return typeof arguments;\n        }\n        console.log(typeof arguments, arguments());\n    }\n    expect_stdout: \"function undefined\"\n}\n\ntypeof_defined_1: {\n    options = {\n        side_effects: true,\n        typeofs: true,\n    }\n    input: {\n        \"undefined\" == typeof A && A;\n        \"undefined\" != typeof A && A;\n        \"undefined\" == typeof A || A;\n        \"undefined\" != typeof A || A;\n    }\n    expect: {\n        \"undefined\" == typeof A && A;\n        \"undefined\" == typeof A && A;\n    }\n}\n\ntypeof_defined_2: {\n    options = {\n        side_effects: true,\n        typeofs: true,\n    }\n    input: {\n        \"function\" == typeof A && A;\n        \"function\" != typeof A && A;\n        \"function\" == typeof A || A;\n        \"function\" != typeof A || A;\n    }\n    expect: {\n        \"function\" != typeof A && A;\n        \"function\" != typeof A && A;\n    }\n}\n\ntypeof_defined_3: {\n    options = {\n        side_effects: true,\n        typeofs: true,\n    }\n    input: {\n        \"undefined\" == typeof A && \"undefined\" == typeof B && (A, B);\n        \"undefined\" == typeof A && \"undefined\" != typeof B && (A, B);\n        \"undefined\" != typeof A && \"undefined\" == typeof B && (A, B);\n        \"undefined\" != typeof A && \"undefined\" != typeof B && (A, B);\n        \"undefined\" == typeof A && \"undefined\" == typeof B || (A, B);\n        \"undefined\" == typeof A && \"undefined\" != typeof B || (A, B);\n        \"undefined\" != typeof A && \"undefined\" == typeof B || (A, B);\n        \"undefined\" != typeof A && \"undefined\" != typeof B || (A, B);\n        \"undefined\" == typeof A || \"undefined\" == typeof B && (A, B);\n        \"undefined\" == typeof A || \"undefined\" != typeof B && (A, B);\n        \"undefined\" != typeof A || \"undefined\" == typeof B && (A, B);\n        \"undefined\" != typeof A || \"undefined\" != typeof B && (A, B);\n        \"undefined\" == typeof A || \"undefined\" == typeof B || (A, B);\n        \"undefined\" == typeof A || \"undefined\" != typeof B || (A, B);\n        \"undefined\" != typeof A || \"undefined\" == typeof B || (A, B);\n        \"undefined\" != typeof A || \"undefined\" != typeof B || (A, B);\n    }\n    expect: {\n        \"undefined\" == typeof A && \"undefined\" == typeof B && (A, B);\n        \"undefined\" == typeof A && \"undefined\" != typeof B && A;\n        \"undefined\" != typeof A && \"undefined\" == typeof B && B;\n        // dropped\n        \"undefined\" == typeof A && \"undefined\" == typeof B || (A, B);\n        \"undefined\" == typeof A && \"undefined\" != typeof B || (A, B);\n        \"undefined\" != typeof A && \"undefined\" == typeof B || (A, B);\n        \"undefined\" != typeof A && \"undefined\" != typeof B || (A, B);\n        \"undefined\" != typeof A && \"undefined\" == typeof B && B;\n        // dropped\n        \"undefined\" == typeof A && \"undefined\" == typeof B && (A, B);\n        \"undefined\" == typeof A && \"undefined\" != typeof B && A;\n        // dropped\n        \"undefined\" != typeof A && \"undefined\" == typeof B && B;\n        \"undefined\" == typeof A && \"undefined\" != typeof B && A;\n        \"undefined\" == typeof A && \"undefined\" == typeof B && (A, B);\n    }\n}\n\ntypeof_defined_4: {\n    options = {\n        side_effects: true,\n        typeofs: true,\n    }\n    input: {\n        \"object\" == typeof A && \"object\" == typeof B && (A, B);\n        \"object\" == typeof A && \"object\" != typeof B && (A, B);\n        \"object\" != typeof A && \"object\" == typeof B && (A, B);\n        \"object\" != typeof A && \"object\" != typeof B && (A, B);\n        \"object\" == typeof A && \"object\" == typeof B || (A, B);\n        \"object\" == typeof A && \"object\" != typeof B || (A, B);\n        \"object\" != typeof A && \"object\" == typeof B || (A, B);\n        \"object\" != typeof A && \"object\" != typeof B || (A, B);\n        \"object\" == typeof A || \"object\" == typeof B && (A, B);\n        \"object\" == typeof A || \"object\" != typeof B && (A, B);\n        \"object\" != typeof A || \"object\" == typeof B && (A, B);\n        \"object\" != typeof A || \"object\" != typeof B && (A, B);\n        \"object\" == typeof A || \"object\" == typeof B || (A, B);\n        \"object\" == typeof A || \"object\" != typeof B || (A, B);\n        \"object\" != typeof A || \"object\" == typeof B || (A, B);\n        \"object\" != typeof A || \"object\" != typeof B || (A, B);\n    }\n    expect: {\n        // dropped\n        \"object\" == typeof A && \"object\" != typeof B && B;\n        \"object\" != typeof A && \"object\" == typeof B && A;\n        \"object\" != typeof A && \"object\" != typeof B && (A, B);\n        \"object\" == typeof A && \"object\" == typeof B || (A, B);\n        \"object\" == typeof A && \"object\" != typeof B || (A, B);\n        \"object\" != typeof A && \"object\" == typeof B || (A, B);\n        \"object\" != typeof A && \"object\" != typeof B || (A, B);\n        \"object\" != typeof A && \"object\" == typeof B && A;\n        \"object\" != typeof A && \"object\" != typeof B && (A, B);\n        // dropped\n        \"object\" == typeof A && \"object\" != typeof B && B;\n        \"object\" != typeof A && \"object\" != typeof B && (A, B);\n        \"object\" != typeof A && \"object\" == typeof B && A;\n        \"object\" == typeof A && \"object\" != typeof B && B;\n        // dropped\n    }\n}\n\nemberjs_global: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        if_return: true,\n        passes: 2,\n        side_effects: true,\n        toplevel: true,\n        typeofs: true,\n        unused: true,\n    }\n    input: {\n        var a;\n        if (typeof A === \"object\") {\n            a = A;\n        } else if (typeof B === \"object\") {\n            a = B;\n        } else {\n            throw new Error(\"PASS\");\n        }\n    }\n    expect: {\n        if (\"object\" != typeof A && \"object\" != typeof B)\n            throw new Error(\"PASS\");\n    }\n    expect_stdout: Error(\"PASS\")\n}\n\nreassign: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        typeofs: true,\n    }\n    input: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            A = void 0;\n            while (console.log(void 0 === A ? \"PASS\" : \"FAIL 2\"));\n        }\n    }\n    expect: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            A = void 0;\n            while (console.log(void 0 === A ? \"PASS\" : \"FAIL 2\"));\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nreassign_call: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        typeofs: true,\n    }\n    input: {\n        A = console;\n        function f() {\n            A = void 0;\n        }\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            f();\n            while (console.log(void 0 === A ? \"PASS\" : \"FAIL 2\"));\n        }\n    }\n    expect: {\n        A = console;\n        function f() {\n            A = void 0;\n        }\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            f();\n            while (console.log(void 0 === A ? \"PASS\" : \"FAIL 2\"));\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nreassign_conditional: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        typeofs: true,\n    }\n    input: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            A &&= void 0;\n            while (console.log(void 0 === A ? \"PASS\" : \"FAIL 2\"));\n        }\n    }\n    expect: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            A &&= void 0;\n            while (console.log(void 0 === A ? \"PASS\" : \"FAIL 2\"));\n        }\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=15\"\n}\n\nreassign_do: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        if_return: true,\n        passes: 2,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        A = console;\n        (function() {\n            if (\"undefined\" == typeof A)\n                return;\n            var a = A, i = 2;\n            do {\n                console.log(void 0 === A, void 0 === a);\n                A = void 0;\n            } while (--i);\n        })();\n    }\n    expect: {\n        A = console;\n        (function() {\n            if (\"undefined\" != typeof A) {\n                var a = A, i = 2;\n                do {\n                    console.log(void 0 === A, (a, false));\n                    A = void 0;\n                } while (--i);\n            }\n        })();\n    }\n    expect_stdout: [\n        \"false false\",\n        \"true false\",\n    ]\n}\n\nreassign_for: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        typeofs: true,\n    }\n    input: {\n        if (A = console, \"undefined\" != typeof A)\n            for (var a = A, i = 0; i < 2; i++)\n                console.log(void 0 === A, void 0 === a),\n                A = void 0;\n    }\n    expect: {\n        if (A = console, \"undefined\" != typeof A)\n            for (var a = A, i = 0; i < 2; i++)\n                console.log(void 0 === A, (a, false)),\n                A = void 0;\n    }\n    expect_stdout: [\n        \"false false\",\n        \"true false\",\n    ]\n}\n\nreassign_for_in: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        reduce_vars: true,\n        typeofs: true,\n    }\n    input: {\n        (A = console) && \"undefined\" != typeof A && function(a) {\n            for (var k in [ a = A, 42 ]) {\n                console.log(void 0 === A, void 0 === a);\n                A = void 0;\n            }\n        }();\n    }\n    expect: {\n        (A = console) && \"undefined\" != typeof A && function(a) {\n            for (var k in [ a = A, 42 ]) {\n                console.log(void 0 === A, (a, false));\n                A = void 0;\n            }\n        }();\n    }\n    expect_stdout: [\n        \"false false\",\n        \"true false\",\n    ]\n}\n\nreassign_iife: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        typeofs: true,\n    }\n    input: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else (function() {\n            A = void 0;\n        })(console.log(void 0 === A ? \"FAIL 2\" : \"PASS\"));\n    }\n    expect: {\n        A = console;\n        \"undefined\" == typeof A ? console.log(\"FAIL 1\") : function() {\n            A = void 0;\n        }(console.log((A, false) ? \"FAIL 2\" : \"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n}\n\nreassign_property: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        typeofs: true,\n    }\n    input: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            A.p = void 0;\n            console.log(void 0 === A ? \"FAIL 2\" : \"PASS\");\n        }\n    }\n    expect: {\n        A = console;\n        if (\"undefined\" == typeof A)\n            console.log(\"FAIL 1\");\n        else {\n            A.p = void 0;\n            console.log((A, false) ? \"FAIL 2\" : \"PASS\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n\nissue_3817: {\n    options = {\n        comparisons: true,\n        conditionals: true,\n        passes: 2,\n        typeofs: true,\n    }\n    input: {\n        if (\"A\" == typeof A || !console.log(\"PASS\")) switch (false) {\n          case \"undefined\" == typeof A:\n            console.log(\"FAIL\");\n        }\n    }\n    expect: {\n        if (\"A\" == typeof A || !console.log(\"PASS\")) switch (false) {\n          case \"undefined\" == typeof A:\n            console.log(\"FAIL\");\n        }\n    }\n    expect_stdout: \"PASS\"\n}\n"
  },
  {
    "path": "test/compress/unicode.js",
    "content": "ascii_only_false: {\n    options = {}\n    beautify = {\n        ascii_only: false,\n    }\n    input: {\n        console.log(\n            \"\\x000\\x001\\x007\\x008\\x00\",\n            \"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\",\n            \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\",\n            \"\\x20\\x21\\x22\\x23 ... \\x7d\\x7e\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\"\n        );\n    }\n    expect_exact: 'console.log(\"\\\\x000\\\\x001\\\\x007\\\\x008\\\\0\",\"\\\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\\x0e\\x0f\",\"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\",\\' !\"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\\');'\n    expect_stdout: true\n}\n\nascii_only_true: {\n    options = {}\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        console.log(\n            \"\\x000\\x001\\x007\\x008\\x00\",\n            \"\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\",\n            \"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\",\n            \"\\x20\\x21\\x22\\x23 ... \\x7d\\x7e\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\"\n        );\n    }\n    expect_exact: 'console.log(\"\\\\x000\\\\x001\\\\x007\\\\x008\\\\0\",\"\\\\0\\\\x01\\\\x02\\\\x03\\\\x04\\\\x05\\\\x06\\\\x07\\\\b\\\\t\\\\n\\\\v\\\\f\\\\r\\\\x0e\\\\x0f\",\"\\\\x10\\\\x11\\\\x12\\\\x13\\\\x14\\\\x15\\\\x16\\\\x17\\\\x18\\\\x19\\\\x1a\\\\x1b\\\\x1c\\\\x1d\\\\x1e\\\\x1f\",\\' !\"# ... }~\\\\x7f\\\\x80\\\\x81 ... \\\\xfe\\\\xff\\\\u0fff\\\\uffff\\');'\n    expect_stdout: true\n}\n\nunicode_parse_variables: {\n    options = {}\n    input: {\n        var a = {};\n        a.你好 = 456;\n\n        var ↂωↂ = 123;\n        var l০ = 3; // 2nd char is a unicode digit\n    }\n    expect: {\n        var a = {};\n        a.你好 = 456;\n\n        var ↂωↂ = 123;\n        var l০ = 3;\n    }\n}\n\nunicode_escaped_identifier_1: {\n    input: {\n        var \\u0061 = \"\\ud800\\udc00\";\n        console.log(a);\n    }\n    expect_exact: 'var a=\"\\ud800\\udc00\";console.log(a);'\n    expect_stdout: \"\\ud800\\udc00\"\n}\n\nunicode_escaped_identifier_2: {\n    input: {\n        var \\u{61} = \"foo\";\n        var \\u{10000} = \"bar\";\n        console.log(a, \\u{10000});\n    }\n    expect_exact: 'var a=\"foo\";var \\u{10000}=\"bar\";console.log(a,\\u{10000});'\n    expect_stdout: \"foo bar\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nunicode_identifier_ascii_only: {\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        var \\u0061 = \"testing \\udbc4\\udd11\";\n        var bar = \"h\\u0065llo\";\n        console.log(a, \\u0062\\u0061r);\n    }\n    expect_exact: 'var a=\"testing \\\\udbc4\\\\udd11\";var bar=\"hello\";console.log(a,bar);'\n    expect_stdout: \"testing \\udbc4\\udd11 hello\"\n}\n\nunicode_string_literals: {\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        var a = \"6 length unicode character: \\udbc4\\udd11\";\n        console.log(\\u0061);\n    }\n    expect_exact: 'var a=\"6 length unicode character: \\\\udbc4\\\\udd11\";console.log(a);'\n    expect_stdout: \"6 length unicode character: \\udbc4\\udd11\"\n}\n\ncheck_escape_style: {\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        var a = \"\\x01\";\n        var \\ua0081 = \"\\x10\"; // \\u0081 only in ID_Continue\n        var \\u0100 = \"\\u0100\";\n        var \\u1000 = \"\\u1000\";\n        var \\u1000 = \"\\ud800\\udc00\";\n        var \\u3f80 = \"\\udbc0\\udc00\";\n        console.log(\\u0061, \\ua0081, \\u0100, \\u1000, \\u3f80);\n    }\n    expect_exact: 'var a=\"\\\\x01\";var \\\\ua0081=\"\\\\x10\";var \\\\u0100=\"\\\\u0100\";var \\\\u1000=\"\\\\u1000\";var \\\\u1000=\"\\\\ud800\\\\udc00\";var \\\\u3f80=\"\\\\udbc0\\\\udc00\";console.log(a,\\\\ua0081,\\\\u0100,\\\\u1000,\\\\u3f80);'\n    expect_stdout: \"\\u0001 \\u0010 \\u0100 \\ud800\\udc00 \\udbc0\\udc00\"\n}\n\nescape_non_escaped_identifier: {\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        var µþ = \"µþ\";\n        console.log(\\u00b5þ);\n    }\n    expect_exact: 'var \\\\u00b5\\\\u00fe=\"\\\\xb5\\\\xfe\";console.log(\\\\u00b5\\\\u00fe);'\n    expect_stdout: \"µþ\"\n}\n\nnon_escape_2_non_escape: {\n    beautify = {\n        ascii_only: false,\n    }\n    input: {\n        var µþ = \"µþ\";\n        console.log(\\u00b5þ);\n    }\n    expect_exact: 'var µþ=\"µþ\";console.log(µþ);'\n    expect_stdout: \"µþ\"\n}\n\nissue_2242_1: {\n    beautify = {\n        ascii_only: false,\n    }\n    input: {\n        console.log(\"\\ud83d\", \"\\ude00\", \"\\ud83d\\ude00\", \"\\ud83d@\\ude00\");\n    }\n    expect_exact: 'console.log(\"\\\\ud83d\",\"\\\\ude00\",\"\\ud83d\\ude00\",\"\\\\ud83d@\\\\ude00\");'\n    expect_stdout: \"\\ud83d \\ude00 \\ud83d\\ude00 \\ud83d@\\ude00\"\n}\n\nissue_2242_2: {\n    beautify = {\n        ascii_only: true,\n    }\n    input: {\n        console.log(\"\\ud83d\", \"\\ude00\", \"\\ud83d\\ude00\", \"\\ud83d@\\ude00\");\n    }\n    expect_exact: 'console.log(\"\\\\ud83d\",\"\\\\ude00\",\"\\\\ud83d\\\\ude00\",\"\\\\ud83d@\\\\ude00\");'\n    expect_stdout: \"\\ud83d \\ude00 \\ud83d\\ude00 \\ud83d@\\ude00\"\n}\n\nissue_2242_3: {\n    options = {\n        evaluate: false,\n    }\n    input: {\n        console.log(\"\\ud83d\" + \"\\ude00\", \"\\ud83d\" + \"@\" + \"\\ude00\");\n    }\n    expect_exact: 'console.log(\"\\\\ud83d\"+\"\\\\ude00\",\"\\\\ud83d\"+\"@\"+\"\\\\ude00\");'\n    expect_stdout: \"\\ud83d\\ude00 \\ud83d@\\ude00\"\n}\n\nissue_2242_4: {\n    options = {\n        evaluate: true,\n    }\n    input: {\n        console.log(\"\\ud83d\" + \"\\ude00\", \"\\ud83d\" + \"@\" + \"\\ude00\");\n    }\n    expect_exact: 'console.log(\"\\ud83d\\ude00\",\"\\\\ud83d@\\\\ude00\");'\n    expect_stdout: \"\\ud83d\\ude00 \\ud83d@\\ude00\"\n}\n\nissue_2569: {\n    input: {\n        new RegExp(\"[\\udc42-\\udcaa\\udd74-\\udd96\\ude45-\\ude4f\\udea3-\\udecc]\");\n    }\n    expect_exact: 'new RegExp(\"[\\\\udc42-\\\\udcaa\\\\udd74-\\\\udd96\\\\ude45-\\\\ude4f\\\\udea3-\\\\udecc]\");'\n}\n\nsurrogate_pair: {\n    beautify = {\n        ascii_only: false,\n        module: false,\n    }\n    input: {\n        var \\u{2f800} = {\n            \\u{2f801}: \"\\u{100000}\",\n        };\n        \\u{2f800}.\\u{2f802} = \"\\u{100001}\";\n        console.log(typeof \\u{2f800}, \\u{2f800}.\\u{2f801}, \\u{2f800}[\"\\u{2f802}\"]);\n    }\n    expect_exact: 'var \\ud87e\\udc00={\"\\ud87e\\udc01\":\"\\udbc0\\udc00\"};\\ud87e\\udc00.\\ud87e\\udc02=\"\\udbc0\\udc01\";console.log(typeof \\ud87e\\udc00,\\ud87e\\udc00.\\ud87e\\udc01,\\ud87e\\udc00[\"\\ud87e\\udc02\"]);'\n    expect_stdout: \"object \\udbc0\\udc00 \\udbc0\\udc01\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\nsurrogate_pair_ecma: {\n    beautify = {\n        ascii_only: false,\n        module: true,\n    }\n    input: {\n        var \\u{2f800} = {\n            \\u{2f801}: \"\\u{100000}\",\n        };\n        \\u{2f800}.\\u{2f802} = \"\\u{100001}\";\n        console.log(typeof \\u{2f800}, \\u{2f800}.\\u{2f801}, \\u{2f800}[\"\\u{2f802}\"]);\n    }\n    expect_exact: 'var \\ud87e\\udc00={\"\\ud87e\\udc01\":\"\\udbc0\\udc00\"};\\ud87e\\udc00.\\ud87e\\udc02=\"\\udbc0\\udc01\";console.log(typeof \\ud87e\\udc00,\\ud87e\\udc00.\\ud87e\\udc01,\\ud87e\\udc00[\"\\ud87e\\udc02\"]);'\n    expect_stdout: \"object \\udbc0\\udc00 \\udbc0\\udc01\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nsurrogate_pair_ascii: {\n    beautify = {\n        ascii_only: true,\n        module: false,\n    }\n    input: {\n        var \\u{2f800} = {\n            \\u{2f801}: \"\\u{100000}\",\n        };\n        \\u{2f800}.\\u{2f802} = \"\\u{100001}\";\n        console.log(typeof \\u{2f800}, \\u{2f800}.\\u{2f801}, \\u{2f800}[\"\\u{2f802}\"]);\n    }\n    expect_exact: 'var \\\\u{2f800}={\"\\\\ud87e\\\\udc01\":\"\\\\udbc0\\\\udc00\"};\\\\u{2f800}.\\\\u{2f802}=\"\\\\udbc0\\\\udc01\";console.log(typeof \\\\u{2f800},\\\\u{2f800}.\\\\u{2f801},\\\\u{2f800}[\"\\\\ud87e\\\\udc02\"]);'\n    expect_stdout: \"object \\udbc0\\udc00 \\udbc0\\udc01\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n\nsurrogate_pair_ascii_ecma: {\n    beautify = {\n        ascii_only: true,\n        module: true,\n    }\n    input: {\n        var \\u{2f800} = {\n            \\u{2f801}: \"\\u{100000}\",\n        };\n        \\u{2f800}.\\u{2f802} = \"\\u{100001}\";\n        console.log(typeof \\u{2f800}, \\u{2f800}.\\u{2f801}, \\u{2f800}[\"\\u{2f802}\"]);\n    }\n    expect_exact: 'var \\\\u{2f800}={\"\\\\u{2f801}\":\"\\\\u{100000}\"};\\\\u{2f800}.\\\\u{2f802}=\"\\\\u{100001}\";console.log(typeof \\\\u{2f800},\\\\u{2f800}.\\\\u{2f801},\\\\u{2f800}[\"\\\\u{2f802}\"]);'\n    expect_stdout: \"object \\udbc0\\udc00 \\udbc0\\udc01\"\n    // non-BMP support is platform-dependent on Node.js v4\n    node_version: \">=6\"\n}\n"
  },
  {
    "path": "test/compress/varify.js",
    "content": "reduce_merge_const: {\n    options = {\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        const a = console;\n        console.log(typeof a);\n        var b = typeof a;\n        console.log(b);\n    }\n    expect: {\n        var a = console;\n        console.log(typeof a);\n        a = typeof a;\n        console.log(a);\n    }\n    expect_stdout: [\n        \"object\",\n        \"object\",\n    ]\n}\n\nreduce_merge_let: {\n    options = {\n        merge_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        let a = console;\n        console.log(typeof a);\n        var b = typeof a;\n        console.log(b);\n    }\n    expect: {\n        \"use strict\";\n        var a = console;\n        console.log(typeof a);\n        a = typeof a;\n        console.log(a);\n    }\n    expect_stdout: [\n        \"object\",\n        \"object\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_block_const: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        {\n            const a = typeof console;\n            console.log(a);\n        }\n    }\n    expect: {\n        var a = typeof console;\n        console.log(a);\n    }\n    expect_stdout: \"object\"\n}\n\nreduce_block_let: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let a = typeof console;\n            console.log(a);\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = typeof console;\n        console.log(a);\n    }\n    expect_stdout: \"object\"\n    node_version: \">=4\"\n}\n\nhoist_props_const: {\n    options = {\n        hoist_props: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        {\n            const o = {\n                p: \"PASS\",\n            };\n            console.log(o.p);\n        }\n    }\n    expect: {\n        var o, o_p = \"PASS\";\n        console.log(o_p);\n    }\n    expect_stdout: \"PASS\"\n}\n\nhoist_props_let: {\n    options = {\n        hoist_props: true,\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        {\n            let o = {\n                p: \"PASS\",\n            };\n            console.log(o.p);\n        }\n    }\n    expect: {\n        \"use strict\";\n        var o, o_p = \"PASS\";\n        console.log(o_p);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nscope_adjustment_const: {\n    options = {\n        conditionals: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        for (var k in [ 42 ])\n            console.log(function f() {\n                if (k) {\n                    const a = 0;\n                }\n            }());\n    }\n    expect: {\n        for (var k in [ 42 ])\n            console.log(void (k && 0));\n    }\n    expect_stdout: \"undefined\"\n}\n\nscope_adjustment_let: {\n    options = {\n        conditionals: true,\n        inline: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        for (var k in [ 42 ])\n            console.log(function f() {\n                if (k) {\n                    let a = 0;\n                }\n            }());\n    }\n    expect: {\n        \"use strict\";\n        for (var k in [ 42 ])\n            console.log(void (k && 0));\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nescaped_const: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        const log = console.log;\n        log(\"PASS\");\n    }\n    expect: {\n        var log = console.log;\n        log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n}\n\nescaped_let: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        let log = console.log;\n        log(\"PASS\");\n    }\n    expect: {\n        \"use strict\";\n        var log = console.log;\n        log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4191_const: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        const a = function() {};\n        console.log(typeof a, a());\n    }\n    expect: {\n        function a() {};\n        console.log(typeof a, a());\n    }\n    expect_stdout: \"function undefined\"\n}\n\nissue_4191_let: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        let a = function() {};\n        console.log(typeof a, a());\n    }\n    expect: {\n        \"use strict\";\n        function a() {};\n        console.log(typeof a, a());\n    }\n    expect_stdout: \"function undefined\"\n    node_version: \">=4\"\n}\n\nforin_const_1: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        const o = {\n            foo: 42,\n            bar: \"PASS\",\n        };\n        for (const k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            foo: 42,\n            bar: \"PASS\",\n        };\n        for (const k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\nforin_const_2: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        const o = {\n            p: 42,\n            q: \"PASS\",\n        };\n        for (const [ k ] in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            p: 42,\n            q: \"PASS\",\n        }, k;\n        for ([ k ] in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"p 42\",\n        \"q PASS\",\n    ]\n    node_version: \">=6\"\n}\n\nforin_const_3: {\n    options = {\n        module: true,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        const o = {\n            p: 42,\n            q: \"PASS\",\n        };\n        for (const k in o)\n            (function f() {\n                console.log(k, o[k]);\n            })();\n    }\n    expect: {\n        \"use strict\";\n        let o = {\n            p: 42,\n            q: \"PASS\",\n        };\n        for (let k in o)\n            (function f() {\n                console.log(k, o[k]);\n            })();\n    }\n    expect_stdout: [\n        \"p 42\",\n        \"q PASS\",\n    ]\n    node_version: \">=4\"\n}\n\nforin_let_1: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        let o = {\n            foo: 42,\n            bar: \"PASS\",\n        };\n        for (let k in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        \"use strict\";\n        var o = {\n            foo: 42,\n            bar: \"PASS\",\n        }, k;\n        for (k in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"foo 42\",\n        \"bar PASS\",\n    ]\n    node_version: \">=4\"\n}\n\nforin_let_2: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        let o = {\n            p: 42,\n            q: \"PASS\",\n        };\n        for (let [ k ] in o)\n            console.log(k, o[k]);\n    }\n    expect: {\n        var o = {\n            p: 42,\n            q: \"PASS\",\n        }, k;\n        for ([ k ] in o)\n            console.log(k, o[k]);\n    }\n    expect_stdout: [\n        \"p 42\",\n        \"q PASS\",\n    ]\n    node_version: \">=6\"\n}\n\nloop_scope_1: {\n    options = {\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        var o = { foo: 1, bar: 2 };\n        for (let i in o) {\n            console.log(i);\n        }\n        for (const j in o)\n            setTimeout(() => console.log(j), 0);\n        for (let k in o)\n            setTimeout(function() {\n                console.log(k);\n            }, 0);\n    }\n    expect: {\n        \"use strict\";\n        var o = { foo: 1, bar: 2 };\n        for (var i in o)\n            console.log(i);\n        for (const j in o)\n            setTimeout(() => console.log(j), 0);\n        for (let k in o)\n            setTimeout(function() {\n                console.log(k);\n            }, 0);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nloop_scope_2: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        var a = [ \"foo\", \"bar\" ];\n        for (var i = 0; i < a.length; i++) {\n            const x = a[i];\n            console.log(x);\n            let y = a[i];\n            setTimeout(() => console.log(y), 0);\n            const z = a[i];\n            setTimeout(function() {\n                console.log(z);\n            }, 0);\n        }\n    }\n    expect: {\n        \"use strict\";\n        var a = [ \"foo\", \"bar\" ];\n        for (var i = 0; i < a.length; i++) {\n            var x = a[i];\n            console.log(x);\n            let y = a[i];\n            setTimeout(() => console.log(y), 0);\n            const z = a[i];\n            setTimeout(function() {\n                console.log(z);\n            }, 0);\n        }\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"foo\",\n        \"foo\",\n        \"bar\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4290_1_const: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        const a = 0;\n        var a;\n    }\n    expect: {\n        const a = 0;\n        var a;\n    }\n    expect_stdout: true\n}\n\nissue_4290_1_let: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        let a = 0;\n        var a;\n    }\n    expect: {\n        \"use strict\";\n        let a = 0;\n        var a;\n    }\n    expect_stdout: true\n    node_version: \">=4\"\n}\n\ndrop_forin_let: {\n    options = {\n        loops: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        for (let a in console.log(\"PASS\"));\n    }\n    expect: {\n        \"use strict\";\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndefault_init: {\n    options = {\n        join_vars: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        A = \"PASS\";\n        (function() {\n            \"use strict\";\n            let a;\n            a = A;\n            console.log(a);\n        })();\n    }\n    expect: {\n        A = \"PASS\";\n        (function() {\n            \"use strict\";\n            var a = A;\n            console.log(a);\n        })();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4933_1: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        console.log(f());\n        function f() {\n            var a;\n            for (console in a = [ f ]) {\n                const b = a;\n            }\n        }\n    }\n    expect: {\n        console.log(function f() {\n            var a;\n            for (console in a = [ f ]) {\n                const b = a;\n            }\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4933_2: {\n    options = {\n        passes: 2,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        console.log(f());\n        function f() {\n            var a;\n            for (console in a = [ f ]) {\n                const b = a;\n            }\n        }\n    }\n    expect: {\n        console.log(function f() {\n            for (console in [ f ]);\n        }());\n    }\n    expect_stdout: \"undefined\"\n}\n\nissue_4954: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        (function() {\n            {\n                let a = console;\n                console.log(typeof a);\n            }\n            {\n                let a = function() {};\n                a && console.log(typeof a);\n            }\n        })();\n    }\n    expect: {\n        \"use strict\";\n        (function() {\n            var a = console;\n            console.log(typeof a);\n            {\n                let a = function() {};\n                a && console.log(typeof a);\n            }\n        })();\n    }\n    expect_stdout: [\n        \"object\",\n        \"function\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5516: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(typeof function() {\n            {\n                let a;\n            }\n            {\n                const a = function() {};\n                return a;\n            }\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(typeof function() {\n            {\n                const a = function() {};\n                return a;\n            }\n        }());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_5697_1: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        console.log(function() {\n            f();\n            return typeof a;\n            function f() {\n                (function() {\n                    for (var k in { foo: 42 }) {\n                        const a = k;\n                        console.log(a);\n                    }\n                })();\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            (function() {\n                for (var k in { foo: 42 }) {\n                    var a = k;\n                    console.log(a);\n                }\n            })();\n            return typeof a;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n}\n\nissue_5697_2: {\n    options = {\n        if_return: true,\n        inline: true,\n        reduce_vars: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function() {\n            f();\n            return typeof a;\n            function f() {\n                (function() {\n                    for (var k in { foo: 42 }) {\n                        let a = k;\n                        console.log(a);\n                    }\n                })();\n            }\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            (function() {\n                for (var k in { foo: 42 }) {\n                    var a = k;\n                    console.log(a);\n                }\n            })();\n            return typeof a;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5697_3: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        console.log(function() {\n            f();\n            return typeof a;\n            function f() {\n                (function() {\n                    for (var k in { foo: 42 }) {\n                        const a = k;\n                        console.log(a);\n                    }\n                })();\n            }\n        }());\n    }\n    expect: {\n        console.log(function() {\n            (function() {\n                for (var k in { foo: 42 }) {\n                    var a = k;\n                    console.log(a);\n                }\n            })();\n            return typeof a;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n}\n\nissue_5697_4: {\n    options = {\n        inline: true,\n        reduce_vars: true,\n        side_effects: true,\n        unused: true,\n        varify: true,\n    }\n    input: {\n        \"use strict\";\n        console.log(function() {\n            f();\n            return typeof a;\n            function f() {\n                (function() {\n                    for (var k in { foo: 42 }) {\n                        let a = k;\n                        console.log(a);\n                    }\n                })();\n            }\n        }());\n    }\n    expect: {\n        \"use strict\";\n        console.log(function() {\n            (function() {\n                for (var k in { foo: 42 }) {\n                    var a = k;\n                    console.log(a);\n                }\n            })();\n            return typeof a;\n        }());\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n"
  },
  {
    "path": "test/compress/webkit.js",
    "content": "lambda_call_dot_assign: {\n    beautify = {\n        webkit: false,\n    }\n    input: {\n        console.log(function() {\n            return {};\n        }().a = 1);\n    }\n    expect_exact: \"console.log(function(){return{}}().a=1);\"\n    expect_stdout: \"1\"\n}\n\nlambda_call_dot_assign_webkit: {\n    beautify = {\n        webkit: true,\n    }\n    input: {\n        console.log(function() {\n            return {};\n        }().a = 1);\n    }\n    expect_exact: \"console.log((function(){return{}}()).a=1);\"\n    expect_stdout: \"1\"\n}\n\nlambda_dot_assign: {\n    beautify = {\n        webkit: false,\n    }\n    input: {\n        console.log(function() {\n            1 + 1;\n        }.a = 1);\n    }\n    expect_exact: \"console.log(function(){1+1}.a=1);\"\n    expect_stdout: \"1\"\n}\n\nlambda_dot_assign_webkit: {\n    beautify = {\n        webkit: true,\n    }\n    input: {\n        console.log(function() {\n            1 + 1;\n        }.a = 1);\n    }\n    expect_exact: \"console.log((function(){1+1}).a=1);\"\n    expect_stdout: \"1\"\n}\n\nlambda_name_mangle: {\n    mangle = {}\n    input: {\n        console.log(typeof function foo(bar) {});\n    }\n    expect_exact: \"console.log(typeof function o(n){});\"\n    expect_stdout: \"function\"\n}\n\nlambda_name_mangle_ie8: {\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        console.log(typeof function foo(bar) {});\n    }\n    expect_exact: \"console.log(typeof function n(o){});\"\n    expect_stdout: \"function\"\n}\n\nfunction_name_mangle: {\n    options = {\n        keep_fnames: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {}\n    input: {\n        (function() {\n            function foo(bar) {}\n            console.log(typeof foo);\n        })();\n    }\n    expect_exact: \"(function(){console.log(typeof function o(n){})})();\"\n    expect_stdout: \"function\"\n}\n\nfunction_name_mangle_ie8: {\n    options = {\n        keep_fnames: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    mangle = {\n        ie: true,\n        toplevel: true,\n    }\n    input: {\n        (function() {\n            function foo(bar) {}\n            console.log(typeof foo);\n        })();\n    }\n    expect_exact: \"(function(){console.log(typeof function n(o){})})();\"\n    expect_stdout: \"function\"\n}\n\nissue_1753: {\n    mangle = {\n        toplevel: false,\n        webkit: true,\n    }\n    input: {\n        \"use strict\";\n        let l = null;\n        for (let i = 0; i < 1; i++)\n            console.log(i);\n    }\n    expect: {\n        \"use strict\";\n        let l = null;\n        for (let i = 0; i < 1; i++)\n            console.log(i);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=4\"\n}\n\nissue_1753_toplevel: {\n    mangle = {\n        toplevel: true,\n        webkit: true,\n    }\n    input: {\n        \"use strict\";\n        let l = null;\n        for (let i = 0; i < 1; i++)\n            console.log(i);\n    }\n    expect: {\n        \"use strict\";\n        let l = null;\n        for (let e = 0; e < 1; e++)\n            console.log(e);\n    }\n    expect_stdout: \"0\"\n    node_version: \">=4\"\n}\n\nissue_5032_await: {\n    options = {\n        merge_vars: true,\n        webkit: false,\n    }\n    input: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        async function f(a) {\n            var b = log(a), c = b;\n            log(b);\n            log(c);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        async function f(a) {\n            var a = log(a), c = a;\n            log(a);\n            log(c);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5032_await_webkit: {\n    options = {\n        merge_vars: true,\n        webkit: true,\n    }\n    input: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        async function f(a) {\n            var b = log(a), c = b;\n            log(b);\n            log(c);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        async function f(a) {\n            var b = log(a), c = b;\n            log(b);\n            log(c);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n    node_version: \">=8\"\n}\n\nissue_5032_yield: {\n    options = {\n        merge_vars: true,\n        webkit: false,\n    }\n    input: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        function *f(a) {\n            var b = log(a), c = b;\n            log(b);\n            log(c);\n        }\n        f(\"PASS\").next();\n    }\n    expect: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        function *f(a) {\n            var a = log(a), c = a;\n            log(a);\n            log(c);\n        }\n        f(\"PASS\").next();\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5032_yield_webkit: {\n    options = {\n        merge_vars: true,\n        webkit: true,\n    }\n    input: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        function *f(a) {\n            var b = log(a), c = b;\n            log(b);\n            log(c);\n        }\n        f(\"PASS\").next();\n    }\n    expect: {\n        function log(value) {\n            console.log(value);\n            return value;\n        }\n        function *f(a) {\n            var b = log(a), c = b;\n            log(b);\n            log(c);\n        }\n        f(\"PASS\").next();\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"PASS\",\n        \"PASS\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5480: {\n    mangle = {\n        webkit: true,\n    }\n    input: {\n        \"use strict\";\n        L: for (let a in console.log(\"PASS\"));\n    }\n    expect: {\n        \"use strict\";\n        o: for (let o in console.log(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n"
  },
  {
    "path": "test/compress/wrap_iife.js",
    "content": "wrap_iife: {\n    options = {\n        negate_iife: false,\n    }\n    beautify = {\n        wrap_iife: true,\n    }\n    input: {\n        (function() {\n            return function() {\n                console.log('test')\n            };\n        })()();\n    }\n    expect_exact: '(function(){return function(){console.log(\"test\")}})()();'\n}\n\nwrap_iife_in_expression: {\n    options = {\n        negate_iife: false,\n    }\n    beautify = {\n        wrap_iife: true,\n    }\n    input: {\n        foo = (function() {\n            return bar();\n        })();\n    }\n    expect_exact: 'foo=(function(){return bar()})();'\n}\n\nwrap_iife_in_return_call: {\n    options = {\n        negate_iife: false,\n    }\n    beautify = {\n        wrap_iife: true,\n    }\n    input: {\n        (function() {\n            return (function() {\n                console.log('test')\n            })();\n        })()();\n    }\n    expect_exact: '(function(){return(function(){console.log(\"test\")})()})()();'\n}\n"
  },
  {
    "path": "test/compress/yields.js",
    "content": "binary: {\n    input: {\n        var a = function*() {\n            console.log(6 * (yield \"PA\" + \"SS\"));\n        }();\n        console.log(a.next(\"FAIL\").value);\n        console.log(a.next(7).done);\n    }\n    expect_exact: 'var a=function*(){console.log(6*(yield\"PA\"+\"SS\"))}();console.log(a.next(\"FAIL\").value);console.log(a.next(7).done);'\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n        \"true\",\n    ]\n    node_version: \">=4\"\n}\n\nempty_yield: {\n    input: {\n        var a = function*() {\n            yield;\n            console.log(yield);\n            yield\n            \"FAIL 1\";\n        }();\n        console.log(a.next(\"FAIL 2\").value);\n        console.log(a.next(\"FAIL 3\").value);\n        console.log(a.next(\"PASS\").value);\n        console.log(a.next(\"FAIL 4\").done);\n    }\n    expect_exact: 'var a=function*(){yield;console.log(yield);yield;\"FAIL 1\"}();console.log(a.next(\"FAIL 2\").value);console.log(a.next(\"FAIL 3\").value);console.log(a.next(\"PASS\").value);console.log(a.next(\"FAIL 4\").done);'\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"PASS\",\n        \"undefined\",\n        \"true\",\n    ]\n    node_version: \">=4\"\n}\n\nempty_yield_conditional: {\n    input: {\n        var a = function*() {\n            console.log((yield) ? yield : yield);\n        }();\n        console.log(a.next(\"FAIL 1\").value);\n        console.log(a.next(\"FAIL 2\").value);\n        console.log(a.next(\"PASS\").value);\n        console.log(a.next(\"FAIL 3\").done);\n    }\n    expect_exact: 'var a=function*(){console.log((yield)?yield:yield)}();console.log(a.next(\"FAIL 1\").value);console.log(a.next(\"FAIL 2\").value);console.log(a.next(\"PASS\").value);console.log(a.next(\"FAIL 3\").done);'\n    expect_stdout: [\n        \"undefined\",\n        \"undefined\",\n        \"PASS\",\n        \"undefined\",\n        \"true\",\n    ]\n    node_version: \">=4\"\n}\n\nnested_yield: {\n    input: {\n        console.log(function*() {\n            (yield*\n            f())\n            function* f() {\n                return \"FAIL\";\n            }\n            yield*\n            f();\n            yield *f();\n        }().next().value || \"PASS\");\n    }\n    expect_exact: 'console.log(function*(){yield*f();function*f(){return\"FAIL\"}yield*f();yield*f()}().next().value||\"PASS\");'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\npause_resume: {\n    input: {\n        function* f() {\n            console.log(yield \"PASS\");\n        }\n        var a = f();\n        console.log(a.next(\"FAIL\").value);\n        console.log(a.next(42).done);\n    }\n    expect_exact: 'function*f(){console.log(yield\"PASS\")}var a=f();console.log(a.next(\"FAIL\").value);console.log(a.next(42).done);'\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n        \"true\",\n    ]\n    node_version: \">=4\"\n}\n\narrow_yield_1: {\n    input: {\n        yield = \"PASS\";\n        console.log(function*() {\n            return () => yield || \"FAIL\";\n        }().next().value());\n    }\n    expect_exact: 'yield=\"PASS\";console.log(function*(){return()=>yield||\"FAIL\"}().next().value());'\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\narrow_yield_2: {\n    input: {\n        console.log(typeof function *() {\n            // Syntax error on Node.js v6+\n            return (yield) => {};\n        }().next().value);\n    }\n    expect_exact: \"console.log(typeof function*(){return(yield)=>{}}().next().value);\"\n    expect_stdout: \"function\"\n    node_version: \"4\"\n}\n\nfor_of: {\n    input: {\n        function* f() {\n            if (yield \"PASS\") yield \"FAIL 1\";\n            yield 42;\n            return \"FAIL 2\";\n        }\n        for (var a of f())\n            console.log(a);\n    }\n    expect_exact: 'function*f(){if(yield\"PASS\")yield\"FAIL 1\";yield 42;return\"FAIL 2\"}for(var a of f())console.log(a);'\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=4\"\n}\n\nfor_await_of: {\n    input: {\n        async function* f() {\n            if (yield \"PASS\") yield \"FAIL 1\";\n            yield {\n                then: function(r) {\n                    r(42);\n                },\n            };\n            return \"FAIL 2\";\n        }\n        (async function(a) {\n            for await (a of f())\n                console.log(a);\n        })();\n    }\n    expect_exact: 'async function*f(){if(yield\"PASS\")yield\"FAIL 1\";yield{then:function(r){r(42)}};return\"FAIL 2\"}(async function(a){for await(a of f())console.log(a)})();'\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=10\"\n}\n\ncomment_newline: {\n    beautify = {\n        comments: \"all\",\n    }\n    input: {\n        console.log(function*() {\n            yield (\n                /* */\n                \"PASS\"\n            );\n        }().next().value);\n    }\n    expect_exact: [\n        \"console.log(function*(){\",\n        \"/* */\",\n        'yield\"PASS\"}().next().value);',\n    ]\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ncollapse_vars_1: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function*() {\n            a = \"PASS\";\n            yield 42;\n            return \"PASS\";\n        })().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function*() {\n            a = \"PASS\";\n            yield 42;\n            return \"PASS\";\n        })().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ncollapse_vars_2: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function*() {\n            yield (a = \"PASS\");\n            return \"PASS\";\n        })().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function*() {\n            yield (a = \"PASS\");\n            return \"PASS\";\n        })().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ncollapse_vars_3: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (function*() {\n            yield (a = \"PASS\", 42);\n            return \"PASS\";\n        })().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function*() {\n            yield (a = \"PASS\", 42);\n            return \"PASS\";\n        })().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ncollapse_vars_4: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var b = function*(c) {\n            return c;\n        }(a = \"PASS\");\n        console.log(a, b.next().done);\n    }\n    expect: {\n        var a = \"FAIL\";\n        var b = function*(c) {\n            return c;\n        }(a = \"PASS\");\n        console.log(a, b.next().done);\n    }\n    expect_stdout: \"PASS true\"\n    node_version: \">=4\"\n}\n\ncollapse_vars_5: {\n    options = {\n        collapse_vars: true,\n    }\n    input: {\n        var a = function* f(b, c) {\n            b = yield c = b;\n            console.log(c);\n        }(\"PASS\");\n        a.next();\n        a.next(\"FAIL\");\n    }\n    expect: {\n        var a = function* f(b, c) {\n            b = yield c = b;\n            console.log(c);\n        }(\"PASS\");\n        a.next();\n        a.next(\"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ncollapse_property_lambda: {\n    options = {\n        collapse_vars: true,\n        pure_getters: \"strict\",\n    }\n    input: {\n        console.log(function* f() {\n            f.g = () => 42;\n            return f.g();\n        }().next().value);\n    }\n    expect: {\n        console.log(function* f() {\n            return (f.g = () => 42)();\n        }().next().value);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\ndefun_name: {\n    input: {\n        function* yield() {\n            console.log(\"PASS\");\n        }\n        yield().next();\n    }\n    expect: {\n        function* yield() {\n            console.log(\"PASS\");\n        }\n        yield().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndrop_fname: {\n    rename = true\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    mangle = {\n        toplevel: true,\n    }\n    input: {\n        function* yield() {\n            console.log(\"PASS\");\n        }\n        yield().next();\n    }\n    expect: {\n        (function*() {\n            console.log(\"PASS\");\n        })().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nkeep_fname: {\n    options = {\n        keep_fnames: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function* yield() {\n            console.log(\"PASS\");\n        }\n        yield().next();\n    }\n    expect: {\n        function* yield() {\n            console.log(\"PASS\");\n        }\n        yield().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nevaluate: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = function*() {}();\n        console.log(typeof a);\n    }\n    expect: {\n        var a = function*() {}();\n        console.log(typeof a);\n    }\n    expect_stdout: \"object\"\n    node_version: \">=4\"\n}\n\nfunctions: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        !function*() {\n            var a = function* a() {\n                return a && \"a\";\n            };\n            var b = function* x() {\n                return !!x;\n            };\n            var c = function*(c) {\n                return c;\n            };\n            if (yield* c(yield* b(yield* a()))) {\n                var d = function*() {};\n                var e = function* y() {\n                    return typeof y;\n                };\n                var f = function*(f) {\n                    return f;\n                };\n                console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);\n            }\n        }().next();\n    }\n    expect: {\n        !function*() {\n            function* a() {\n                return a && \"a\";\n            }\n            function* b() {\n                return !!b;\n            }\n            function* c(c) {\n                return c;\n            }\n            if (yield* c(yield* b(yield* a()))) {\n                var d = function*() {};\n                var e = function* y() {\n                    return typeof y;\n                };\n                var f = function*(f) {\n                    return f;\n                };\n                console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);\n            }\n        }().next();\n    }\n    expect_stdout: \"a true 42 function function function\"\n    node_version: \">=4\"\n}\n\nfunctions_use_strict: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        \"use strict\";\n        !function*() {\n            var a = function* a() {\n                return a && \"a\";\n            };\n            var b = function* x() {\n                return !!x;\n            };\n            var c = function*(c) {\n                return c;\n            };\n            if (yield* c(yield* b(yield* a()))) {\n                var d = function*() {};\n                var e = function* y() {\n                    return typeof y;\n                };\n                var f = function*(f) {\n                    return f;\n                };\n                console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);\n            }\n        }().next();\n    }\n    expect: {\n        \"use strict\";\n        !function*() {\n            function* a() {\n                return a && \"a\";\n            }\n            function* b() {\n                return !!b;\n            }\n            function* c(c) {\n                return c;\n            }\n            if (yield* c(yield* b(yield* a()))) {\n                var d = function*() {};\n                var e = function* y() {\n                    return typeof y;\n                };\n                var f = function*(f) {\n                    return f;\n                };\n                console.log(yield* a(yield* d()), yield* b(yield* e()), yield* c(yield* f(42)), typeof d, yield* e(), typeof f);\n            }\n        }().next();\n    }\n    expect_stdout: \"a true 42 function function function\"\n    node_version: \">=4\"\n}\n\nfunctions_anonymous: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var yield = function*() {\n            return \"PASS\";\n        };\n        console.log(yield().next(yield).value);\n    }\n    expect: {\n        function* yield() {\n            return \"PASS\";\n        }\n        console.log(yield().next(yield).value);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nfunctions_inner_var: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var yield = function* a() {\n            var a;\n            console.log(a, a);\n        };\n        yield().next(yield);\n    }\n    expect: {\n        function* yield() {\n            var a;\n            console.log(a, a);\n        }\n        yield().next(yield);\n    }\n    expect_stdout: \"undefined undefined\"\n    node_version: \">=4\"\n}\n\nnegate_iife: {\n    options = {\n        negate_iife: true,\n        side_effects: true,\n    }\n    input: {\n        (function*(a) {\n            console.log(a);\n        })(\"PASS\").next();\n    }\n    expect: {\n        !function*(a) {\n            console.log(a);\n        }(\"PASS\").next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nreduce_iife_1: {\n    options = {\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function*(a) {\n            yield a;\n        }(42).next().value);\n    }\n    expect: {\n        console.log(function*(a) {\n            yield 42;\n        }().next().value);\n    }\n    expect_stdout: \"42\"\n    node_version: \">=4\"\n}\n\nreduce_iife_2: {\n    options = {\n        evaluate: true,\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var a = \"PASS\";\n        (function*() {\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        (function*() {\n            a = \"FAIL\";\n        })();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nreduce_single_use_defun: {\n    options = {\n        reduce_vars: true,\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        function* f(a) {\n            console.log(a);\n        }\n        f(\"PASS\").next();\n    }\n    expect: {\n        (function*(a) {\n            console.log(a);\n        })(\"PASS\").next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nreduce_tagged: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        function* f() {\n            function g() {\n                h`foo`;\n            }\n            g();\n            function h(s) {\n                console.log(s[0]);\n            }\n            h([ \"bar\" ]);\n        }\n        f().next();\n    }\n    expect: {\n        function* f() {\n            (function() {\n                h`foo`;\n            })();\n            function h(s) {\n                console.log(s[0]);\n            }\n            h([ \"bar\" ]);\n        }\n        f().next();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=4\"\n}\n\nreduce_tagged_async: {\n    options = {\n        reduce_funcs: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        async function* f() {\n            function g() {\n                h`foo`;\n            }\n            g();\n            function h(s) {\n                console.log(s[0]);\n            }\n            h([ \"bar\" ]);\n        }\n        f().next();\n    }\n    expect: {\n        async function* f() {\n            (function() {\n                h`foo`;\n            })();\n            function h(s) {\n                console.log(s[0]);\n            }\n            h([ \"bar\" ]);\n        }\n        f().next();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=10\"\n}\n\nlift_sequence: {\n    options = {\n        sequences: true,\n        yields: true,\n    }\n    input: {\n        console.log(function*() {\n            yield (console, \"PASS\");\n        }().next().value);\n    }\n    expect: {\n        console.log(function*() {\n            console, yield \"PASS\";\n        }().next().value);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ninline_nested: {\n    options = {\n        inline: true,\n        sequences: true,\n        yields: true,\n    }\n    input: {\n        var a = function*() {\n            yield* function*() {\n                yield \"foo\";\n                return \"FAIL\";\n            }();\n        }(), b;\n        do {\n            b = a.next();\n            console.log(b.value);\n        } while (!b.done);\n    }\n    expect: {\n        var a = function*() {\n            yield \"foo\",\n            \"FAIL\";\n        }(), b;\n        do {\n            b = a.next(),\n            console.log(b.value);\n        } while (!b.done);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\ninline_nested_async: {\n    options = {\n        awaits: true,\n        inline: true,\n        sequences: true,\n        side_effects: true,\n        yields: true,\n    }\n    input: {\n        console.log(\"foo\");\n        var a = async function*() {\n            console.log(await(yield* async function*() {\n                yield {\n                    then: r => r(\"bar\"),\n                };\n                return \"baz\";\n            }()));\n        }();\n        console.log(\"moo\");\n        a.next().then(function f(b) {\n            console.log(b.value);\n            b.done || a.next().then(f);\n        });\n        console.log(\"moz\");\n    }\n    expect: {\n        console.log(\"foo\");\n        var a = async function*() {\n            console.log((yield {\n                then: r => r(\"bar\"),\n            }, await \"baz\"));\n        }();\n        console.log(\"moo\"),\n        a.next().then(function f(b) {\n            console.log(b.value),\n            b.done || a.next().then(f);\n        }),\n        console.log(\"moz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"moo\",\n        \"moz\",\n        \"bar\",\n        \"baz\",\n        \"undefined\",\n    ]\n    node_version: \">=10\"\n}\n\ninline_nested_block: {\n    options = {\n        if_return: true,\n        inline: true,\n        yields: true,\n    }\n    input: {\n        var a = function*() {\n            yield* function*() {\n                for (var a of [ \"foo\", \"bar\" ])\n                    yield a;\n                return \"FAIL\";\n            }();\n        }(), b;\n        do {\n            b = a.next();\n            console.log(b.value);\n        } while (!b.done);\n    }\n    expect: {\n        var a = function*() {\n            for (var a of [ \"foo\", \"bar\" ])\n                yield a;\n            \"FAIL\";\n        }(), b;\n        do {\n            b = a.next();\n            console.log(b.value);\n        } while (!b.done);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"undefined\",\n    ]\n    node_version: \">=4\"\n}\n\ndont_inline_nested: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var yield = \"PASS\";\n        (function*() {\n            (function() {\n                console.log(yield);\n            })();\n        })().next();\n    }\n    expect: {\n        var yield = \"PASS\";\n        (function*() {\n            (function() {\n                console.log(yield);\n            })();\n        })().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ndrop_body_1: {\n    options = {\n        side_effects: true,\n        yields: true,\n    }\n    input: {\n        (function*([ , a = console.log(\"foo\") ]) {\n            console.log(\"bar\");\n        })([ console.log(\"baz\") ]);\n    }\n    expect: {\n        void ([ [ , [][0] = console.log(\"foo\") ] ] = [ [ console.log(\"baz\") ] ]);\n    }\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n    ]\n    node_version: \">=6\"\n}\n\ndrop_body_2: {\n    options = {\n        passes: 2,\n        side_effects: true,\n        yields: true,\n    }\n    input: {\n        (function*([ , a = console.log(\"foo\") ]) {\n            console.log(\"bar\");\n        })([ console.log(\"baz\") ]);\n    }\n    expect: {\n        [ [ , [][0] = console.log(\"foo\") ] ] = [ [ console.log(\"baz\") ] ];\n    }\n    expect_stdout: [\n        \"baz\",\n        \"foo\",\n    ]\n    node_version: \">=6\"\n}\n\ndrop_unused_call: {\n    options = {\n        inline: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a = function*(){}(console.log(\"PASS\"));\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\ninstanceof_lambda: {\n    options = {\n        evaluate: true,\n        side_effects: true,\n    }\n    input: {\n        console.log(42 instanceof function*() {});\n    }\n    expect: {\n        console.log(false);\n    }\n    expect_stdout: \"false\"\n    node_version: \">=4\"\n}\n\nkeep_yield: {\n    options = {\n        arrows: true,\n        module: true,\n    }\n    input: {\n        console.log(function*() {\n            yield \"PASS\";\n        }().next().value);\n    }\n    expect: {\n        console.log(function*() {\n            yield \"PASS\";\n        }().next().value);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nfunc_to_arrow_arg: {\n    options = {\n        arrows: true,\n        module: true,\n    }\n    input: {\n        console.log(function(yield) {\n            return yield;\n        }(\"PASS\"));\n    }\n    expect: {\n        console.log((yield => yield)(\"PASS\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nfunc_to_arrow_var: {\n    options = {\n        arrows: true,\n        module: true,\n    }\n    input: {\n        var yield = \"PASS\";\n        console.log(function() {\n            return yield;\n        }());\n    }\n    expect: {\n        var yield = \"PASS\";\n        console.log((() => yield)());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4454_1: {\n    rename = false\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            (function*(b = console.log(a)) {})();\n            var yield = 42..toString();\n            console.log(yield);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function f(a) {\n            (function*(b = console.log(a)) {})();\n            var yield = 42..toString();\n            console.log(yield);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4454_2: {\n    rename = true\n    options = {\n        merge_vars: true,\n    }\n    input: {\n        function f(a) {\n            (function*(b = console.log(a)) {})();\n            var yield = 42..toString();\n            console.log(yield);\n        }\n        f(\"PASS\");\n    }\n    expect: {\n        function f(a) {\n            (function*(c = console.log(a)) {})();\n            var b = 42..toString();\n            console.log(b);\n        }\n        f(\"PASS\");\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"42\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_4618: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(typeof function() {\n            var yield = function* f() {\n                console || f();\n            };\n            console.log;\n            return yield;\n        }());\n    }\n    expect: {\n        console.log(typeof function() {\n            var yield = function* f() {\n                console || f();\n            };\n            console.log;\n            return yield;\n        }());\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_4623: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        if (console ? function*() {} : 0)\n            console.log(\"PASS\");\n    }\n    expect: {\n        (console ? function*() {} : 0) && console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_4633: {\n    options = {\n        collapse_vars: true,\n        unused: true,\n    }\n    input: {\n        var a = function*() {\n            (function(log) {\n                log(typeof this);\n            })(yield \"PASS\");\n        }();\n        console.log(a.next().value);\n        a.next(console.log);\n    }\n    expect: {\n        var a = function*() {\n            (function(log) {\n                log(typeof this);\n            })(yield \"PASS\");\n        }();\n        console.log(a.next().value);\n        a.next(console.log);\n    }\n    expect_stdout: [\n        \"PASS\",\n        \"object\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_4639_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function*() {\n            return function() {\n                return yield => \"PASS\";\n            }();\n        }().next().value());\n    }\n    expect: {\n        console.log(function*() {\n            return function() {\n                return yield => \"PASS\";\n            }();\n        }().next().value());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4 <7 || >=8.7.0\"\n}\n\nissue_4639_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (function*() {\n            console.log(function() {\n                return typeof yield;\n            }());\n        })().next();\n    }\n    expect: {\n        (function*() {\n            console.log(function() {\n                return typeof yield;\n            }());\n        })().next();\n    }\n    expect_stdout: \"undefined\"\n    node_version: \">=4\"\n}\n\nissue_4641_1: {\n    options = {\n        sequences: true,\n    }\n    input: {\n        console.log(typeof async function*() {\n            try {\n                console.log(\"foo\");\n                return;\n            } finally {\n                console.log(\"bar\");\n            }\n        }().next().then);\n    }\n    expect: {\n        console.log(typeof async function*() {\n            try {\n                console.log(\"foo\");\n                return;\n            } finally {\n                console.log(\"bar\");\n            }\n        }().next().then);\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"function\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_4641_2: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console.log(typeof async function*() {\n            try {\n                return void \"FAIL\";\n            } finally {\n                console.log(\"PASS\");\n            }\n        }().next().then);\n    }\n    expect: {\n        console.log(typeof async function*() {\n            try {\n                return void 0;\n            } finally {\n                console.log(\"PASS\");\n            }\n        }().next().then);\n    }\n    expect_stdout: [\n        \"function\",\n        \"PASS\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_4641_3: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        console.log(typeof async function*() {\n            try {\n                return void \"FAIL\";\n            } finally {\n                console.log(\"PASS\");\n            }\n        }().next().then);\n    }\n    expect: {\n        console.log(typeof async function*() {\n            try {\n                return void \"FAIL\";\n            } finally {\n                console.log(\"PASS\");\n            }\n        }().next().then);\n    }\n    expect_stdout: [\n        \"function\",\n        \"PASS\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_4769_1: {\n    options = {\n        side_effects: true,\n    }\n    input: {\n        console.log(function*() {\n            (function({} = yield => {}) {})();\n        }().next().done);\n    }\n    expect: {\n        console.log(function*() {\n            (function({} = yield => {}) {})();\n        }().next().done);\n    }\n    expect_stdout: \"true\"\n    node_version: \">=6\"\n}\n\nissue_4769_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        console.log(function*() {\n            return function({} = yield => {}) {\n                return \"PASS\";\n            }();\n        }().next().value);\n    }\n    expect: {\n        console.log(function*() {\n            return function({} = yield => {}) {\n                return \"PASS\";\n            }();\n        }().next().value);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5019_1: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        (function(a) {\n            return a = function*() {\n                console.log(typeof a);\n            }();\n        })().next();\n    }\n    expect: {\n        (function(a) {\n            return a = function*() {\n                console.log(typeof a);\n            }();\n        })().next();\n    }\n    expect_stdout: \"object\"\n    node_version: \">=4\"\n}\n\nissue_5019_2: {\n    options = {\n        inline: true,\n        toplevel: true,\n    }\n    input: {\n        var a = [];\n        for (var b in \"foo\")\n            a.push(function(c) {\n                return function*() {\n                    console.log(c);\n                }();\n            }(b));\n        a.map(function(d) {\n            return d.next();\n        });\n    }\n    expect: {\n        var a = [];\n        for (var b in \"foo\")\n            a.push(function(c) {\n                return function*() {\n                    console.log(c);\n                }();\n            }(b));\n        a.map(function(d) {\n            return d.next();\n        });\n    }\n    expect_stdout: [\n        \"0\",\n        \"1\",\n        \"2\",\n    ]\n    node_version: \">=4\"\n}\n\nissue_5034: {\n    options = {\n        functions: true,\n        reduce_vars: true,\n        unused: true,\n    }\n    input: {\n        console.log(function() {\n            var yield = function f() {\n                return function*() {\n                    return f;\n                };\n            };\n            return yield()().next().value === yield;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect: {\n        console.log(function() {\n            var yield = function f() {\n                return function*() {\n                    return f;\n                };\n            };\n            return yield()().next().value === yield;\n        }() ? \"PASS\" : \"FAIL\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5076_1: {\n    options = {\n        evaluate: true,\n        hoist_vars: true,\n        keep_fargs: false,\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a;\n        console.log(\"PASS\");\n        var b = function*({\n            p: {},\n        }) {}({\n            p: { a } = 42,\n        });\n    }\n    expect: {\n        var a;\n        console.log(\"PASS\"),\n        a = 42..a;\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5076_2: {\n    options = {\n        evaluate: true,\n        hoist_vars: true,\n        keep_fargs: false,\n        passes: 2,\n        pure_getters: \"strict\",\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a;\n        console.log(\"PASS\");\n        var b = function*({\n            p: {},\n        }) {}({\n            p: { a } = 42,\n        });\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5177: {\n    options = {\n        properties: true,\n    }\n    input: {\n        console.log(typeof function*() {\n            return {\n                p(yield) {},\n            }.p;\n        }().next().value);\n    }\n    expect: {\n        console.log(typeof function*() {\n            return {\n                p(yield) {},\n            }.p;\n        }().next().value);\n    }\n    expect_stdout: \"function\"\n    node_version: \">=4\"\n}\n\nissue_5385_1: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function*() {\n            (function() {\n                try {\n                    return console.log(\"foo\");\n                } finally {\n                    return console.log(\"bar\");\n                }\n                console.log(\"baz\");\n            })();\n        })().next();\n        console.log(\"moo\");\n    }\n    expect: {\n        (async function*() {\n            (function() {\n                try {\n                    return console.log(\"foo\");\n                } finally {\n                    return console.log(\"bar\");\n                }\n                console.log(\"baz\");\n            })();\n        })().next();\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5385_2: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function*() {\n            return function() {\n                try {\n                    return console.log(\"foo\");\n                } finally {\n                    return console.log(\"bar\");\n                }\n            }();\n        })().next();\n        console.log(\"moo\");\n    }\n    expect: {\n        (async function*() {\n            return function() {\n                try {\n                    return console.log(\"foo\");\n                } finally {\n                    return console.log(\"bar\");\n                }\n            }();\n        })().next();\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5385_3: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function*() {\n            return function() {\n                try {\n                    throw console.log(\"foo\");\n                } catch (e) {\n                    return console.log(\"bar\");\n                }\n            }();\n        })().next();\n        console.log(\"moo\");\n    }\n    expect: {\n        (async function*() {\n            try {\n                throw console.log(\"foo\");\n            } catch (e) {\n                return console.log(\"bar\");\n            }\n            return void 0;\n        })().next();\n        console.log(\"moo\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"moo\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5385_4: {\n    options = {\n        awaits: true,\n        inline: true,\n    }\n    input: {\n        (async function*() {\n            return async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            resolve(console.log(\"FAIL\"));\n                        },\n                    };\n                } finally {\n                    return \"PASS\";\n                }\n            }();\n        })().next().then(o => console.log(o.value, o.done));\n    }\n    expect: {\n        (async function*() {\n            return async function() {\n                try {\n                    return {\n                        then(resolve) {\n                            resolve(console.log(\"FAIL\"));\n                        },\n                    };\n                } finally {\n                    return \"PASS\";\n                }\n            }();\n        })().next().then(o => console.log(o.value, o.done));\n    }\n    expect_stdout: \"PASS true\"\n    node_version: \">=10\"\n}\n\nissue_5425: {\n    options = {\n        assignments: true,\n        ie: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        var b = function* f() {}(a ? a = \"PASS\" : 42);\n        console.log(a, typeof f);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (function* f() {})(a && (a = \"PASS\"));\n        console.log(a, typeof f);\n    }\n    expect_stdout: \"PASS undefined\"\n    node_version: \">=4\"\n}\n\nissue_5456: {\n    options = {\n        inline: true,\n        merge_vars: true,\n    }\n    input: {\n        var a = true;\n        (function() {\n            (function(b, c) {\n                var d = function*() {\n                    c = null;\n                }();\n                var e = function() {\n                    if (c)\n                        console.log(typeof d);\n                    while (b);\n                }();\n            })(function(i) {\n                return console.log(\"foo\") && i;\n            }(a));\n        })();\n    }\n    expect: {\n        var a = true;\n        (function() {\n            b = (i = a, console.log(\"foo\") && i),\n            d = function*() {\n                c = null;\n            }(),\n            e = function() {\n                if (c) console.log(typeof d);\n                while (b);\n            }(),\n            void 0;\n            var b, c, d, e;\n            var i;\n        })();\n    }\n    expect_stdout: \"foo\"\n    node_version: \">=4\"\n}\n\nissue_5506: {\n    options = {\n        dead_code: true,\n    }\n    input: {\n        console.log(function(a) {\n            var b = function*() {\n                a = null in (a = \"PASS\");\n            }();\n            try {\n                b.next();\n            } catch (e) {\n                return a;\n            }\n        }(\"FAIL\"));\n    }\n    expect: {\n        console.log(function(a) {\n            var b = function*() {\n                a = null in (a = \"PASS\");\n            }();\n            try {\n                b.next();\n            } catch (e) {\n                return a;\n            }\n        }(\"FAIL\"));\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5526: {\n    options = {\n        inline: true,\n        side_effects: true,\n    }\n    input: {\n        (async function*() {\n            try {\n                return function() {\n                    while (console.log(\"foo\"));\n                }();\n            } finally {\n                console.log(\"bar\");\n            }\n        })().next();\n        console.log(\"baz\");\n    }\n    expect: {\n        (async function*() {\n            try {\n                while (console.log(\"foo\"));\n                return void 0;\n            } finally {\n                console.log(\"bar\");\n            }\n        })().next();\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"baz\",\n        \"bar\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5576: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function*() {\n            try {\n                (function() {\n                    while (console.log(\"foo\"));\n                })();\n            } finally {\n                console.log(\"bar\");\n            }\n        })().next();\n        console.log(\"baz\");\n    }\n    expect: {\n        (async function*() {\n            try {\n                while (console.log(\"foo\"));\n            } finally {\n                console.log(\"bar\");\n            }\n        })().next();\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5663: {\n    options = {\n        toplevel: true,\n        unused: true,\n    }\n    input: {\n        var [ , a ] = function*() {\n            console.log(\"foo\");\n            yield console.log(\"bar\");\n            console.log(\"baz\");\n            yield console.log(\"moo\");\n            console.log(\"moz\");\n            yield FAIL;\n        }();\n    }\n    expect: {\n        var [ , , ] = function*() {\n            console.log(\"foo\");\n            yield console.log(\"bar\");\n            console.log(\"baz\");\n            yield console.log(\"moo\");\n            console.log(\"moz\");\n            yield FAIL;\n        }();\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n        \"baz\",\n        \"moo\",\n    ]\n    node_version: \">=6\"\n}\n\nissue_5679_1: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return;\n                else\n                    return;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                b;\n                return;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5679_2: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return undefined;\n                else\n                    return;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return void 0;\n                return;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5679_3: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return;\n                else\n                    return undefined;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f(42).next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return;\n                return void 0;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f(42).next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5679_4: {\n    options = {\n        conditionals: true,\n    }\n    input: {\n        var a = \"PASS\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return undefined;\n                else\n                    return undefined;\n            } finally {\n                a = \"FAIL\";\n            }\n        }\n        f(null).next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        async function* f(b) {\n            try {\n                return b, void 0;\n            } finally {\n                a = \"FAIL\";\n            }\n        }\n        f(null).next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5679_5: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return console;\n                else\n                    return;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return console;\n                return;\n            } finally {\n                a = \"PASS\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5679_6: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        var a = \"PASS\";\n        async function* f(b) {\n            try {\n                if (b)\n                    return;\n                else\n                    return console;\n            } finally {\n                a = \"FAIL\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"PASS\";\n        async function* f(b) {\n            try {\n                if (!b)\n                    return console;\n            } finally {\n                a = \"FAIL\";\n            }\n        }\n        f().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5684: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        (async function*() {\n            switch (42) {\n              default:\n                if (console.log(\"PASS\"))\n                    return;\n                return null;\n              case false:\n            }\n        })().next();\n    }\n    expect: {\n        (async function*() {\n            switch (42) {\n              default:\n                return console.log(\"PASS\") ? void 0 : null;\n              case false:\n            }\n        })().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5707_1: {\n    options = {\n        hoist_props: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a, b;\n        function* f(c = (b = 42, console.log(\"PASS\"))) {}\n        b = f();\n    }\n    expect: {\n        (function(c = console.log(\"PASS\")) {})();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5707_2: {\n    options = {\n        hoist_props: true,\n        passes: 2,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a, b;\n        function* f(c = (b = 42, console.log(\"PASS\"))) {}\n        b = f();\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=6\"\n}\n\nissue_5710: {\n    options = {\n        conditionals: true,\n        if_return: true,\n    }\n    input: {\n        (async function*() {\n            try {\n                switch (42) {\n                  case 42:\n                    {\n                        if (console.log(\"PASS\"))\n                            return;\n                        return null;\n                    }\n                    break;\n                }\n            } finally {}\n        })().next();\n    }\n    expect: {\n        (async function*() {\n            try {\n                switch (42) {\n                  case 42:\n                    if (console.log(\"PASS\"))\n                        return;\n                    return null;\n                    break;\n                }\n            } finally {}\n        })().next();\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5749_1: {\n    options = {\n        collapse_vars: true,\n        reduce_vars: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a;\n        function* f() {}\n        a = f(new function() {\n            var b = a |= 0, c = a += console.log(\"PASS\");\n        }());\n    }\n    expect: {\n        (function() {})(function() {\n            console.log(\"PASS\");\n        }());\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5749_2: {\n    options = {\n        collapse_vars: true,\n        inline: true,\n        reduce_vars: true,\n        sequences: true,\n        side_effects: true,\n        toplevel: true,\n        unused: true,\n        yields: true,\n    }\n    input: {\n        var a;\n        function* f() {}\n        a = f(new function() {\n            var b = a |= 0, c = a += console.log(\"PASS\");\n        }());\n    }\n    expect: {\n        console.log(\"PASS\");\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=4\"\n}\n\nissue_5754: {\n    options = {\n        if_return: true,\n    }\n    input: {\n        async function* f(a, b) {\n            try {\n                if (a)\n                    return void 0;\n            } finally {\n                console.log(b);\n            }\n        }\n        f(42, \"foo\").next();\n        f(null, \"bar\").next();\n        console.log(\"baz\");\n    }\n    expect: {\n        async function* f(a, b) {\n            try {\n                if (a)\n                    return void 0;\n            } finally {\n                console.log(b);\n            }\n        }\n        f(42, \"foo\").next();\n        f(null, \"bar\").next();\n        console.log(\"baz\");\n    }\n    expect_stdout: [\n        \"bar\",\n        \"baz\",\n        \"foo\",\n    ]\n    node_version: \">=10\"\n}\n\nissue_5842: {\n    options = {\n        inline: true,\n    }\n    input: {\n        var a = \"FAIL\";\n        (async function*() {\n            (function() {\n                try {\n                    try {\n                        return console;\n                    } finally {\n                        a = \"PASS\";\n                    }\n                } catch (e) {}\n                FAIL;\n            })();\n        })().next();\n        console.log(a);\n    }\n    expect: {\n        var a = \"FAIL\";\n        (async function*() {\n            (function() {\n                try {\n                    try {\n                        return console;\n                    } finally {\n                        a = \"PASS\";\n                    }\n                } catch (e) {}\n                FAIL;\n            })();\n        })().next();\n        console.log(a);\n    }\n    expect_stdout: \"PASS\"\n    node_version: \">=10\"\n}\n\nissue_5956: {\n    options = {\n        inline: true,\n    }\n    input: {\n        (async function*() {\n            (function() {\n                try {\n                    FAIL;\n                } finally {\n                    try {\n                        return console;\n                    } finally {\n                        console.log(\"foo\");\n                    }\n                }\n            })();\n        })().next();\n        console.log(\"bar\");\n    }\n    expect: {\n        (async function*() {\n            (function() {\n                try {\n                    FAIL;\n                } finally {\n                    try {\n                        return console;\n                    } finally {\n                        console.log(\"foo\");\n                    }\n                }\n            })();\n        })().next();\n        console.log(\"bar\");\n    }\n    expect_stdout: [\n        \"foo\",\n        \"bar\",\n    ]\n    node_version: \">=10\"\n}\n"
  },
  {
    "path": "test/compress.js",
    "content": "\"use strict\";\n\nrequire(\"../tools/tty\");\n\nvar assert = require(\"assert\");\nvar child_process = require(\"child_process\");\nvar fs = require(\"fs\");\nvar path = require(\"path\");\nvar sandbox = require(\"./sandbox\");\nvar semver = require(\"semver\");\nvar U = require(\"./node\");\n\nvar batch = 50;\nvar dir = path.resolve(path.dirname(module.filename), \"compress\");\nif (process.argv.length > 3) {\n    var file = process.argv[2];\n    var start = process.argv[3] | 0;\n    var minify_options = require(\"./ufuzz/options.json\").map(JSON.stringify);\n    var tests = parse_test(path.resolve(dir, file));\n    process.exit(Object.keys(tests).slice(start, start + batch).filter(function(name) {\n        return !test_case(tests[name]);\n    }).length);\n} else {\n    var files = process.argv.length == 3 ? [ process.argv[2] ] : fs.readdirSync(dir).filter(function(name) {\n        return /\\.js$/i.test(name);\n    });\n    var failures = 0;\n    var failed_files = Object.create(null);\n    (function next(file, start, length) {\n        if (start < length) {\n            child_process.spawn(process.argv[0], [ process.argv[1], file, start, batch ], {\n                stdio: [ \"ignore\", 1, 2 ]\n            }).on(\"exit\", function(code) {\n                if (code) {\n                    failures += code;\n                    failed_files[file] = true;\n                }\n                next(file, start + batch, length);\n            });\n        } else if (file = files.shift()) {\n            log(\"--- {file}\", { file: file });\n            start = 0;\n            length = Object.keys(parse_test(path.resolve(dir, file))).length;\n            next(file, start, length);\n        } else if (failures) {\n            console.error();\n            console.error(\"!!! Failed \" + failures + \" test case(s).\");\n            console.error(\"!!! \" + Object.keys(failed_files).join(\", \"));\n            process.exit(1);\n        }\n    })();\n}\n\nfunction evaluate(code) {\n    if (code instanceof U.AST_Node) code = make_code(code, { beautify: true });\n    return new Function(\"return(\" + code + \")\")();\n}\n\nfunction log() {\n    console.log(\"%s\", tmpl.apply(null, arguments));\n}\n\nfunction make_code(ast, options, expression) {\n    var stream = U.OutputStream(options);\n    if (expression) ast = ast.clone(true).unwrap_expression();\n    ast.print(stream);\n    return stream.get();\n}\n\nfunction parse_test(file) {\n    var script = fs.readFileSync(file, \"utf8\");\n    try {\n        var ast = U.parse(script, { filename: file, module: \"\" });\n    } catch (e) {\n        console.error(\"Caught error while parsing tests in \" + file);\n        console.error(e);\n        process.exit(1);\n    }\n    var tests = Object.create(null);\n    var tw = new U.TreeWalker(function(node, descend) {\n        if (node instanceof U.AST_LabeledStatement\n            && tw.parent() instanceof U.AST_Toplevel) {\n            var name = node.label.name;\n            if (name in tests) {\n                throw new Error('Duplicated test name \"' + name + '\" in ' + file);\n            }\n            tests[name] = get_one_test(name, node.body);\n            return true;\n        }\n        if (!(node instanceof U.AST_Toplevel)) croak(node);\n    });\n    ast.walk(tw);\n    return tests;\n\n    function croak(node) {\n        throw new Error(tmpl(\"Can't understand test file {file} [{line},{col}]\\n{code}\", {\n            file: file,\n            line: node.start.line,\n            col: node.start.col,\n            code: make_code(node, { beautify: false }),\n        }));\n    }\n\n    function read_string(stat) {\n        if (stat.TYPE == \"SimpleStatement\") {\n            var body = stat.body;\n            switch (body.TYPE) {\n              case \"String\":\n                return body.value;\n              case \"Array\":\n                return body.elements.map(function(element) {\n                    if (element.TYPE !== \"String\")\n                        throw new Error(\"Should be array of strings\");\n                    return element.value;\n                }).join(\"\\n\");\n            }\n        }\n        throw new Error(\"Should be string or array of strings\");\n    }\n\n    function get_one_test(name, block) {\n        var test = { name: name, options: {} };\n        var tw = new U.TreeWalker(function(node, descend) {\n            if (node instanceof U.AST_Assign) {\n                if (!(node.left instanceof U.AST_SymbolRef)) {\n                    croak(node);\n                }\n                var name = node.left.name;\n                assert.ok([\n                    \"beautify\",\n                    \"expression\",\n                    \"mangle\",\n                    \"options\",\n                    \"rename\",\n                ].indexOf(name) >= 0, tmpl(\"Unsupported setting {name} [{line},{col}]\", {\n                    name: name,\n                    line: node.start.line,\n                    col: node.start.col,\n                }));\n                test[name] = evaluate(node.right);\n                return true;\n            }\n            if (node instanceof U.AST_LabeledStatement) {\n                var label = node.label;\n                assert.ok([\n                    \"input\",\n                    \"expect\",\n                    \"expect_exact\",\n                    \"expect_warnings\",\n                    \"expect_stdout\",\n                    \"node_version\",\n                ].indexOf(label.name) >= 0, tmpl(\"Unsupported label {name} [{line},{col}]\", {\n                    name: label.name,\n                    line: label.start.line,\n                    col: label.start.col,\n                }));\n                var stat = node.body;\n                if (label.name == \"expect_exact\" || label.name == \"node_version\") {\n                    test[label.name] = read_string(stat);\n                } else if (label.name == \"expect_stdout\") {\n                    var body = stat.body;\n                    if (body instanceof U.AST_Boolean) {\n                        test[label.name] = body.value;\n                    } else if (body instanceof U.AST_Call) {\n                        var ctor = global[body.expression.name];\n                        assert.ok(ctor === Error || ctor.prototype instanceof Error, tmpl(\"Unsupported expect_stdout format [{line},{col}]\", {\n                            line: label.start.line,\n                            col: label.start.col,\n                        }));\n                        test[label.name] = ctor.apply(null, body.args.map(function(node) {\n                            assert.ok(node instanceof U.AST_Constant, tmpl(\"Unsupported expect_stdout format [{line},{col}]\", {\n                                line: label.start.line,\n                                col: label.start.col,\n                            }));\n                            return node.value;\n                        }));\n                    } else {\n                        test[label.name] = read_string(stat) + \"\\n\";\n                    }\n                } else {\n                    test[label.name] = stat;\n                }\n                return true;\n            }\n        });\n        block.walk(tw);\n        return test;\n    }\n}\n\n// Try to reminify original input with standard options\n// to see if it matches expect_stdout.\nfunction reminify(expression, orig_options, input_code, input_formatted, stdout) {\n    for (var i = 0; i < minify_options.length; i++) {\n        var options = JSON.parse(minify_options[i]);\n        if (expression) {\n            if (!options.parse || typeof options.parse != \"object\") options.parse = {};\n            options.parse.expression = true;\n            if (options.compress == null) options.compress = {};\n            if (options.compress) {\n                if (typeof options.compress != \"object\") options.compress = {};\n                options.compress.expression = true;\n            }\n        }\n        [\n            \"keep_fargs\",\n            \"keep_fnames\",\n        ].forEach(function(name) {\n            if (name in orig_options) options[name] = orig_options[name];\n        });\n        var options_formatted = JSON.stringify(options, null, 4);\n        options.validate = true;\n        var result = U.minify(input_code, options);\n        if (result.error) {\n            log([\n                \"!!! failed input reminify\",\n                \"---INPUT---\",\n                \"{input}\",\n                \"---OPTIONS---\",\n                \"{options}\",\n                \"--ERROR---\",\n                \"{error}\",\n                \"\",\n                \"\",\n            ].join(\"\\n\"), {\n                input: input_formatted,\n                options: options_formatted,\n                error: result.error,\n            });\n            return false;\n        } else {\n            var toplevel = sandbox.has_toplevel(options);\n            var expected = stdout[toplevel ? 1 : 0];\n            var actual = run_code(expression, result.code, toplevel);\n            if (typeof expected != \"string\" && typeof actual != \"string\" && expected.name == actual.name) {\n                actual = expected;\n            }\n            if (!sandbox.same_stdout(expected, actual)) {\n                log([\n                    \"!!! failed running reminified input\",\n                    \"---INPUT---\",\n                    \"{input}\",\n                    \"---OPTIONS---\",\n                    \"{options}\",\n                    \"---OUTPUT---\",\n                    \"{output}\",\n                    \"---EXPECTED {expected_type}---\",\n                    \"{expected}\",\n                    \"---ACTUAL {actual_type}---\",\n                    \"{actual}\",\n                    \"\",\n                    \"\",\n                ].join(\"\\n\"), {\n                    input: input_formatted,\n                    options: options_formatted,\n                    output: result.code,\n                    expected_type: typeof expected == \"string\" ? \"STDOUT\" : \"ERROR\",\n                    expected: expected,\n                    actual_type: typeof actual == \"string\" ? \"STDOUT\" : \"ERROR\",\n                    actual: actual,\n                });\n                return false;\n            }\n        }\n    }\n    return true;\n}\n\nfunction run_code(expression, code, toplevel) {\n    return sandbox.run_code(expression ? \"console.log(\" + code + \");\" : code, toplevel);\n}\n\nfunction test_case(test) {\n    log(\"    Running test [{name}]\", { name: test.name });\n    U.AST_Node.enable_validation();\n    var output_options = test.beautify || {};\n    var expect;\n    if (test.expect) {\n        expect = to_toplevel(test.expect, test.mangle, test.expression);\n        expect = make_code(expect, output_options, test.expression);\n    } else {\n        expect = test.expect_exact;\n    }\n    var input = to_toplevel(test.input, test.mangle, test.expression);\n    var input_code = make_code(input, {\n        keep_quoted_props: true,\n    }, test.expression);\n    var input_formatted = make_code(test.input, {\n        annotations: true,\n        beautify: true,\n        comments: \"all\",\n        keep_quoted_props: true,\n        quote_style: 3,\n    });\n    try {\n        input.validate_ast();\n        U.parse(input_code, { expression: test.expression });\n    } catch (ex) {\n        log([\n            \"!!! Cannot parse input\",\n            \"---INPUT---\",\n            \"{input}\",\n            \"--PARSE ERROR--\",\n            \"{error}\",\n            \"\",\n            \"\",\n        ].join(\"\\n\"), {\n            input: input_formatted,\n            error: ex,\n        });\n        return false;\n    }\n    var warnings_emitted = [];\n    if (test.expect_warnings) {\n        var expected_warnings = make_code(test.expect_warnings, {\n            beautify: false,\n            quote_style: 2, // force double quote to match JSON\n        });\n        U.AST_Node.log_function(function(text) {\n            warnings_emitted.push(text);\n        }, /\"INFO: /.test(expected_warnings));\n    }\n    var quoted_props;\n    if (test.mangle && test.mangle.properties && test.mangle.properties.keep_quoted) {\n        quoted_props = test.mangle.properties.reserved;\n        if (!Array.isArray(quoted_props)) quoted_props = [];\n        test.mangle.properties.reserved = quoted_props;\n        U.reserve_quoted_keys(input, quoted_props);\n    }\n    if (test.rename) {\n        input.figure_out_scope(test.mangle);\n        input.expand_names(test.mangle);\n    }\n    var cmp = new U.Compressor(test.options, true);\n    var output = cmp.compress(input);\n    output.figure_out_scope(test.mangle);\n    if (test.mangle) {\n        output.compute_char_frequency(test.mangle);\n        output.mangle_names(test.mangle);\n        if (quoted_props) U.reserve_quoted_keys(input, quoted_props);\n        if (test.mangle.properties) U.mangle_properties(output, test.mangle.properties);\n    }\n    var output_code = make_code(output, output_options, test.expression);\n    U.AST_Node.log_function();\n    if (expect != output_code) {\n        log([\n            \"!!! failed\",\n            \"---INPUT---\",\n            \"{input}\",\n            \"---OUTPUT---\",\n            \"{output}\",\n            \"---EXPECTED---\",\n            \"{expected}\",\n            \"\",\n            \"\",\n        ].join(\"\\n\"), {\n            input: input_formatted,\n            output: output_code,\n            expected: expect\n        });\n        return false;\n    }\n    // expect == output\n    try {\n        output.validate_ast();\n        U.parse(output_code, { expression: test.expression });\n    } catch (ex) {\n        log([\n            \"!!! Test matched expected result but cannot parse output\",\n            \"---INPUT---\",\n            \"{input}\",\n            \"---OUTPUT---\",\n            \"{output}\",\n            \"--REPARSE ERROR--\",\n            \"{error}\",\n            \"\",\n            \"\",\n        ].join(\"\\n\"), {\n            input: input_formatted,\n            output: output_code,\n            error: ex,\n        });\n        return false;\n    }\n    if (test.expect_warnings) {\n        warnings_emitted = warnings_emitted.map(function(input) {\n            return input.split(process.cwd() + path.sep).join(\"\").split(path.sep).join(\"/\");\n        });\n        var actual_warnings = JSON.stringify(warnings_emitted);\n        if (expected_warnings != actual_warnings) {\n            log([\n                \"!!! failed\",\n                \"---INPUT---\",\n                \"{input}\",\n                \"---EXPECTED WARNINGS---\",\n                \"{expected_warnings}\",\n                \"---ACTUAL WARNINGS---\",\n                \"{actual_warnings}\",\n                \"\",\n                \"\",\n            ].join(\"\\n\"), {\n                input: input_formatted,\n                expected_warnings: expected_warnings,\n                actual_warnings: actual_warnings,\n            });\n            return false;\n        }\n    }\n    if (test.expect_stdout && (!test.node_version || semver.satisfies(process.version, test.node_version))) {\n        var stdout = [ run_code(test.expression, input_code), run_code(test.expression, input_code, true) ];\n        var toplevel = sandbox.has_toplevel({\n            compress: test.options,\n            mangle: test.mangle\n        });\n        var actual = stdout[toplevel ? 1 : 0];\n        if (test.expect_stdout === true || test.expect_stdout instanceof Error && test.expect_stdout.name === actual.name) {\n            test.expect_stdout = actual;\n        }\n        if (!sandbox.same_stdout(test.expect_stdout, actual)) {\n            log([\n                \"!!! Invalid input or expected stdout\",\n                \"---INPUT---\",\n                \"{input}\",\n                \"---EXPECTED {expected_type}---\",\n                \"{expected}\",\n                \"---ACTUAL {actual_type}---\",\n                \"{actual}\",\n                \"\",\n                \"\",\n            ].join(\"\\n\"), {\n                input: input_formatted,\n                expected_type: typeof test.expect_stdout == \"string\" ? \"STDOUT\" : \"ERROR\",\n                expected: test.expect_stdout,\n                actual_type: typeof actual == \"string\" ? \"STDOUT\" : \"ERROR\",\n                actual: actual,\n            });\n            return false;\n        }\n        actual = run_code(test.expression, output_code, toplevel);\n        if (!sandbox.same_stdout(test.expect_stdout, actual)) {\n            log([\n                \"!!! failed\",\n                \"---INPUT---\",\n                \"{input}\",\n                \"---EXPECTED {expected_type}---\",\n                \"{expected}\",\n                \"---ACTUAL {actual_type}---\",\n                \"{actual}\",\n                \"\",\n                \"\",\n            ].join(\"\\n\"), {\n                input: input_formatted,\n                expected_type: typeof test.expect_stdout == \"string\" ? \"STDOUT\" : \"ERROR\",\n                expected: test.expect_stdout,\n                actual_type: typeof actual == \"string\" ? \"STDOUT\" : \"ERROR\",\n                actual: actual,\n            });\n            return false;\n        }\n        if (!reminify(test.expression, test.options, input_code, input_formatted, stdout)) {\n            return false;\n        }\n    }\n    return true;\n}\n\nfunction tmpl() {\n    return U.string_template.apply(null, arguments);\n}\n\nfunction to_toplevel(input, mangle_options, expression) {\n    if (!(input instanceof U.AST_BlockStatement)) throw new Error(\"Unsupported input syntax\");\n    var offset = input.start.line;\n    var tokens = [];\n    input.walk(new U.TreeWalker(function(node) {\n        if (U.push_uniq(tokens, node.start)) node.start.line -= offset;\n        if (U.push_uniq(tokens, node.end)) node.end.line -= offset;\n    }));\n    var toplevel;\n    if (!expression) {\n        var directive = true;\n        toplevel = new U.AST_Toplevel(input.transform(new U.TreeTransformer(function(node) {\n            if (!directive) return node;\n            if (node === input) return;\n            if (node instanceof U.AST_SimpleStatement && node.body instanceof U.AST_String) {\n                return new U.AST_Directive(node.body);\n            }\n            directive = false;\n        })));\n    } else if (input.body.length == 1) {\n        toplevel = input.body[0].wrap_expression();\n    } else {\n        throw new Error(\"Invalid expression\");\n    }\n    toplevel.figure_out_scope(mangle_options);\n    return toplevel;\n}\n"
  },
  {
    "path": "test/exports.js",
    "content": "exports[\"Compressor\"] = Compressor;\nexports[\"defaults\"] = defaults;\nexports[\"is_statement\"] = is_statement;\nexports[\"JS_Parse_Error\"] = JS_Parse_Error;\nexports[\"List\"] = List;\nexports[\"mangle_properties\"] = mangle_properties;\nexports[\"minify\"] = minify;\nexports[\"OutputStream\"] = OutputStream;\nexports[\"parse\"] = parse;\nexports[\"push_uniq\"] = push_uniq;\nexports[\"reserve_quoted_keys\"] = reserve_quoted_keys;\nexports[\"string_template\"] = string_template;\nexports[\"to_ascii\"] = to_ascii;\nexports[\"tokenizer\"] = tokenizer;\nexports[\"TreeTransformer\"] = TreeTransformer;\nexports[\"TreeWalker\"] = TreeWalker;\nexports[\"vlq_decode\"] = vlq_decode;\n"
  },
  {
    "path": "test/fetch.js",
    "content": "var fs = require(\"fs\");\nvar parse = require(\"url\").parse;\nvar path = require(\"path\");\n\ntry {\n    fs.mkdirSync(\"./tmp\");\n} catch (e) {\n    if (e.code != \"EEXIST\") throw e;\n}\n\nfunction local(url) {\n    return path.join(\"./tmp\", encodeURIComponent(url));\n}\n\nfunction read(url) {\n    return fs.createReadStream(local(url));\n}\n\nmodule.exports = function(url, callback) {\n    var result = read(url);\n    result.on(\"error\", function(e) {\n        if (e.code != \"ENOENT\") return callback(e);\n        var options = parse(url);\n        options.rejectUnauthorized = false;\n        require(options.protocol.slice(0, -1)).get(options, function(res) {\n            if (res.statusCode !== 200) return callback(res.statusCode);\n            res.pipe(fs.createWriteStream(local(url)));\n            callback(null, res);\n        });\n    }).on(\"open\", function() {\n        callback(null, result);\n    });\n};\n"
  },
  {
    "path": "test/input/comments/filter.js",
    "content": "// foo\n/*@preserve*/\n// bar\n"
  },
  {
    "path": "test/input/enclose/input.js",
    "content": "function enclose() {\n    console.log(\"test enclose\");\n}\nenclose();\n"
  },
  {
    "path": "test/input/global_defs/nested.js",
    "content": "console.log(C.V, C.D);\n"
  },
  {
    "path": "test/input/global_defs/simple.js",
    "content": "console.log(D);\n"
  },
  {
    "path": "test/input/invalid/assign_1.js",
    "content": "console.log(1 || 5--);\n"
  },
  {
    "path": "test/input/invalid/assign_2.js",
    "content": "console.log(2 || (Math.random() /= 2));\n"
  },
  {
    "path": "test/input/invalid/assign_3.js",
    "content": "console.log(3 || ++this);\n"
  },
  {
    "path": "test/input/invalid/assign_4.js",
    "content": "console.log(4 || (null = 4));\n"
  },
  {
    "path": "test/input/invalid/assign_5.js",
    "content": "console.log(5 || ([]?.length ^= 5));\n"
  },
  {
    "path": "test/input/invalid/delete.js",
    "content": "function f(x) {\n    delete 42;\n    delete (0, x);\n    delete null;\n    delete x;\n}\n\nfunction g(x) {\n    \"use strict\";\n    delete 42;\n    delete (0, x);\n    delete null;\n    delete x;\n}\n"
  },
  {
    "path": "test/input/invalid/destructured_var.js",
    "content": "function f() {\n    var { eval } = null;\n}\n\nfunction g() {\n    \"use strict\";\n    var { eval } = 42;\n}\n"
  },
  {
    "path": "test/input/invalid/dot_1.js",
    "content": "a.=\n"
  },
  {
    "path": "test/input/invalid/dot_2.js",
    "content": "%.a;\n"
  },
  {
    "path": "test/input/invalid/dot_3.js",
    "content": "a./();\n"
  },
  {
    "path": "test/input/invalid/else.js",
    "content": "if (0) else 1;\n"
  },
  {
    "path": "test/input/invalid/eof.js",
    "content": "foo, bar(\n"
  },
  {
    "path": "test/input/invalid/for-await.js",
    "content": "for await (; console.log(42););\n"
  },
  {
    "path": "test/input/invalid/for-in_1.js",
    "content": "var a, b = [1, 2];\nfor (1, 2, a in b) {\n    console.log(a, b[a]);\n}\n"
  },
  {
    "path": "test/input/invalid/for-in_2.js",
    "content": "var c = [1, 2];\nfor (var a, b in c) {\n    console.log(a, c[a]);\n}\n"
  },
  {
    "path": "test/input/invalid/for-of_1.js",
    "content": "var a = [ 1 ], b;\nfor (b = 2 of a)\n    console.log(b);\n"
  },
  {
    "path": "test/input/invalid/for-of_2.js",
    "content": "var a = [ 1 ];\nfor (var b = 2 of a)\n    console.log(b);\n"
  },
  {
    "path": "test/input/invalid/function_1.js",
    "content": "function f(arguments) {\n}\n\nfunction g(arguments) {\n    \"use strict\";\n}\n"
  },
  {
    "path": "test/input/invalid/function_2.js",
    "content": "function arguments() {\n}\n\nfunction eval() {\n    \"use strict\";\n}\n"
  },
  {
    "path": "test/input/invalid/function_3.js",
    "content": "!function eval() {\n}();\n\n!function arguments() {\n    \"use strict\";\n}();\n"
  },
  {
    "path": "test/input/invalid/loop-no-body.js",
    "content": "for (var i = 0; i < 1; i++) \n"
  },
  {
    "path": "test/input/invalid/object.js",
    "content": "console.log({%: 1});\n"
  },
  {
    "path": "test/input/invalid/optional-template.js",
    "content": "console?.log``;\n"
  },
  {
    "path": "test/input/invalid/return.js",
    "content": "return 42;\n"
  },
  {
    "path": "test/input/invalid/simple.js",
    "content": "function f(a{}\n"
  },
  {
    "path": "test/input/invalid/switch.js",
    "content": "switch (0) {\n  default:\n  default:\n}\n"
  },
  {
    "path": "test/input/invalid/tab.js",
    "content": "\t\tfoo(\txyz, 0abc);\n"
  },
  {
    "path": "test/input/invalid/try.js",
    "content": "function f() {\n    try {} catch (eval) {}\n}\n\nfunction g() {\n    \"use strict\";\n    try {} catch (eval) {}\n}\n"
  },
  {
    "path": "test/input/invalid/var.js",
    "content": "function f() {\n    var eval;\n}\n\nfunction g() {\n    \"use strict\";\n    var eval;\n}\n"
  },
  {
    "path": "test/input/issue-1236/simple.js",
    "content": "\"use strict\";\n\nvar foo = function foo(x) {\n  return \"foo \" + x;\n};\nconsole.log(foo(\"bar\"));\n\n//# sourceMappingURL=simple.js.map\n"
  },
  {
    "path": "test/input/issue-1242/bar.es5",
    "content": "function bar(x) {\n    var triple = x * (2 + 1);\n    return triple;\n}\n"
  },
  {
    "path": "test/input/issue-1242/baz.es5",
    "content": "function baz(x) {\n    var half = x / 2;\n    return half;\n}\n"
  },
  {
    "path": "test/input/issue-1242/foo.es5",
    "content": "var print = console.log.bind(console);\nfunction foo(x) {\n    var twice = x * 2;\n    print('Foo:', twice);\n}\n"
  },
  {
    "path": "test/input/issue-1242/qux.js",
    "content": "var x = bar(1+2);\nvar y = baz(3+9);\nprint('q' + 'u' + 'x', x, y);\nfoo(5+6);\n"
  },
  {
    "path": "test/input/issue-1323/sample.js",
    "content": "var bar = (function() {\n    function foo (bar) {\n        return bar;\n    }\n\n    return foo;\n})();"
  },
  {
    "path": "test/input/issue-1431/sample.js",
    "content": "function f(x) {\n    return function() {\n        function n(a) {\n            return a * a;\n        }\n        return x(n);\n    };\n}\n\nfunction g(op) {\n    return op(1) + op(2);\n}\n\nconsole.log(f(g)() == 5);"
  },
  {
    "path": "test/input/issue-1482/beautify.js",
    "content": "if (x) foo();\n\nif (x) foo(); else baz();\n\nif (x) foo(); else if (y) bar(); else baz();\n\nif (x) if (y) foo(); else bar(); else baz();\n\nif (x) foo(); else if (y) bar(); else if (z) baz(); else moo();\n\nfunction f() {\n    if (x) foo();\n    if (x) foo(); else baz();\n    if (x) foo(); else if (y) bar(); else baz();\n    if (x) if (y) foo(); else bar(); else baz();\n    if (x) foo(); else if (y) bar(); else if (z) baz(); else moo();\n}\n"
  },
  {
    "path": "test/input/issue-1482/braces.js",
    "content": "if (x) {\n    foo();\n}\n\nif (x) {\n    foo();\n} else {\n    baz();\n}\n\nif (x) {\n    foo();\n} else if (y) {\n    bar();\n} else {\n    baz();\n}\n\nif (x) {\n    if (y) {\n        foo();\n    } else {\n        bar();\n    }\n} else {\n    baz();\n}\n\nif (x) {\n    foo();\n} else if (y) {\n    bar();\n} else if (z) {\n    baz();\n} else {\n    moo();\n}\n\nfunction f() {\n    if (x) {\n        foo();\n    }\n    if (x) {\n        foo();\n    } else {\n        baz();\n    }\n    if (x) {\n        foo();\n    } else if (y) {\n        bar();\n    } else {\n        baz();\n    }\n    if (x) {\n        if (y) {\n            foo();\n        } else {\n            bar();\n        }\n    } else {\n        baz();\n    }\n    if (x) {\n        foo();\n    } else if (y) {\n        bar();\n    } else if (z) {\n        baz();\n    } else {\n        moo();\n    }\n}\n"
  },
  {
    "path": "test/input/issue-1482/default.js",
    "content": "if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo();function f(){if(x)foo();if(x)foo();else baz();if(x)foo();else if(y)bar();else baz();if(x)if(y)foo();else bar();else baz();if(x)foo();else if(y)bar();else if(z)baz();else moo()}\n"
  },
  {
    "path": "test/input/issue-1482/input.js",
    "content": "if (x) foo();\nif (x) foo(); else baz();\nif (x) foo(); else if (y) bar(); else baz();\nif (x) if (y) foo(); else bar(); else baz();\nif (x) foo(); else if (y) bar(); else if (z) baz(); else moo();\nfunction f() {\nif (x) foo();\nif (x) foo(); else baz();\nif (x) foo(); else if (y) bar(); else baz();\nif (x) if (y) foo(); else bar(); else baz();\nif (x) foo(); else if (y) bar(); else if (z) baz(); else moo();\n}\n"
  },
  {
    "path": "test/input/issue-1632/^{foo}[bar](baz)+$.js",
    "content": "console.log(x);"
  },
  {
    "path": "test/input/issue-2082/sample.js",
    "content": "console.log(x);"
  },
  {
    "path": "test/input/issue-2310/input.js",
    "content": "function foo() {\n    return function() {\n        console.log(\"PASS\");\n    };\n}\n\n(function() {\n    var f = foo();\n    f();\n})();\n"
  },
  {
    "path": "test/input/issue-3040/expect.js",
    "content": "\"use strict\";\n\nfunction _toConsumableArray(arr) {\n    return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();\n}\n\nfunction _nonIterableSpread() {\n    throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\n\nfunction _unsupportedIterableToArray(o, minLen) {\n    if (!o) return;\n    if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);\n    var n = Object.prototype.toString.call(o).slice(8, -1);\n    if (n === \"Object\" && o.constructor) n = o.constructor.name;\n    if (n === \"Map\" || n === \"Set\") return Array.from(n);\n    if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);\n}\n\nfunction _iterableToArray(iter) {\n    if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter);\n}\n\nfunction _arrayWithoutHoles(arr) {\n    if (Array.isArray(arr)) return _arrayLikeToArray(arr);\n}\n\nfunction _arrayLikeToArray(arr, len) {\n    if (len == null || len > arr.length) len = arr.length;\n    for (var i = 0, arr2 = new Array(len); i < len; i++) {\n        arr2[i] = arr[i];\n    }\n    return arr2;\n}\n\nvar _require = require(\"bar\"), foo = _require.foo;\n\nvar _require2 = require(\"world\"), hello = _require2.hello;\n\nfoo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHtmb299ID0gcmVxdWlyZShcImJhclwiKTtcbmNvbnN0IHtoZWxsb30gPSByZXF1aXJlKFwid29ybGRcIik7XG5cbmZvby54KC4uLmZvby55KGhlbGxvLnopKTtcbiJdLCJuYW1lcyI6WyJyZXF1aXJlIiwiZm9vIiwiaGVsbG8iLCJ4IiwiYXBwbHkiLCJfdG9Db25zdW1hYmxlQXJyYXkiLCJ5IiwieiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7ZUFBY0EsUUFBUSxLQUFELEdBQWRDLE0sU0FBQUE7O0EsZ0JBQ1NELFFBQVEsT0FBRCxHQUFoQkUsUSxVQUFBQTs7QUFFUEQsSUFBSUUsRUFBSkMsTUFBQUgsS0FBR0ksbUJBQU1KLElBQUlLLEVBQUVKLE1BQU1LLENBQVosQ0FBTixDQUFBIn0=\n"
  },
  {
    "path": "test/input/issue-3040/input.js",
    "content": "\"use strict\";\n\nfunction _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }\n\nfunction _nonIterableSpread() { throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\"); }\n\nfunction _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === \"string\") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === \"Object\" && o.constructor) n = o.constructor.name; if (n === \"Map\" || n === \"Set\") return Array.from(n); if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }\n\nfunction _iterableToArray(iter) { if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter); }\n\nfunction _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }\n\nfunction _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }\n\nvar _require = require(\"bar\"),\n    foo = _require.foo;\n\nvar _require2 = require(\"world\"),\n    hello = _require2.hello;\n\nfoo.x.apply(foo, _toConsumableArray(foo.y(hello.z)));\n\n//# sourceMappingURL=input.js.map"
  },
  {
    "path": "test/input/issue-3294/input.js",
    "content": "var Foo = function Foo(){console.log(1+2);}; new Foo();\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,DeadBeef\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9\n\n\n"
  },
  {
    "path": "test/input/issue-3294/output.js",
    "content": "console.log(3);\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSxDQUFHIn0=\n"
  },
  {
    "path": "test/input/issue-3315/config.json",
    "content": "{\n    \"compress\": false,\n    \"mangle\": {\n        \"properties\": {\n            \"regex\": \"/^_/\"\n        }\n    }\n}\n"
  },
  {
    "path": "test/input/issue-3315/input.js",
    "content": "function f() {\n    \"aaaaaaaaaa\";\n    var o = {\n        prop: 1,\n        _int: 2,\n    };\n    return o.prop + o._int;\n}\n"
  },
  {
    "path": "test/input/issue-3441/input.js",
    "content": "// Generated by CoffeeScript 2.4.1\n(function() {\n  console.log('hello');\n\n}).call(this);\n\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1haW4uY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtFQUFBLE9BQU8sQ0FBQyxHQUFSLENBQVksT0FBWjtBQUFBIiwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2cgJ2hlbGxvJ1xuIl19\n//# sourceURL=/Users/mohamed/Downloads/main.coffee\n"
  },
  {
    "path": "test/input/issue-505/input.js",
    "content": "function test(callback) {\n    'aaaaaaaaaaaaaaaa';\n    callback(err, data);\n    callback(err, data);\n}\n"
  },
  {
    "path": "test/input/issue-505/output.js",
    "content": "function test(a){\n\"aaaaaaaaaaaaaaaa\";\na(err,data),a(err,\ndata)}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsidGVzdCIsImNhbGxiYWNrIiwiZXJyIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0E7SEFBS0MsR0FDVjtBQUNBQTtoQkFBU0MsSUFBS0MsSUFBSSxFQUNsQkYsRUFBU0MsSUFBS0MsSUFBSSxDQUN0QiJ9"
  },
  {
    "path": "test/input/issue-520/input.js",
    "content": "var Foo = function Foo(){console.log(1+2);}; new Foo();\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLElBQU0sR0FBRyxHQUFDLEFBQUUsWUFBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBLEFBQUUsQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDOyJ9\n"
  },
  {
    "path": "test/input/issue-520/output.js",
    "content": "console.log(3);\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIl0sInNvdXJjZXNDb250ZW50IjpbImNsYXNzIEZvbyB7IGNvbnN0cnVjdG9yKCl7Y29uc29sZS5sb2coMSsyKTt9IH0gbmV3IEZvbygpO1xuIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUEwQkEsUUFBUUMsSUFBSSxDQUFHIn0=\n"
  },
  {
    "path": "test/input/module/expect.js",
    "content": "function n(){return this||arguments[0]+arguments[1]}function o(){return this||arguments[0]+arguments[1]}console.log(n(n(1,3),5)),console.log(o(o(2,4),6));\n"
  },
  {
    "path": "test/input/module/input.js",
    "content": "console.log(function() {\n    function sum(...params) {\n        return this || arguments[0] + arguments[1];\n    }\n    return sum(sum(1, 3), 5);\n}());\nconsole.log(function() {\n    \"use strict\";\n    function sum(...params) {\n        return this || arguments[0] + arguments[1];\n    }\n    return sum(sum(2, 4), 6);\n}());"
  },
  {
    "path": "test/input/reduce/destructured_assign.js",
    "content": "var o = {};\n[ o[1 + .1 + .1] ] = [ 42 ];\nconsole.log(o[1.2]);\n"
  },
  {
    "path": "test/input/reduce/destructured_assign.reduced.js",
    "content": "// (beautified)\nvar o = {};\n\n[ o[1 + .1 + .1] ] = [];\n\nconsole.log(o);\n// output: { '1.2000000000000002': undefined }\n// \n// minify: { '1.2': undefined }\n// \n// options: {\n//   \"compress\": {\n//     \"unsafe_math\": true\n//   },\n//   \"mangle\": false,\n//   \"validate\": true\n// }"
  },
  {
    "path": "test/input/reduce/destructured_catch.js",
    "content": "try {\n    \"foo\" in 42;\n} catch ({\n    message,\n}) {\n    console.log(message);\n}\n"
  },
  {
    "path": "test/input/reduce/destructured_catch.reduced.js",
    "content": "// (beautified)\ntry {\n    1 in 0;\n} catch (message) {\n    console.log(message);\n}\n// output: TypeError: Cannot use 'in' operator to search for '1' in 0\n// \n// minify: TypeError: Cannot use 'in' operator to search for '0' in 0\n// \n// options: {\n//   \"mangle\": false\n// }"
  },
  {
    "path": "test/input/reduce/diff_error.js",
    "content": "console.log(function(undefined) {\n    return undefined[function() {\n        {}\n    }] || 1 + .1 + .1;\n}(42));\n"
  },
  {
    "path": "test/input/reduce/diff_error.reduced.js",
    "content": "// (beautified)\nconsole.log(1 + .1 + .1);\n// output: 1.2000000000000002\n// \n// minify: 1.2\n// \n// options: {\n//   \"compress\": {\n//     \"unsafe_math\": true\n//   },\n//   \"mangle\": false\n// }"
  },
  {
    "path": "test/input/reduce/export_default.js",
    "content": "var unused;\nexport default class {\n    ____11111() {\n        a, b, c, d, e;\n        f, g, h, i, j;\n        k, l, m, n, o;\n        p, q, r, s, t;\n        u, v, w, x, y, z;\n        A, B, C, D, E;\n        F, G, H, I, J;\n        K, L, M, N, O;\n        P, Q, R, S, T;\n        U, V, W, X, Y, Z;\n        $, _;\n        unused;\n    }\n}\n"
  },
  {
    "path": "test/input/reduce/label.js",
    "content": "UNUSED: {\n    console.log(0 - .1 - .1 - .1);\n}\n"
  },
  {
    "path": "test/input/reduce/label.reduced.js",
    "content": "// (beautified)\nconsole.log(0 - 1 - .1 - .1);\n// output: -1.2000000000000002\n// \n// minify: -1.2\n// \n// options: {\n//   \"compress\": {\n//     \"unsafe_math\": true\n//   },\n//   \"mangle\": false\n// }"
  },
  {
    "path": "test/input/reduce/setter.js",
    "content": "({\n    set p(v) {\n        console.log(+v + .1 + .1);\n    }\n}).p = 1;\n"
  },
  {
    "path": "test/input/reduce/setter.reduced.js",
    "content": "// (beautified)\n({\n    set p(v) {\n        console.log(1 + .1 + .1);\n    }\n}).p = 0;\n// output: 1.2000000000000002\n// \n// minify: 1.2\n// \n// options: {\n//   \"compress\": {\n//     \"unsafe_math\": true\n//   },\n//   \"mangle\": false\n// }"
  },
  {
    "path": "test/input/reduce/unsafe_math.js",
    "content": "var _calls_ = 10, a = 100, b = 10, c = 0;\n\nfunction f0(b_1, a, undefined_2) {\n    a++ + ++b;\n    {\n        var expr2 = (b + 1 - .1 - .1 - .1 || a || 3).toString();\n        L20778: for (var key2 in expr2) {\n            (c = c + 1) + [ --b + b_1, typeof f0 == \"function\" && --_calls_ >= 0 && f0(--b + typeof (undefined_2 = 1 === 1 ? a : b), --b + {\n                c: (c = c + 1) + null\n            }, a++ + (typeof f0 == \"function\" && --_calls_ >= 0 && f0(typeof (c = 1 + c, 3 / \"a\" * (\"c\" >>> 23..toString()) >= (b_1 && (b_1[(c = c + 1) + a--] = (- -0,\n            true + {})))), 3, 25))), 1 === 1 ? a : b ];\n        }\n    }\n}\n\nvar a_1 = f0([ , 0 ].length === 2);\n\nconsole.log(null, a, b, c, Infinity, NaN, undefined);\n"
  },
  {
    "path": "test/input/reduce/unsafe_math.reduced.js",
    "content": "// (beautified)\nvar expr2 = (0 - 1 - .1 - .1).toString();\n\nconsole.log(expr2);\n// output: -1.2000000000000002\n// \n// minify: -1.2\n// \n// options: {\n//   \"compress\": {\n//     \"unsafe_math\": true\n//   },\n//   \"mangle\": false\n// }"
  },
  {
    "path": "test/input/rename/input.js",
    "content": "function f(x) {\n    return g(x);\n    function g(x) {\n        return x + x;\n    }\n}\n"
  },
  {
    "path": "test/jetstream.js",
    "content": "#! /usr/bin/env node\n// -*- js -*-\n\n\"use strict\";\n\nvar site = \"https://browserbench.org/JetStream1.1\";\nif (typeof phantom == \"undefined\") {\n    require(\"../tools/tty\");\n    var args = process.argv.slice(2);\n    var debug = args.indexOf(\"--debug\");\n    if (debug < 0) {\n        debug = false;\n    } else {\n        args.splice(debug, 1);\n        debug = true;\n    }\n    if (!args.length) args.push(\"-mcO\", \"webkit\");\n    args.unshift(\"bin/uglifyjs\");\n    args.push(\"--validate\", \"--timings\");\n    var child_process = require(\"child_process\");\n    var fetch = require(\"./fetch\");\n    var http = require(\"http\");\n    var server = http.createServer(function(request, response) {\n        request.resume();\n        var url = site + request.url;\n        fetch(url, function(err, res) {\n            if (err) {\n                if (typeof err != \"number\") throw err;\n                response.writeHead(err);\n                response.end();\n            } else {\n                response.writeHead(200, {\n                    \"Content-Type\": {\n                        css: \"text/css\",\n                        js: \"application/javascript\",\n                        png: \"image/png\"\n                    }[url.slice(url.lastIndexOf(\".\") + 1)] || \"text/html; charset=utf-8\"\n                });\n                if (/\\.js$/.test(url)) {\n                    var stderr = \"\";\n                    var uglifyjs = child_process.spawn(process.argv[0], args, {\n                        silent: true\n                    }).on(\"exit\", function(code) {\n                        console.log(\"uglifyjs\", url.slice(site.length + 1), args.slice(1).join(\" \"));\n                        console.log(stderr);\n                        if (code) throw new Error(\"uglifyjs failed with code \" + code);\n                    });\n                    uglifyjs.stderr.on(\"data\", function(data) {\n                        stderr += data;\n                    }).setEncoding(\"utf8\");\n                    uglifyjs.stdout.pipe(response);\n                    res.pipe(uglifyjs.stdin);\n                } else {\n                    res.pipe(response);\n                }\n            }\n        });\n    }).listen();\n    server.on(\"listening\", function() {\n        var port = server.address().port;\n        if (debug) return console.log(\"http://localhost:\" + port + \"/\");\n        var cmd = process.platform == \"win32\" ? \"npm.cmd\" : \"npm\";\n\n        function npm(args, done) {\n            args.push(\"--loglevel=error\");\n            child_process.spawn(cmd, args, {\n                shell: true,\n                stdio: [ \"ignore\", 1, 2 ],\n            }).on(\"exit\", done);\n        }\n\n        (function install() {\n            npm([\n                \"install\",\n                \"graceful-fs@4.2.6\",\n                \"is-my-json-valid@2.20.5\",\n                \"phantomjs-prebuilt@2.1.14\",\n                \"--no-audit\",\n                \"--no-fund\",\n                \"--no-optional\",\n                \"--no-save\",\n                \"--no-strict-ssl\",\n                \"--no-update-notifier\",\n                \"--production\",\n            ], function(code) {\n                if (code) {\n                    console.log(\"npm install failed with code\", code);\n                    return npm([\n                        \"cache\",\n                        \"clean\",\n                        \"--force\",\n                    ], install);\n                }\n                var program = require(\"phantomjs-prebuilt\").exec(process.argv[1], port);\n                program.stdout.pipe(process.stdout);\n                program.stderr.pipe(process.stderr);\n                program.on(\"exit\", function(code) {\n                    server.close();\n                    if (code) throw new Error(\"JetStream failed!\");\n                    console.log(\"JetStream completed successfully.\");\n                    process.exit(0);\n                });\n            });\n        })();\n    });\n    server.timeout = 0;\n} else {\n    var page = require(\"webpage\").create();\n    page.onError = function(msg, trace) {\n        var body = [ msg ];\n        if (trace) trace.forEach(function(t) {\n            body.push(\"  \" + (t.function || \"Anonymous function\") + \" (\" + t.file + \":\" + t.line + \")\");\n        });\n        console.error(body.join(\"\\n\"));\n        phantom.exit(1);\n    };\n    var url = \"http://localhost:\" + require(\"system\").args[1] + \"/\";\n    page.onConsoleMessage = function(msg) {\n        if (/Error:/i.test(msg)) {\n            console.error(msg);\n            phantom.exit(1);\n        }\n        console.log(msg);\n        if (~msg.indexOf(\"Raw results:\")) {\n            phantom.exit();\n        }\n    };\n    page.open(url, function(status) {\n        if (status != \"success\") phantom.exit(1);\n        page.evaluate(function() {\n            JetStream.switchToQuick();\n            JetStream.start();\n        });\n    });\n}\n"
  },
  {
    "path": "test/mocha/arguments.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../..\");\n\ndescribe(\"arguments\", function() {\n    it(\"Should known that arguments in functions are local scoped\", function() {\n        var ast = UglifyJS.parse(\"var arguments; var f = function() {arguments.length}\");\n        ast.figure_out_scope();\n        // Test scope of `var arguments`\n        assert.strictEqual(ast.find_variable(\"arguments\").global, true);\n        // Select arguments symbol in function\n        var symbol = ast.body[1].definitions[0].value.find_variable(\"arguments\");\n        assert.strictEqual(symbol.global, false);\n        assert.strictEqual(symbol.scope, ast. // From ast\n            body[1]. // Select 2nd statement (equals to `var f ...`)\n            definitions[0]. // First definition of selected statement\n            value // Select function as scope\n        );\n    });\n\n    it(\"Should recognize when a function uses arguments\", function() {\n        var ast = UglifyJS.parse(\"function a(){function b(){function c(){}; return arguments[0];}}\");\n        ast.figure_out_scope();\n        assert.strictEqual(ast.body[0].uses_arguments, false);\n        assert.strictEqual(ast.body[0].body[0].uses_arguments, true);\n        assert.strictEqual(ast.body[0].body[0].body[0].uses_arguments, false);\n    });\n});\n"
  },
  {
    "path": "test/mocha/awaits.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"async\", function() {\n    it(\"Should reject `await` as symbol name within async functions only\", function() {\n        [\n            \"function await() {}\",\n            \"function(await) {}\",\n            \"function() { await; }\",\n            \"function() { await: {} }\",\n            \"function() { var await; }\",\n            \"function() { function await() {} }\",\n            \"function() { try {} catch (await) {} }\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(\"(\" + code + \")();\");\n            assert.strictEqual(ast.TYPE, \"Toplevel\");\n            assert.strictEqual(ast.body.length, 1);\n            assert.strictEqual(ast.body[0].TYPE, \"SimpleStatement\");\n            assert.strictEqual(ast.body[0].body.TYPE, \"Call\");\n            assert.strictEqual(ast.body[0].body.expression.TYPE, \"Function\");\n            assert.throws(function() {\n                UglifyJS.parse(\"(async \" + code + \")();\");\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject `await` expression outside of async functions\", function() {\n        [\n            \"await 42;\",\n            \"function f() { await 42; }\",\n            \"async function f() { function g() { await 42; } }\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject `await` expression directly on computed key of function argument\", function() {\n        [\n            \"function f({ [await 42]: a }) {}\",\n            \"async function f({ [await 42]: a }) {}\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should accept `await` expression nested within computed key of function argument\", function() {\n        [\n            \"function f({ [async function() { await 42; }()]: a }) {}\",\n            \"async function f({ [async function() { await 42; }()]: a }) {}\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(code);\n            assert.strictEqual(ast.TYPE, \"Toplevel\");\n            assert.strictEqual(ast.body.length, 1);\n            assert.strictEqual(ast.body[0].argnames.length, 1);\n            assert.strictEqual(ast.body[0].argnames[0].TYPE, \"DestructuredObject\");\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/bug-report.js",
    "content": "var assert = require(\"assert\");\nvar exec = require(\"child_process\").exec;\n\ndescribe(\"UGLIFY_BUG_REPORT\", function() {\n    var env = Object.create(process.env);\n    env.UGLIFY_BUG_REPORT = 1;\n    it(\"Should generate bug report via API\", function(done) {\n        exec('\"' + process.argv[0] + '\"', { env: env }, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                \"// UGLIFY_BUG_REPORT\",\n                \"// <<undefined>>\",\n                \"\",\n                \"//-------------------------------------------------------------\",\n                \"// INPUT CODE\",\n                \"...---...\",\n                \"\",\n            ].join(\"\\n\"));\n            done();\n        }).stdin.end('console.log(require(\"./\").minify(\"...---...\").code);');\n    });\n    it(\"Should generate bug report via CLI\", function(done) {\n        exec('\"' + process.argv[0] + '\" bin/uglifyjs -mc', { env: env }, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                \"// UGLIFY_BUG_REPORT\",\n                \"// {\",\n                '//   \"mangle\": {},',\n                '//   \"compress\": {}',\n                \"// }\",\n                \"\",\n                \"//-------------------------------------------------------------\",\n                \"// STDIN\",\n                \"...---...\",\n                \"\",\n            ].join(\"\\n\"));\n            done();\n        }).stdin.end(\"...---...\");\n    });\n});\n"
  },
  {
    "path": "test/mocha/cli.js",
    "content": "var assert = require(\"assert\");\nvar exec = require(\"child_process\").exec;\nvar fs = require(\"fs\");\nvar run_code = require(\"../sandbox\").run_code;\nvar semver = require(\"semver\");\nvar to_ascii = require(\"../node\").to_ascii;\n\nfunction read(path) {\n    return fs.readFileSync(path, \"utf8\");\n}\n\ndescribe(\"bin/uglifyjs\", function() {\n    var uglifyjscmd = '\"' + process.argv[0] + '\" bin/uglifyjs';\n    it(\"Should produce a functional build when using --self\", function(done) {\n        this.timeout(30000);\n        var command = [\n            uglifyjscmd,\n            \"--self\",\n            \"--wrap WrappedUglifyJS\",\n            semver.satisfies(process.version, \"<4\") ? \"--no-module\" : \"--module\",\n            semver.satisfies(process.version, \"<=0.12\") ? \"-mc hoist_funs\" : \"-mc\",\n        ].join(\" \");\n        exec(command, { maxBuffer: 1048576 }, function(err, stdout) {\n            if (err) throw err;\n            eval(stdout);\n            assert.strictEqual(typeof WrappedUglifyJS, \"object\");\n            var result = WrappedUglifyJS.minify(\"foo([true,,2+3]);\");\n            assert.strictEqual(result.error, undefined);\n            assert.strictEqual(result.code, \"foo([!0,,5]);\");\n            done();\n        });\n    });\n    it(\"Should be able to filter comments correctly with `--comments all`\", function(done) {\n        var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"// foo\\n/*@preserve*/\\n// bar\\n\");\n            done();\n        });\n    });\n    it(\"Should be able to filter comments correctly with `--comment <RegExp>`\", function(done) {\n        var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"/*@preserve*/\\n// bar\\n\");\n            done();\n        });\n    });\n    it(\"Should be able to filter comments correctly with just `--comment`\", function(done) {\n        var command = uglifyjscmd + ' test/input/comments/filter.js --comments';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"/*@preserve*/\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --expression\", function(done) {\n        exec([\n            uglifyjscmd,\n            \"--expression\",\n            \"--compress\",\n            \"--mangle\",\n        ].join(\" \"), function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"(r=>{for(;r(););return 42})(A)\\n\");\n            done();\n        }).stdin.end([\n            \"function(x) {\",\n            \"    while (x()) {}\",\n            \"    return 42;\",\n            \"}(A)\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should work with --source-map names=true\", function(done) {\n        exec([\n            uglifyjscmd,\n            \"--beautify\",\n            \"--source-map\", [\n                \"names=true\",\n                \"url=inline\",\n            ].join(),\n        ].join(\" \"), function(err, stdout) {\n            if (err) throw err;\n            var expected = [\n                \"var obj = {\",\n                \"    p: a,\",\n                \"    q: b\",\n                \"};\",\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,\",\n            ].join(\"\\n\");\n            assert.strictEqual(stdout.slice(0, expected.length), expected);\n            var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));\n            assert.deepEqual(map.names, [ \"obj\", \"p\", \"a\", \"q\", \"b\" ]);\n            done();\n        }).stdin.end([\n            \"var obj = {\",\n            \"    p: a,\",\n            \"    q: b\",\n            \"};\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should work with --source-map names=false\", function(done) {\n        exec([\n            uglifyjscmd,\n            \"--beautify\",\n            \"--source-map\", [\n                \"names=false\",\n                \"url=inline\",\n            ].join(),\n        ].join(\" \"), function(err, stdout) {\n            if (err) throw err;\n            var expected = [\n                \"var obj = {\",\n                \"    p: a,\",\n                \"    q: b\",\n                \"};\",\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,\",\n            ].join(\"\\n\");\n            assert.strictEqual(stdout.slice(0, expected.length), expected);\n            var map = JSON.parse(to_ascii(stdout.slice(expected.length).trim()));\n            assert.deepEqual(map.names, []);\n            done();\n        }).stdin.end([\n            \"var obj = {\",\n            \"    p: a,\",\n            \"    q: b\",\n            \"};\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should give sensible error against invalid input source map\", function(done) {\n        var command = uglifyjscmd + \" test/mocha.js --source-map content=blah,url=inline --verbose\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.deepEqual(stderr.split(/\\n/).slice(0, 2), [\n                \"INFO: Using input source map: blah\",\n                \"ERROR: invalid input source map: blah\",\n            ]);\n            done();\n        });\n    });\n    it(\"Should append source map to output when using --source-map url=inline\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-1323/sample.js --source-map url=inline\";\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                \"var bar=function(){function foo(bar){return bar}return foo}();\",\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=\",\n                \"\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should not append source map to output when not using --source-map url=inline\", function(done) {\n        var command = uglifyjscmd + ' test/input/issue-1323/sample.js';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"var bar=function(){function foo(bar){return bar}return foo}();\\n\");\n            done();\n        });\n    });\n    it(\"Should not consider source map file content as source map file name (issue #2082)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-2082/sample.js\",\n            \"--source-map\", \"content=test/input/issue-2082/sample.js.map\",\n            \"--source-map\", \"url=inline\",\n            \"--verbose\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            var stderrLines = stderr.split(\"\\n\");\n            assert.strictEqual(stderrLines[0], \"INFO: Using input source map: test/input/issue-2082/sample.js.map\");\n            assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {\"version\": 3,\"sources\": [\"index.js\"],\"mappings\": \";\"}');\n            done();\n        });\n    });\n    it(\"Should not load source map before finish reading from STDIN\", function(done) {\n        var mapFile = \"tmp/input.js.map\";\n        try {\n            fs.mkdirSync(\"./tmp\");\n        } catch (e) {\n            if (e.code != \"EEXIST\") throw e;\n        }\n        try {\n            fs.unlinkSync(mapFile);\n        } catch (e) {\n            if (e.code != \"ENOENT\") throw e;\n        }\n        var command = [\n            uglifyjscmd,\n            \"--beautify\",\n            \"--source-map\", [\n                \"content=\" + mapFile,\n                \"includeSources\",\n                \"url=inline\",\n            ].join(),\n        ].join(\" \");\n\n        var child = exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, read(\"test/input/issue-3040/expect.js\"));\n            done();\n        });\n        setTimeout(function() {\n            fs.writeFileSync(mapFile, read(\"test/input/issue-3040/input.js.map\"));\n            child.stdin.end(read(\"test/input/issue-3040/input.js\"));\n        }, 1000);\n    });\n    it(\"Should work with --keep-fargs (mangle only)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-1431/sample.js\",\n            \"--keep-fargs\",\n            \"--mangle\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --keep-fargs (mangle & compress)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-1431/sample.js\",\n            \"--keep-fargs\",\n            \"--mangle\",\n            \"--no-module\",\n            \"--compress\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(x){return function(){return x(function(a){return a*a})}}function g(op){return op(1)+op(2)}console.log(5==f(g)());\\n\");\n            done();\n        });\n    });\n    it(\"Should work with keep_fargs under mangler options\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-1431/sample.js\",\n            \"--mangle\", \"keep_fargs=true\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --keep-fnames (mangle only)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-1431/sample.js\",\n            \"--keep-fnames\",\n            \"--mangle\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --keep-fnames (mangle & compress)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-1431/sample.js\",\n            \"--keep-fnames\",\n            \"--mangle\",\n            \"--no-module\",\n            \"--compress\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(n){return function(){return n(function n(r){return r*r})}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\\n\");\n            done();\n        });\n    });\n    it(\"Should work with keep_fnames under mangler options\", function(done) {\n        var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --define (simple)\", function(done) {\n        var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"console.log(5);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --define (nested)\", function(done) {\n        var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"console.log(3,5);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --define (AST_Node)\", function(done) {\n        var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"stdout.println(D);\\n\");\n            done();\n        });\n    });\n    it(\"Should work with `--beautify`\", function(done) {\n        var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, read(\"test/input/issue-1482/beautify.js\"));\n            done();\n        });\n    });\n    it(\"Should work with `--beautify braces`\", function(done) {\n        var command = uglifyjscmd + ' test/input/issue-1482/input.js -b braces';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, read(\"test/input/issue-1482/braces.js\"));\n            done();\n        });\n    });\n    it(\"Should work with `--output-opts`\", function(done) {\n        var command = uglifyjscmd + ' test/input/issue-1482/input.js -O ascii_only';\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, read(\"test/input/issue-1482/default.js\"));\n            done();\n        });\n    });\n    it(\"Should fail when both --beautify & --output-opts are specified\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-520/input.js -bO ascii_only\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stderr, \"ERROR: --beautify cannot be used with --output-opts\\n\");\n            done();\n        });\n    });\n    it(\"Should process inline source map\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-520/input.js\",\n            \"-mc\", \"toplevel\",\n            \"--source-map\", \"content=inline\",\n            \"--source-map\", \"includeSources=true\",\n            \"--source-map\", \"url=inline\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, read(\"test/input/issue-520/output.js\"));\n            done();\n        });\n    });\n    it(\"Should warn for missing inline source map\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-1323/sample.js --source-map content=inline,url=inline --warn\";\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                \"var bar=function(){function foo(bar){return bar}return foo}();\",\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=\",\n                \"\",\n            ].join(\"\\n\"));\n            var stderrLines = stderr.split(\"\\n\");\n            assert.strictEqual(stderrLines[0], \"WARN: inline source map not found: test/input/issue-1323/sample.js\");\n            done();\n        });\n    });\n    it(\"Should handle multiple input and inline source map\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-520/input.js\",\n            \"test/input/issue-1323/sample.js\",\n            \"--source-map\", \"content=inline,url=inline\",\n            \"--warn\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                \"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();\",\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUVBLE1BQWNDLFFBQVFDLElBQUksRUFBRSxDQUFDLENBQUUsRUFBSSxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxHQUNYLENBRUEsT0FBT0MsR0FDVixFQUFFIn0=\",\n                \"\",\n            ].join(\"\\n\"));\n            var stderrLines = stderr.split(\"\\n\");\n            assert.strictEqual(stderrLines[0], \"WARN: inline source map not found: test/input/issue-1323/sample.js\");\n            done();\n        });\n    });\n    it(\"Should fail with acorn and inline source map\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stderr, \"ERROR: inline source map only works with built-in parser\\n\");\n            done();\n        });\n    });\n    it(\"Should fail with SpiderMonkey and inline source map\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-520/input.js --source-map content=inline,url=inline -p spidermonkey\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stderr, \"ERROR: inline source map only works with built-in parser\\n\");\n            done();\n        });\n    });\n    it(\"Should fail with invalid syntax\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/simple.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/simple.js:1,12\",\n                \"function f(a{}\",\n                \"            ^\",\n                \"ERROR: Unexpected token: punc «{», expected: punc «,»\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should fail with correct marking of tabs\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/tab.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/tab.js:1,12\",\n                \"\\t\\tfoo(\\txyz, 0abc);\",\n                \"\\t\\t    \\t     ^\",\n                \"ERROR: Invalid syntax: 0abc\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should fail with correct marking at start of line\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/eof.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/eof.js:2,0\",\n                \"foo, bar(\",\n                \"         ^\",\n                \"ERROR: Unexpected token: eof\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should fail with a missing loop body\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/loop-no-body.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/loop-no-body.js:2,0\",\n                \"for (var i = 0; i < 1; i++) \",\n                \"                            ^\",\n                \"ERROR: Unexpected token: eof\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (5--)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/assign_1.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/assign_1.js:1,18\",\n                \"console.log(1 || 5--);\",\n                \"                  ^\",\n                \"ERROR: Invalid use of -- operator\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (Math.random() /= 2)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/assign_2.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/assign_2.js:1,32\",\n                \"console.log(2 || (Math.random() /= 2));\",\n                \"                                ^\",\n                \"ERROR: Invalid assignment\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (++this)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/assign_3.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/assign_3.js:1,17\",\n                \"console.log(3 || ++this);\",\n                \"                 ^\",\n                \"ERROR: Invalid use of ++ operator\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (null = 4)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/assign_4.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/assign_4.js:1,23\",\n                \"console.log(4 || (null = 4));\",\n                \"                       ^\",\n                \"ERROR: Invalid assignment\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error ([]?.length ^= 5)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/assign_5.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/assign_5.js:1,29\",\n                \"console.log(5 || ([]?.length ^= 5));\",\n                \"                             ^\",\n                \"ERROR: Invalid assignment\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (a.=)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/dot_1.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/dot_1.js:1,2\",\n                \"a.=\",\n                \"  ^\",\n                \"ERROR: Unexpected token: operator «=», expected: name\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (%.a)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/dot_2.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/dot_2.js:1,0\",\n                \"%.a;\",\n                \"^\",\n                \"ERROR: Unexpected token: operator «%»\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (a./();)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/dot_3.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/dot_3.js:1,2\",\n                \"a./();\",\n                \"  ^\",\n                \"ERROR: Unexpected token: operator «/», expected: name\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error ({%: 1})\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/object.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/object.js:1,13\",\n                \"console.log({%: 1});\",\n                \"             ^\",\n                \"ERROR: Unexpected token: operator «%»\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (delete x)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/delete.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/delete.js:13,11\",\n                \"    delete x;\",\n                \"           ^\",\n                \"ERROR: Calling delete on expression not allowed in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (function g(arguments))\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/function_1.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/function_1.js:4,11\",\n                \"function g(arguments) {\",\n                \"           ^\",\n                \"ERROR: Unexpected arguments in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (function eval())\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/function_2.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/function_2.js:4,9\",\n                \"function eval() {\",\n                \"         ^\",\n                \"ERROR: Unexpected eval in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (iife arguments())\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/function_3.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/function_3.js:4,10\",\n                \"!function arguments() {\",\n                \"          ^\",\n                \"ERROR: Unexpected arguments in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (catch (eval))\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/try.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/try.js:7,18\",\n                \"    try {} catch (eval) {}\",\n                \"                  ^\",\n                \"ERROR: Unexpected eval in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (var eval)\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/var.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/var.js:7,8\",\n                \"    var eval;\",\n                \"        ^\",\n                \"ERROR: Unexpected eval in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (var { eval })\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/invalid/destructured_var.js\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/destructured_var.js:7,10\",\n                \"    var { eval } = 42;\",\n                \"          ^\",\n                \"ERROR: Unexpected eval in strict mode\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (else)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/else.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/else.js:1,7\",\n                \"if (0) else 1;\",\n                \"       ^\",\n                \"ERROR: Unexpected token: keyword «else»\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (return)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/return.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/return.js:1,0\",\n                \"return 42;\",\n                \"^\",\n                \"ERROR: 'return' outside of function\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (for-in init)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/for-in_1.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/for-in_1.js:2,5\",\n                \"for (1, 2, a in b) {\",\n                \"     ^\",\n                \"ERROR: Invalid left-hand side in for..in/of loop\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (for-in var)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/for-in_2.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/for-in_2.js:2,5\",\n                \"for (var a, b in c) {\",\n                \"     ^\",\n                \"ERROR: Only one variable declaration allowed in for..in/of loop\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (for-of init)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/for-of_1.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/for-of_1.js:2,5\",\n                \"for (b = 2 of a)\",\n                \"     ^\",\n                \"ERROR: Invalid left-hand side in for..in/of loop\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (for-of var)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/for-of_2.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/for-of_2.js:2,13\",\n                \"for (var b = 2 of a)\",\n                \"             ^\",\n                \"ERROR: No initializers allowed in for..of loop\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (for-await)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/for-await.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/for-await.js:1,11\",\n                \"for await (; console.log(42););\",\n                \"           ^\",\n                \"ERROR: Unexpected token: punc «;»\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (switch defaults)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/switch.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/switch.js:3,2\",\n                \"  default:\",\n                \"  ^\",\n                \"ERROR: More than one default clause in switch statement\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should throw syntax error (console?.log``)\", function(done) {\n        var command = uglifyjscmd + \" test/input/invalid/optional-template.js\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr.split(/\\n/).slice(0, 4).join(\"\\n\"), [\n                \"Parse error at test/input/invalid/optional-template.js:1,12\",\n                \"console?.log``;\",\n                \"            ^\",\n                \"ERROR: Invalid template on optional chain\",\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should handle literal string as source map input\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-1236/simple.js\",\n            \"--source-map\",\n            'content=\"' + read_map() + '\",url=inline'\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                '\"use strict\";var foo=function foo(x){return\"foo \"+x};console.log(foo(\"bar\"));',\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxDQUFkLEVBQ1ZDLFFBQVFDLElBQUlILElBQUksS0FBSixDQUFaIn0=\",\n                \"\"\n            ].join(\"\\n\"));\n            done();\n        });\n\n        function read_map() {\n            var map = JSON.parse(read(\"test/input/issue-1236/simple.js.map\"));\n            delete map.sourcesContent;\n            return JSON.stringify(map).replace(/\"/g, '\\\\\"');\n        }\n    });\n    it(\"Should include function calls in source map\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-2310/input.js\",\n            \"--compress\",\n            \"--no-module\",\n            \"--source-map\", \"url=inline\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, [\n                'function foo(){return function(){console.log(\"PASS\")}}foo()();',\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFTQSxNQUNMLE9BQU8sV0FDSEMsUUFBUUMsSUFBSSxNQUFNLENBQ3RCLENBQ0osQ0FHWUYsSUFBSSxFQUNWIn0=\",\n                \"\"\n            ].join(\"\\n\"));\n            done();\n        });\n    });\n    it(\"Should dump AST as JSON\", function(done) {\n        var command = uglifyjscmd + \" test/input/global_defs/simple.js -mco ast\";\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            var ast = JSON.parse(stdout);\n            assert.strictEqual(ast._class, \"AST_Toplevel\");\n            assert.ok(Array.isArray(ast.body));\n            done();\n        });\n    });\n    it(\"Should print supported options on invalid option syntax\", function(done) {\n        var command = uglifyjscmd + \" test/input/comments/filter.js -b ascii-only\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.ok(/^Supported options:\\n[\\s\\S]*?\\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);\n            done();\n        });\n    });\n    it(\"Should work with --mangle reserved=[]\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-505/input.js\",\n            \"--mangle\", \"reserved=[callback]\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, 'function test(callback){\"aaaaaaaaaaaaaaaa\";callback(err,data);callback(err,data)}\\n');\n            done();\n        });\n    });\n    it(\"Should work with --mangle reserved=false\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-505/input.js\",\n            \"--mangle\", \"reserved=false\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, 'function test(a){\"aaaaaaaaaaaaaaaa\";a(err,data);a(err,data)}\\n');\n            done();\n        });\n    });\n    it(\"Should fail with --mangle-props reserved=[in]\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-505/input.js --mangle-props reserved=[in]\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.ok(/^Supported options:\\n[\\s\\S]*?\\nERROR: `reserved=\\[in]` is not a supported option/.test(stderr), stderr);\n            done();\n        });\n    });\n    it(\"Should work with mangle.properties.regex from --config-file\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/issue-3315/input.js\",\n            \"--config-file\", \"test/input/issue-3315/config.json\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, 'function f(){\"aaaaaaaaaa\";var a={prop:1,t:2};return a.prop+a.t}\\n');\n            done();\n        });\n    });\n    it(\"Should fail with --define a-b\", function(done) {\n        var command = uglifyjscmd + \" test/input/issue-505/input.js --define a-b\";\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.strictEqual(stdout, \"\");\n            assert.strictEqual(stderr, \"ERROR: cannot parse arguments for 'define': a-b\\n\");\n            done();\n        });\n    });\n    it(\"Should work with explicit --rename\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/rename/input.js\",\n            \"--no-module\",\n            \"--rename\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(a){return b(a);function b(c){return c+c}}\\n\");\n            done();\n        });\n    });\n    it(\"Should work with explicit --no-rename\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/rename/input.js\",\n            \"--compress\", \"passes=2\",\n            \"--mangle\",\n            \"--no-module\",\n            \"--no-rename\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(n){return function(n){return n+n}(n)}\\n\");\n            done();\n        });\n    });\n    it(\"Should work with implicit --rename\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/rename/input.js\",\n            \"--compress\", \"passes=2\",\n            \"--mangle\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(n){return n+n}\\n\");\n            done();\n        });\n    });\n    it(\"Should work with implicit --no-rename\", function(done) {\n        var command = [\n            uglifyjscmd,\n            \"test/input/rename/input.js\",\n            \"--compress\", \"passes=2\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"function f(x){return function(x){return x+x}(x)}\\n\");\n            done();\n        });\n    });\n    it(\"Should work with --enclose\", function(done) {\n        var command = uglifyjscmd + \" test/input/enclose/input.js --enclose\";\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, '(function(){function enclose(){console.log(\"test enclose\")}enclose()})();\\n');\n            done();\n        });\n    });\n    it(\"Should work with --enclose arg\", function(done) {\n        var command = uglifyjscmd + \" test/input/enclose/input.js --enclose undefined\";\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, '(function(undefined){function enclose(){console.log(\"test enclose\")}enclose()})();\\n');\n            done();\n        });\n    });\n    it(\"Should work with --enclose arg:value\", function(done) {\n        var command = uglifyjscmd + \" test/input/enclose/input.js --enclose window,undefined:window\";\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, '(function(window,undefined){function enclose(){console.log(\"test enclose\")}enclose()})(window);\\n');\n            done();\n        });\n    });\n    it(\"Should work with --enclose & --wrap\", function(done) {\n        var command = uglifyjscmd + \" test/input/enclose/input.js --enclose window,undefined:window --wrap exports\";\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, '(function(exports){(function(window,undefined){function enclose(){console.log(\"test enclose\")}enclose()})(window)})(typeof exports==\"undefined\"?exports={}:exports);\\n');\n            done();\n        });\n    });\n    it(\"Should work with --module\", function(done) {\n        var command = uglifyjscmd + \" test/input/module/input.js --module -mc\";\n        exec(command, function(err, stdout, stderr) {\n            if (err) throw err;\n            assert.strictEqual(stdout, read(\"test/input/module/expect.js\"));\n            done();\n        });\n    });\n    it(\"Should compress swarm of unused variables with reasonable performance\", function(done) {\n        var code = [\n            \"console.log(function() {\",\n        ];\n        for (var i = 0; i < 10000; i++) {\n            code.push(\"var obj\" + i + \" = {p: \" + i + \"};\");\n        }\n        code.push(\"var map = {\");\n        for (var i = 0; i < 10000; i++) {\n            code.push(\"obj\" + i + \": obj\" + i + \",\");\n        }\n        code = code.concat([\n            \"};\",\n            \"return obj25.p + obj121.p + obj1024.p;\",\n            \"}());\",\n        ]).join(\"\\n\");\n        exec(uglifyjscmd + \" --no-module -mc\", function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, \"console.log(function(){var p={p:25},n={p:121},o={p:1024};return p.p+n.p+o.p}());\\n\");\n            assert.strictEqual(run_code(stdout), run_code(code));\n            done();\n        }).stdin.end(code);\n    });\n});\n"
  },
  {
    "path": "test/mocha/comments.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"comments\", function() {\n    it(\"Should recognize eol of single line comments\", function() {\n        var tests = [\n            \"//Some comment 1\\n>\",\n            \"//Some comment 2\\r>\",\n            \"//Some comment 3\\r\\n>\",\n            \"//Some comment 4\\u2028>\",\n            \"//Some comment 5\\u2029>\"\n        ];\n\n        var fail = function(e) {\n            return e instanceof UglifyJS.JS_Parse_Error\n                && e.message === \"Unexpected token: operator «>»\"\n                && e.line === 2\n                && e.col === 0;\n        }\n\n        for (var i = 0; i < tests.length; i++) {\n            assert.throws(function() {\n                UglifyJS.parse(tests[i]);\n            }, fail, tests[i]);\n        }\n    });\n\n    it(\"Should update the position of a multiline comment correctly\", function() {\n        var tests = [\n            \"/*Some comment 1\\n\\n\\n*/\\n>\\n\\n\\n\\n\\n\\n\",\n            \"/*Some comment 2\\r\\n\\r\\n\\r\\n*/\\r\\n>\\n\\n\\n\\n\\n\\n\",\n            \"/*Some comment 3\\r\\r\\r*/\\r>\\n\\n\\n\\n\\n\\n\",\n            \"/*Some comment 4\\u2028\\u2028\\u2028*/\\u2028>\\n\\n\\n\\n\\n\\n\",\n            \"/*Some comment 5\\u2029\\u2029\\u2029*/\\u2029>\\n\\n\\n\\n\\n\\n\"\n        ];\n\n        var fail = function(e) {\n            return e instanceof UglifyJS.JS_Parse_Error\n                && e.message === \"Unexpected token: operator «>»\"\n                && e.line === 5\n                && e.col === 0;\n        }\n\n        for (var i = 0; i < tests.length; i++) {\n            assert.throws(function() {\n                UglifyJS.parse(tests[i]);\n            }, fail, tests[i]);\n        }\n    });\n\n    describe(\"comment within return\", function() {\n        it(\"Should handle leading return\", function() {\n            var result = UglifyJS.minify([\n                \"function unequal(x, y) {\",\n                \"    return (\",\n                \"        // Either one\",\n                \"        x < y\",\n                \"        ||\",\n                \"        y < x\",\n                \"    );\",\n                \"}\",\n            ].join(\"\\n\"), {\n                compress: false,\n                mangle: false,\n                output: {\n                    beautify: true,\n                    comments: \"all\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, [\n                \"function unequal(x, y) {\",\n                \"    // Either one\",\n                \"    return x < y || y < x;\",\n                \"}\",\n            ].join(\"\\n\"));\n        });\n\n        it(\"Should handle trailing return\", function() {\n            var result = UglifyJS.minify([\n                \"function unequal(x) {\",\n                \"    var y;\",\n                \"    return (\",\n                \"        // Either one\",\n                \"        x < y\",\n                \"        ||\",\n                \"        y < x\",\n                \"    );\",\n                \"}\",\n            ].join(\"\\n\"), {\n                compress: false,\n                mangle: false,\n                output: {\n                    beautify: true,\n                    comments: \"all\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, [\n                \"function unequal(x) {\",\n                \"    var y;\",\n                \"    // Either one\",\n                \"    return x < y || y < x;\",\n                \"}\",\n            ].join(\"\\n\"));\n        });\n\n        it(\"Should handle comment folded into return\", function() {\n            var result = UglifyJS.minify([\n                \"function f() {\",\n                \"    /* boo */ x();\",\n                \"    return y();\",\n                \"}\",\n            ].join(\"\\n\"), {\n                mangle: false,\n                output: {\n                    beautify: true,\n                    comments: \"all\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, [\n                \"function f() {\",\n                \"    /* boo */\",\n                \"    return x(), y();\",\n                \"}\",\n            ].join(\"\\n\"));\n        });\n    });\n\n    it(\"Should not drop comments after first OutputStream\", function() {\n        var code = \"/* boo */\\nx();\";\n        var ast = UglifyJS.parse(code);\n        var out1 = UglifyJS.OutputStream({\n            beautify: true,\n            comments: \"all\",\n        });\n        ast.print(out1);\n        var out2 = UglifyJS.OutputStream({\n            beautify: true,\n            comments: \"all\",\n        });\n        ast.print(out2);\n        assert.strictEqual(out1.get(), code);\n        assert.strictEqual(out2.get(), out1.get());\n    });\n\n    it(\"Should retain trailing comments\", function() {\n        var code = [\n            \"if (foo /* lost comment */ && bar /* lost comment */) {\",\n            \"    // this one is kept\",\n            \"    {/* lost comment */}\",\n            \"    !function() {\",\n            \"        // lost comment\",\n            \"    }();\",\n            \"    function baz() {/* lost comment */}\",\n            \"    // lost comment\",\n            \"}\",\n            \"// comments right before EOF are lost as well\",\n        ].join(\"\\n\");\n        var result = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                beautify: true,\n                comments: \"all\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, code);\n    });\n\n    it(\"Should retain comments within braces\", function() {\n        var code = [\n            \"{/* foo */}\",\n            \"a({/* foo */});\",\n            \"while (a) {/* foo */}\",\n            \"switch (a) {/* foo */}\",\n            \"if (a) {/* foo */} else {/* bar */}\",\n        ].join(\"\\n\\n\");\n        var result = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                beautify: true,\n                comments: \"all\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, code);\n    });\n\n    it(\"Should correctly preserve new lines around comments\", function() {\n        [\n            [\n                \"// foo\",\n                \"// bar\",\n                \"x();\",\n            ].join(\"\\n\"),\n            [\n                \"// foo\",\n                \"/* bar */\",\n                \"x();\",\n            ].join(\"\\n\"),\n            [\n                \"// foo\",\n                \"/* bar */ x();\",\n            ].join(\"\\n\"),\n            [\n                \"/* foo */\",\n                \"// bar\",\n                \"x();\",\n            ].join(\"\\n\"),\n            [\n                \"/* foo */ // bar\",\n                \"x();\",\n            ].join(\"\\n\"),\n            [\n                \"/* foo */\",\n                \"/* bar */\",\n                \"x();\",\n            ].join(\"\\n\"),\n            [\n                \"/* foo */\",\n                \"/* bar */ x();\",\n            ].join(\"\\n\"),\n            [\n                \"/* foo */ /* bar */\",\n                \"x();\",\n            ].join(\"\\n\"),\n            \"/* foo */ /* bar */ x();\",\n        ].forEach(function(code) {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                mangle: false,\n                output: {\n                    beautify: true,\n                    comments: \"all\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, code);\n        });\n    });\n\n    it(\"Should preserve new line before comment without beautify\", function() {\n        var code = [\n            \"function f(){\",\n            \"/* foo */bar()}\",\n        ].join(\"\\n\");\n        var result = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                comments: \"all\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, code);\n    });\n\n    it(\"Should handle comments around parentheses correctly\", function() {\n        var code = [\n            \"a();\",\n            \"/* foo */\",\n            \"(b())\",\n            \"/* bar */\",\n            \"c();\",\n        ].join(\"\\n\");\n        var result = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                comments: \"all\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"a();\",\n            \"/* foo */\",\n            \"b()\",\n            \"/* bar */;c();\",\n        ].join(\"\\n\"));\n    });\n\n    it(\"Should preserve comments around IIFE\", function() {\n        var result = UglifyJS.minify(\"/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();\", {\n            compress: false,\n            mangle: false,\n            output: {\n                comments: \"all\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, \"/*a*/ /*b*/(function(){/*c*/}/*d*/ /*e*/)();\");\n    });\n\n    it(\"Should output line comments after statements\", function() {\n        var result = UglifyJS.minify([\n            \"x()//foo\",\n            \"{y()//bar\",\n            \"}\",\n        ].join(\"\\n\"), {\n            compress: false,\n            mangle: false,\n            output: {\n                comments: \"all\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"x();//foo\",\n            \"{y();//bar\",\n            \"}\",\n        ].join(\"\\n\"));\n    });\n\n    it(\"Should handle programmatic AST insertions gracefully\", function() {\n        var ast = UglifyJS.parse([\n            \"function f() {\",\n            \"    //foo\",\n            \"    bar;\",\n            \"    return;\",\n            \"}\",\n        ].join(\"\\n\"));\n        ast.body[0].body[0] = new UglifyJS.AST_Throw({value: ast.body[0].body[0].body});\n        ast.body[0].body[1].value = new UglifyJS.AST_Number({value: 42});\n        assert.strictEqual(ast.print_to_string({comments: \"all\"}), [\n            \"function f(){\",\n            \"//foo\",\n            \"throw bar;return 42}\",\n        ].join(\"\\n\"));\n    });\n\n    it(\"Should not duplicate sourceMappingURL\", function() {\n        var code = [\n            \"//# sourceMappingURL=input.map\",\n            \"print(42);\",\n            \"//# sourceMappingURL=input.map\",\n            \"\",\n            \"//# sourceMappingURL=input.map\",\n            \"//# sourceMappingURL=input.map\",\n            \"\",\n        ].join(\"\\n\");\n\n        var result = UglifyJS.minify(code, {\n            output: { comments: true },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"//# sourceMappingURL=input.map\",\n            \"print(42);\",\n            \"//# sourceMappingURL=input.map\",\n            \"//# sourceMappingURL=input.map\",\n            \"//# sourceMappingURL=input.map\",\n        ].join(\"\\n\"));\n\n        result = UglifyJS.minify(code, {\n            output: { comments: true },\n            sourceMap: { url: \"output.map\" },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"//# sourceMappingURL=input.map\",\n            \"print(42);\",\n            \"//# sourceMappingURL=input.map\",\n            \"//# sourceMappingURL=input.map\",\n            \"//# sourceMappingURL=output.map\",\n        ].join(\"\\n\"));\n    });\n\n    describe(\"comment before constant\", function() {\n        var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';\n\n        it(\"Should test comment before constant is retained and output after mangle.\", function() {\n            var result = UglifyJS.minify(js, {\n                compress: { collapse_vars: false, reduce_vars: false },\n                output: { comments: true },\n            });\n            assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}');\n        });\n\n        it(\"Should test code works when comments disabled.\", function() {\n            var result = UglifyJS.minify(js, {\n                compress: { collapse_vars: false, reduce_vars: false },\n                output: { comments: false },\n            });\n            assert.strictEqual(result.code, 'function f(){var n=!1;return n}');\n        });\n    });\n\n    describe(\"comment filters\", function() {\n        it(\"Should be able to filter comments by passing regexp\", function() {\n            var ast = UglifyJS.parse(\"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n<!--test5\\n<!--!test6\\n-->test7\\n-->!test8\");\n            assert.strictEqual(ast.print_to_string({comments: /^!/}), \"/*!test1*/\\n//!test3\\n//!test6\\n//!test8\");\n        });\n\n        it(\"Should be able to filter comments with the 'all' option\", function() {\n            var ast = UglifyJS.parse(\"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n<!--test5\\n<!--!test6\\n-->test7\\n-->!test8\");\n            assert.strictEqual(ast.print_to_string({comments: \"all\"}), \"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n//test5\\n//!test6\\n//test7\\n//!test8\");\n        });\n\n        it(\"Should be able to filter comments with the 'some' option\", function() {\n            var ast = UglifyJS.parse(\"// foo\\n/*@preserve*/\\n// bar\\n/*@license*/\\n//@license with the wrong comment type\\n/*@cc_on something*/\");\n            assert.strictEqual(ast.print_to_string({comments: \"some\"}), \"/*@preserve*/\\n/*@license*/\\n/*@cc_on something*/\");\n        });\n\n        it(\"Should be able to filter comments by passing a function\", function() {\n            var ast = UglifyJS.parse(\"/*TEST 123*/\\n//An other comment\\n//8 chars.\");\n            var f = function(node, comment) {\n                return comment.value.length === 8;\n            };\n            assert.strictEqual(ast.print_to_string({comments: f}), \"/*TEST 123*/\\n//8 chars.\");\n        });\n\n        it(\"Should be able to filter comments by passing regex in string format\", function() {\n            var ast = UglifyJS.parse(\"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n<!--test5\\n<!--!test6\\n-->test7\\n-->!test8\");\n            assert.strictEqual(ast.print_to_string({comments: \"/^!/\"}), \"/*!test1*/\\n//!test3\\n//!test6\\n//!test8\");\n        });\n\n        it(\"Should be able to get the comment and comment type when using a function\", function() {\n            var ast = UglifyJS.parse(\"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n<!--test5\\n<!--!test6\\n-->test7\\n-->!test8\");\n            var f = function(node, comment) {\n                return comment.type == \"comment1\" || comment.type == \"comment3\";\n            };\n            assert.strictEqual(ast.print_to_string({comments: f}), \"//!test3\\n//test4\\n//test5\\n//!test6\");\n        });\n\n        it(\"Should be able to filter comments by passing a boolean\", function() {\n            var ast = UglifyJS.parse(\"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n<!--test5\\n<!--!test6\\n-->test7\\n-->!test8\");\n            assert.strictEqual(ast.print_to_string({comments: true}), \"/*!test1*/\\n/*test2*/\\n//!test3\\n//test4\\n//test5\\n//!test6\\n//test7\\n//!test8\");\n            assert.strictEqual(ast.print_to_string({comments: false}), \"\");\n        });\n\n        it(\"Should never be able to filter comment5 (shebangs)\", function() {\n            var ast = UglifyJS.parse(\"#!Random comment\\n//test1\\n/*test2*/\");\n            var f = function(node, comment) {\n                assert.strictEqual(comment.type === \"comment5\", false);\n                return true;\n            };\n            assert.strictEqual(ast.print_to_string({comments: f}), \"#!Random comment\\n//test1\\n/*test2*/\");\n        });\n\n        it(\"Should never be able to filter comment5 when using 'some' as filter\", function() {\n            var ast = UglifyJS.parse(\"#!foo\\n//foo\\n/*@preserve*/\\n/* please hide me */\");\n            assert.strictEqual(ast.print_to_string({comments: \"some\"}), \"#!foo\\n/*@preserve*/\");\n        });\n\n        it(\"Should have no problem on multiple calls\", function() {\n            const options = {\n                comments: /ok/,\n            };\n            assert.strictEqual(UglifyJS.parse(\"/* ok */ function a(){}\").print_to_string(options), \"/* ok */function a(){}\");\n            assert.strictEqual(UglifyJS.parse(\"/* ok */ function a(){}\").print_to_string(options), \"/* ok */function a(){}\");\n            assert.strictEqual(UglifyJS.parse(\"/* ok */ function a(){}\").print_to_string(options), \"/* ok */function a(){}\");\n        });\n\n        it(\"Should handle shebang and preamble correctly\", function() {\n            var code = UglifyJS.minify(\"#!/usr/bin/node\\nvar x = 10;\", {\n                output: { preamble: \"/* Build */\" },\n            }).code;\n            assert.strictEqual(code, \"#!/usr/bin/node\\n/* Build */\\nvar x=10;\");\n        });\n\n        it(\"Should handle preamble without shebang correctly\", function() {\n            var code = UglifyJS.minify(\"var x = 10;\", {\n                output: { preamble: \"/* Build */\" },\n            }).code;\n            assert.strictEqual(code, \"/* Build */\\nvar x=10;\");\n        });\n    });\n\n    describe(\"Huge number of comments.\", function() {\n        it(\"Should parse and compress code with thousands of consecutive comments\", function() {\n            var js = \"function lots_of_comments(x) { return 7 -\";\n            for (var i = 1; i <= 5000; ++i) js += \"// \" + i + \"\\n\";\n            for (; i <= 10000; ++i) js += \"/* \" + i + \" */ /**/\";\n            js += \"x; }\";\n            var result = UglifyJS.minify(js, {\n                mangle: false,\n            });\n            assert.strictEqual(result.code, \"function lots_of_comments(x){return 7-x}\");\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/directives.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"Directives\", function() {\n    it(\"Should allow tokenizer to store directives state\", function() {\n        var tokenizer = UglifyJS.tokenizer(\"\", \"foo.js\");\n        // Stack level 0\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n        // Stack level 2\n        tokenizer.push_directives_stack();\n        tokenizer.push_directives_stack();\n        tokenizer.add_directive(\"use strict\");\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), true);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n        // Stack level 3\n        tokenizer.push_directives_stack();\n        tokenizer.add_directive(\"use strict\");\n        tokenizer.add_directive(\"use asm\");\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), true);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), true);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n        // Stack level 2\n        tokenizer.pop_directives_stack();\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), true);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n        // Stack level 3\n        tokenizer.push_directives_stack();\n        tokenizer.add_directive(\"use thing\");\n        tokenizer.add_directive(\"use\\\\\\nasm\");\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), true);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false); // Directives are strict!\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), true);\n        // Stack level 2\n        tokenizer.pop_directives_stack();\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), true);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n        // Stack level 1\n        tokenizer.pop_directives_stack();\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n        // Stack level 0\n        tokenizer.pop_directives_stack();\n        assert.strictEqual(tokenizer.has_directive(\"use strict\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use asm\"), false);\n        assert.strictEqual(tokenizer.has_directive(\"use thing\"), false);\n    });\n    it(\"Should know which strings are directive and which ones are not\", function() {\n        [\n            [\n                '\"use strict\"\\n',\n                [ \"use strict\" ],\n                [ \"use asm\" ]\n            ],\n            [\n                '\"use\\\\\\nstrict\";',\n                [],\n                [ \"use strict\", \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                '\"use strict\"\\n\"use asm\"\\n\"use bar\"\\n',\n                [ \"use strict\", \"use asm\", \"use bar\" ],\n                [ \"use foo\", \"use\\\\x20strict\" ]\n            ],\n            [\n                '\"use \\\\\\nstrict\";\"use strict\";',\n                [ \"use strict\" ],\n                [ \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                '\"\\\\76\";',\n                [ \"\\\\76\" ],\n                [ \">\" ]\n            ],\n            [\n                // no ; or newline\n                '\"use strict\"',\n                [ \"use strict\" ],\n                [ \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                ';\"use strict\"',\n                [],\n                [ \"use strict\", \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            // Duplicate above code but put it in a function\n            [\n                'function foo() {\"use strict\"\\n',\n                [ \"use strict\" ],\n                [ \"use asm\" ]\n            ],\n            [\n                'function foo() {\"use\\\\\\nstrict\";',\n                [],\n                [ \"use strict\", \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                'function foo() {\"use strict\"\\n\"use asm\"\\n\"use bar\"\\n',\n                [ \"use strict\", \"use asm\", \"use bar\" ],\n                [ \"use foo\", \"use\\\\x20strict\" ]\n            ],\n            [\n                'function foo() {\"use \\\\\\nstrict\";\"use strict\";',\n                [ \"use strict\" ],\n                [ \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                'var foo = function() {\"\\\\76\";',\n                [ \"\\\\76\" ],\n                [ \">\" ]\n            ],\n            [\n                'var foo = function() {\"use strict\"', // no ; or newline\n                [ \"use strict\" ],\n                [ \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                'var foo = function() {;\"use strict\"',\n                [],\n                [ \"use strict\", \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            // Special cases\n            [\n                '\"1\";\"2\";\"3\";\"4\";;\"5\"',\n                [ \"1\", \"2\", \"3\", \"4\" ],\n                [ \"5\", \"6\", \"use strict\", \"use asm\" ]\n            ],\n            [\n                'if(1){\"use strict\";',\n                [],\n                [ \"use strict\", \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n            [\n                '\"use strict\";try{\"use asm\";',\n                [ \"use strict\" ],\n                [ \"use\\nstrict\", \"use \\nstrict\", \"use asm\" ]\n            ],\n        ].forEach(function(test) {\n            var tokenizer = UglifyJS.tokenizer(test[0] + \"]\", \"foo.js\");\n            assert.throws(function() {\n                UglifyJS.parse(tokenizer);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && /^Unexpected token: punc «]»/.test(e.message)\n            }, test[0]);\n            test[1].forEach(function(directive) {\n                assert.strictEqual(tokenizer.has_directive(directive), true, directive + \" in \" + test[0]);\n            });\n            test[2].forEach(function(fake_directive) {\n                assert.strictEqual(tokenizer.has_directive(fake_directive), false, fake_directive + \" in \" + test[0]);\n            });\n        });\n    });\n    it(\"Should print semicolon to separate strings from directives\", function() {\n        [\n            [ \"\", ';\"\";' ],\n            [ '\"test\";', '\"test\";;\"\";' ],\n            [ '\"test\";;', '\"test\";;\"\";' ],\n            [ '\"tests\";\\n', '\"tests\";;\"\";' ],\n            [ '\"tests\"', '\"tests\";;\"\";' ],\n            [ '\"tests\";   \\n\\t', '\"tests\";;\"\";' ],\n            [ '\"tests\";\\n\\n', '\"tests\";;\"\";' ],\n            [ '\\n\\n\"use strict\";\\n\\n', '\"use strict\";;\"\";' ],\n        ].forEach(function(test) {\n            var ast = UglifyJS.parse(test[0]);\n            ast.body.push(new UglifyJS.AST_SimpleStatement({\n                body: new UglifyJS.AST_String({ value: \"\" })\n            }));\n            var out = UglifyJS.OutputStream();\n            ast.print(out);\n            assert.strictEqual(out.get(), test[1], test[0]);\n        });\n    });\n    it(\"Should only print 2 semicolons spread over 2 lines in beautify mode\", function() {\n        var result = UglifyJS.minify([\n            '\"use strict\";',\n            \"'use strict';\",\n            '\"use strict\";',\n            '\"use strict\";',\n            \";'use strict';\",\n            \"console.log('use strict');\"\n        ].join(\"\"), {\n            compress: false,\n            output: {\n                beautify: true,\n                quote_style: 3\n            }\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            '\"use strict\";',\n            \"'use strict';\",\n            '\"use strict\";',\n            '\"use strict\";',\n            \";'use strict';\",\n            \"console.log('use strict');\"\n        ].join(\"\\n\\n\"));\n    });\n    it(\"Should not add double semicolons in non-scoped block statements to avoid strings becoming directives\", function() {\n        [\n            [\n                '\"use strict\";\"use\\\\x20strict\";',\n                '\"use strict\";\"use\\\\x20strict\";'\n            ],\n            [\n                '{\"use\\\\x20strict\"}',\n                '{\"use strict\"}'\n            ],\n            [\n                'function foo(){\"use\\\\x20strict\";}', // Valid place for directives\n                'function foo(){\"use\\\\x20strict\"}'\n            ],\n            [\n                'try{\"use\\\\x20strict\"}catch(e){}finally{\"use\\\\x20strict\"}',\n                'try{\"use strict\"}catch(e){}finally{\"use strict\"}'\n            ],\n            [\n                'if(1){\"use\\\\x20strict\"} else {\"use strict\"}',\n                'if(1){\"use strict\"}else{\"use strict\"}'\n            ]\n        ].forEach(function(test) {\n            var result = UglifyJS.minify(test[0], {\n                compress: false,\n                mangle: false\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, test[1], test[0]);\n        });\n    });\n    it(\"Should check quote style of directives\", function() {\n        [\n            // 0. Prefer double quotes, unless string contains more double quotes than single quotes\n            [\n                '\"testing something\";',\n                0,\n                '\"testing something\";'\n            ],\n            [\n                \"'use strict';\",\n                0,\n                '\"use strict\";'\n            ],\n            [\n                '\"\\\\\\'use strict\\\\\\'\";',\n                0,\n                '\"\\\\\\'use strict\\\\\\'\";',\n            ],\n            [\n                \"'\\\"use strict\\\"';\",\n                0,\n                \"'\\\"use strict\\\"';\",\n            ],\n            // 1. Always use single quote\n            [\n                '\"testing something\";',\n                1,\n                \"'testing something';\"\n            ],\n            [\n                \"'use strict';\",\n                1,\n                \"'use strict';\"\n            ],\n            [\n                '\"\\'use strict\\'\";',\n                1,\n                // Intentionally causes directive breakage at cost of less logic, usage should be rare anyway\n                '\"\\'use strict\\'\";',\n            ],\n            [\n                \"'\\\\'use strict\\\\'';\", // Not a valid directive\n                1,\n                \"'\\\\'use strict\\\\'';\" // But no ; necessary as directive stays invalid\n            ],\n            [\n                \"'\\\"use strict\\\"';\",\n                1,\n                \"'\\\"use strict\\\"';\",\n            ],\n            // 2. Always use double quote\n            [\n                '\"testing something\";',\n                2,\n                '\"testing something\";'\n            ],\n            [\n                \"'use strict';\",\n                2,\n                '\"use strict\";'\n            ],\n            [\n                '\"\\'use strict\\'\";',\n                2,\n                \"\\\"'use strict'\\\";\",\n            ],\n            [\n                \"'\\\"use strict\\\"';\",\n                2,\n                // Intentionally causes directive breakage at cost of less logic, usage should be rare anyway\n                \"'\\\"use strict\\\"';\",\n            ],\n            [\n                '\"\\\\\"use strict\\\\\"\";', // Not a valid directive\n                2,\n                '\"\\\\\"use strict\\\\\"\";' // But no ; necessary as directive stays invalid\n            ],\n            // 3. Always use original\n            [\n                '\"testing something\";',\n                3,\n                '\"testing something\";'\n            ],\n            [\n                \"'use strict';\",\n                3,\n                \"'use strict';\",\n            ],\n            [\n                '\"\\'use strict\\'\";',\n                3,\n                '\"\\'use strict\\'\";',\n            ],\n            [\n                \"'\\\"use strict\\\"';\",\n                3,\n                \"'\\\"use strict\\\"';\",\n            ],\n        ].forEach(function(test) {\n            var result = UglifyJS.minify(test[0], {\n                compress: false,\n                output: {\n                    quote_style: test[1]\n                }\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, test[2], test[0] + \" using mode \" + test[1]);\n        });\n    });\n    it(\"Should be able to compress without side effects\", function() {\n        [\n            [\n                '\"use strict\";\"use strict\";\"use strict\";\"use foo\";\"use strict\";;\"use sloppy\";doSomething(\"foo\");',\n                '\"use strict\";doSomething(\"foo\");'\n            ],\n            [\n                // Nothing gets optimized in the compressor because \"use asm\" is the first statement\n                '\"use asm\";\"use\\\\x20strict\";1+1;',\n                '\"use asm\";\"use\\\\x20strict\";1+1;'\n            ],\n            [\n                'function f(){ \"use strict\" }',\n                'function f(){}'\n            ],\n            [\n                'function f(){ \"use asm\" }',\n                'function f(){\"use asm\"}'\n            ],\n            [\n                'function f(){ \"use nondirective\" }',\n                'function f(){}'\n            ],\n            [\n                'function f(){ ;\"use strict\" }',\n                'function f(){}'\n            ],\n            [\n                'function f(){ \"use \\\\n\"; }',\n                'function f(){}'\n            ],\n        ].forEach(function(test) {\n            var result = UglifyJS.minify(test[0], {\n                module: false,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, test[1], test[0]);\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/exports.js",
    "content": "var acorn = require(\"acorn\");\nvar assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"export\", function() {\n    it(\"Should reject invalid `export ...` statement syntax\", function() {\n        [\n            \"export *;\",\n            \"export A;\",\n            \"export 42;\",\n            \"export var;\",\n            \"export * as A;\",\n            \"export A as B;\",\n            \"export const A;\",\n            \"export function(){};\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject invalid `export { ... }` statement syntax\", function() {\n        [\n            \"export { * };\",\n            \"export { * as A };\",\n            \"export { 42 as A };\",\n            \"export { 'A' as B };\",\n            \"export { A as B-C };\",\n            \"export { default as A };\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject invalid `export default ...` statement syntax\", function() {\n        [\n            \"export default *;\",\n            \"export default var;\",\n            \"export default A as B;\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject invalid `export ... from ...` statement syntax\", function() {\n        [\n            \"export from 'path';\",\n            \"export A from 'path';\",\n            \"export * from `path`;\",\n            \"export 'A' from 'path';\",\n            \"export A as B from 'path';\",\n            \"export 'A' as B from 'path';\",\n            \"export default from 'path';\",\n            \"export { A }, B from 'path';\",\n            \"export * as A, B from 'path';\",\n            \"export * as A, {} from 'path';\",\n            \"export { * as A } from 'path';\",\n            \"export { 42 as A } from 'path';\",\n            \"export { A-B as C } from 'path';\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject `export` statement not under top-level scope\", function() {\n        [\n            \"{ export {}; }\",\n            \"if (0) export var A;\",\n            \"function f() { export default 42; }\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should compare `export` statements correctly\", function() {\n        var stats = {\n            Declaration: [\n                \"export let A;\",\n                \"export const A = 42;\",\n                \"export var { A, B: [] } = C;\",\n                \"export function A() { return B(A); }\",\n                \"export async function* A({}, ...[]) { return B(A); }\",\n            ],\n            Default: [\n                \"export default 42;\",\n                \"export default A => A(B);\",\n                \"export default class A extends B {}\",\n                \"export default (class A extends B {});\",\n                \"export default class A { static C = 42; }\",\n                \"export default class A extends B { static C = 42; }\",\n            ],\n            Foreign: [\n                \"export * from 'path';\",\n                \"export {} from 'path';\",\n                \"export * as A from 'path';\",\n                \"export { default } from 'path';\",\n                \"export { A, B as C } from 'path';\",\n                \"export { A, default as C } from 'path';\",\n            ],\n            References: [\n                \"export {};\",\n                \"export { A };\",\n                \"export { A as B };\",\n                \"export { A, B as C };\",\n                \"export { A as default };\",\n            ],\n        };\n        for (var k in stats) stats[k].forEach(function(c, i) {\n            var s = UglifyJS.parse(c);\n            assert.ok(s instanceof UglifyJS.AST_Toplevel, c);\n            assert.strictEqual(s.body.length, 1, c);\n            assert.strictEqual(s.body[0].TYPE, \"Export\" + k, c);\n            for (var l in stats) stats[l].forEach(function(d, j) {\n                var t = UglifyJS.parse(d);\n                assert.ok(t instanceof UglifyJS.AST_Toplevel, d);\n                assert.strictEqual(t.body.length, 1, d);\n                assert.strictEqual(t.body[0].TYPE, \"Export\" + l, d);\n                assert.strictEqual(s.equals(t), k === l && i === j, c + \"\\n\" + d);\n            });\n        });\n    });\n    it(\"Should interoperate with ESTree correctly\", function() {\n        [\n            \"export var A = 42;\",\n            \"export default (class A {});\",\n            \"var A; export { A as '42' };\",\n            \"export { '42' } from 'path';\",\n            \"export * as '42' from 'path';\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(code);\n            try {\n                var spidermonkey = ast.to_mozilla_ast();\n            } catch (ex) {\n                assert.fail(\"[to_mozilla_ast] \" + ex.stack);\n            }\n            try {\n                var ast2 = UglifyJS.AST_Node.from_mozilla_ast(spidermonkey);\n            } catch (ex) {\n                assert.fail(\"[from_mozilla_ast] \" + ex.stack);\n            }\n            assert.strictEqual(ast2.print_to_string(), ast.print_to_string(), [\n                \"spidermonkey:\",\n                ast.print_to_string(),\n                ast2.print_to_string(),\n            ].join(\"\\n\"));\n            try {\n                var acorn_est = acorn.parse(code, {\n                    ecmaVersion: \"latest\",\n                    locations: true,\n                    sourceType: \"module\",\n                });\n            } catch (ex) {\n                assert.fail(\"[acorn.parse] \" + ex.stack);\n            }\n            try {\n                var ast3 = UglifyJS.AST_Node.from_mozilla_ast(acorn_est);\n            } catch (ex) {\n                assert.fail(\"[from_acorn] \" + ex.stack);\n            }\n            assert.strictEqual(ast3.print_to_string(), ast.print_to_string(), [\n                \"acorn:\",\n                ast.print_to_string(),\n                ast3.print_to_string(),\n            ].join(\"\\n\"));\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/getter-setter.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"Getters and setters\", function() {\n    it(\"Should not accept operator symbols as getter/setter name\", function() {\n        [\n            \"++\",\n            \"--\",\n            \"+\",\n            \"-\",\n            \"!\",\n            \"~\",\n            \"&\",\n            \"|\",\n            \"^\",\n            \"*\",\n            \"/\",\n            \"%\",\n            \">>\",\n            \"<<\",\n            \">>>\",\n            \"<\",\n            \">\",\n            \"<=\",\n            \">=\",\n            \"==\",\n            \"===\",\n            \"!=\",\n            \"!==\",\n            \"?\",\n            \"=\",\n            \"+=\",\n            \"-=\",\n            \"/=\",\n            \"*=\",\n            \"%=\",\n            \">>=\",\n            \"<<=\",\n            \">>>=\",\n            \"|=\",\n            \"^=\",\n            \"&=\",\n            \"&&\",\n            \"||\"\n        ].reduce(function(tests, illegalOperator) {\n            tests.push({\n                code: \"var obj = { get \" + illegalOperator + \"() { return test; }};\",\n                operator: illegalOperator,\n            });\n            tests.push({\n                code: \"var obj = { set \" + illegalOperator + \"(value) { test = value; }};\",\n                operator: illegalOperator,\n            });\n            return tests;\n        }, []).forEach(function(test) {\n            assert.throws(function() {\n                UglifyJS.parse(test.code);\n            }, test.operator == \"=\" ? function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && /^Unexpected token: punc «{», expected: punc «.*?»$/.test(e.message);\n            } : function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && e.message === \"Unexpected token: operator «\" + test.operator + \"»\";\n            }, \"Expected but didn't get a syntax error while parsing following line:\\n\" + test.code);\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/glob.js",
    "content": "var assert = require(\"assert\");\nvar exec = require(\"child_process\").exec;\nvar path = require(\"path\");\n\ndescribe(\"bin/uglifyjs with input file globs\", function() {\n    var uglifyjscmd = '\"' + process.argv[0] + '\" bin/uglifyjs';\n    it(\"bin/uglifyjs with one input file extension glob.\", function(done) {\n        var command = [\n            uglifyjscmd,\n            '\"test/input/issue-1242/foo.*\"',\n            \"--compress\",\n            \"--mangle\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print(\"Foo:\",2*o)}\\n');\n            done();\n        });\n    });\n    it(\"bin/uglifyjs with one input file name glob.\", function(done) {\n        var command = [\n            uglifyjscmd,\n            '\"test/input/issue-1242/b*.es5\"',\n            \"--compress\",\n            \"--mangle\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\\n');\n            done();\n        });\n    });\n    it(\"bin/uglifyjs with multiple input file globs.\", function(done) {\n        var command = [\n            uglifyjscmd,\n            '\"test/input/issue-1242/???.es5\"',\n            '\"test/input/issue-1242/*.js\"',\n            \"--compress\", \"toplevel,passes=3\",\n            \"--mangle\",\n            \"--no-module\",\n        ].join(\" \");\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n            assert.strictEqual(stdout, 'var print=console.log.bind(console);print(\"qux\",9,6),print(\"Foo:\",22);\\n');\n            done();\n        });\n    });\n    it(\"Should throw with non-matching glob string\", function(done) {\n        var command = uglifyjscmd + ' \"test/input/issue-1242/blah.*\"';\n\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.ok(/^ERROR: ENOENT/.test(stderr));\n            done();\n        });\n    });\n    it('\"?\" in glob string should not match \"/\"', function(done) {\n        var command = uglifyjscmd + ' \"test/input?issue-1242/foo.*\"';\n\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.ok(/^ERROR: ENOENT/.test(stderr));\n            done();\n        });\n    });\n    it(\"Should handle special characters in glob string\", function(done) {\n        var command = uglifyjscmd + ' \"test/input/issue-1632/^{*}[???](*)+$.??\" -cm';\n\n        exec(command, function(err, stdout) {\n            if (err) throw err;\n\n            assert.strictEqual(stdout, \"console.log(x);\\n\");\n            done();\n        });\n    });\n    it(\"Should handle array of glob strings - matching and otherwise\", function(done) {\n        var dir = \"test/input/issue-1242\";\n        var command = uglifyjscmd + ' \"' + [\n            path.join(dir, \"b*.es5\"),\n            path.join(dir, \"z*.es5\"),\n            path.join(dir, \"*.js\")\n        ].join('\" \"') + '\"';\n\n        exec(command, function(err, stdout, stderr) {\n            assert.ok(err);\n            assert.ok(/^ERROR: ENOENT.*?z\\*\\.es5/.test(stderr));\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/imports.js",
    "content": "var acorn = require(\"acorn\");\nvar assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"import\", function() {\n    it(\"Should reject invalid `import` statement syntax\", function() {\n        [\n            \"import *;\",\n            \"import A;\",\n            \"import {};\",\n            \"import `path`;\",\n            \"{ import 'path'; }\",\n            \"import from 'path';\",\n            \"if (0) import 'path';\",\n            \"import * from 'path';\",\n            \"import 'A' from 'path';\",\n            \"import A-B from 'path';\",\n            \"import A as B from 'path';\",\n            \"import { A }, B from 'path';\",\n            \"import * as 'A' from 'path';\",\n            \"import * as A-B from 'path';\",\n            \"import * as A, B from 'path';\",\n            \"import * as A, {} from 'path';\",\n            \"import { * as A } from 'path';\",\n            \"import { * as 'A' } from 'path';\",\n            \"import { * as A-B } from 'path';\",\n            \"function f() { import 'path'; }\",\n            \"import { 42 as A } from 'path';\",\n            \"import { A-B as C } from 'path';\",\n            \"import { 'A' as 'B' } from 'path';\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should compare `import` statements correctly\", function() {\n        [\n            \"import 'foo';\",\n            \"import 'path';\",\n            \"import A from 'path';\",\n            \"import { A } from 'path';\",\n            \"import * as A from 'path';\",\n            \"import A, { B } from 'path';\",\n            \"import A, * as B from 'path';\",\n            \"import { A as B } from 'path';\",\n            \"import A, { B, C as D } from 'path';\",\n        ].forEach(function(c, i, stats) {\n            var s = UglifyJS.parse(c);\n            assert.ok(s instanceof UglifyJS.AST_Toplevel, c);\n            assert.strictEqual(s.body.length, 1, c);\n            assert.ok(s.body[0] instanceof UglifyJS.AST_Import, c);\n            stats.forEach(function(d, j) {\n                var t = UglifyJS.parse(d);\n                assert.ok(t instanceof UglifyJS.AST_Toplevel, d);\n                assert.strictEqual(t.body.length, 1, d);\n                assert.ok(t.body[0] instanceof UglifyJS.AST_Import, d);\n                assert.strictEqual(s.equals(t), i === j, c + \"\\n\" + d);\n            });\n        });\n    });\n    it(\"Should interoperate with ESTree correctly\", function() {\n        [\n            \"import A from 'path';\",\n            \"import * as A from 'path';\",\n            \"import A, * as B from 'path';\",\n            \"import { '42' as A, B } from 'path';\",\n            \"import A, { '42' as B } from 'path';\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(code);\n            try {\n                var spidermonkey = ast.to_mozilla_ast();\n            } catch (ex) {\n                assert.fail(\"[to_mozilla_ast] \" + ex.stack);\n            }\n            try {\n                var ast2 = UglifyJS.AST_Node.from_mozilla_ast(spidermonkey);\n            } catch (ex) {\n                assert.fail(\"[from_mozilla_ast] \" + ex.stack);\n            }\n            assert.strictEqual(ast2.print_to_string(), ast.print_to_string(), [\n                \"spidermonkey:\",\n                ast.print_to_string(),\n                ast2.print_to_string(),\n            ].join(\"\\n\"));\n            try {\n                var acorn_est = acorn.parse(code, {\n                    ecmaVersion: \"latest\",\n                    locations: true,\n                    sourceType: \"module\",\n                });\n            } catch (ex) {\n                assert.fail(\"[acorn.parse] \" + ex.stack);\n            }\n            try {\n                var ast3 = UglifyJS.AST_Node.from_mozilla_ast(acorn_est);\n            } catch (ex) {\n                assert.fail(\"[from_acorn] \" + ex.stack);\n            }\n            assert.strictEqual(ast3.print_to_string(), ast.print_to_string(), [\n                \"acorn:\",\n                ast.print_to_string(),\n                ast3.print_to_string(),\n            ].join(\"\\n\"));\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/let.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"let\", function() {\n    this.timeout(30000);\n    it(\"Should not produce reserved keywords as variable name in mangle\", function() {\n        // Produce a lot of variables in a function and run it through mangle.\n        var s = '\"dddddeeeeelllllooooottttt\"; function foo() {';\n        for (var i = 0; i < 18000; i++) {\n            s += \"var v\" + i + \"=[];\";\n        }\n        s += '}';\n        var result = UglifyJS.minify(s, {\n            compress: false,\n        });\n        if (result.error) throw result.error;\n        // Verify that select keywords and reserved keywords not produced\n        [\n            \"do\",\n            \"let\",\n            \"var\",\n        ].forEach(function(name) {\n            assert.strictEqual(result.code.indexOf(\"var \" + name + \"=\"), -1);\n        });\n        // Verify that the variable names that appeared immediately before\n        // and after the erroneously generated variable name still exist\n        // to show the test generated enough symbols.\n        [\n            \"to\", \"eo\",\n            \"eet\", \"fet\",\n            \"rar\", \"oar\",\n        ].forEach(function(name) {\n            assert.notStrictEqual(result.code.indexOf(\"var \" + name + \"=\"), -1);\n        });\n    });\n    it(\"Should quote mangled properties that are reserved keywords\", function() {\n        var s = '\"rrrrrnnnnniiiiiaaaaa\";';\n        for (var i = 0; i < 18000; i++) {\n            s += \"v.b\" + i + \"=v;\";\n        }\n        var result = UglifyJS.minify(s, {\n            compress: false,\n            ie: true,\n            mangle: {\n                properties: {\n                    domprops: true,\n                },\n            },\n        });\n        if (result.error) throw result.error;\n        [\n            \"in\",\n            \"var\",\n        ].forEach(function(name) {\n            assert.notStrictEqual(result.code.indexOf('v[\"' + name + '\"]'), -1);\n        });\n    });\n    it(\"Should parse `let` as name correctly\", function() {\n        [\n            \"for(var let;let;let)let;\",\n            \"function let(let){let}\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(code);\n            assert.strictEqual(ast.print_to_string(), code);\n            assert.throws(function() {\n                UglifyJS.parse('\"use strict\";' + code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error && e.message == \"Unexpected let in strict mode\";\n            }, code);\n        });\n    });\n    it(\"Should throw on ambiguous use of `let`\", function() {\n        [\n            \"export let\",\n            [\n                \"let\",\n                \"console.log(42)\",\n            ].join(\"\\n\"),\n            [\n                \"let\",\n                \"[ console.log(42) ]\",\n            ].join(\"\\n\"),\n            [\n                \"let\",\n                \"{\",\n                \"    console.log(42)\",\n                \"}\",\n            ].join(\"\\n\"),\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/line-endings.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"line-endings\", function() {\n    var options = {\n        compress: false,\n        mangle: false,\n        output: {\n            beautify: false,\n            comments: /^!/,\n        }\n    };\n    var expected_code = '/*!one\\n2\\n3*/\\nfunction f(x){if(x)return 3}';\n\n    it(\"Should parse LF line endings\", function() {\n        var js = '/*!one\\n2\\n3*///comment\\nfunction f(x) {\\n if (x)\\n//comment\\n  return 3;\\n}\\n';\n        var result = UglifyJS.minify(js, options);\n        assert.strictEqual(result.code, expected_code);\n    });\n\n    it(\"Should parse CR/LF line endings\", function() {\n        var js = '/*!one\\r\\n2\\r\\n3*///comment\\r\\nfunction f(x) {\\r\\n if (x)\\r\\n//comment\\r\\n  return 3;\\r\\n}\\r\\n';\n        var result = UglifyJS.minify(js, options);\n        assert.strictEqual(result.code, expected_code);\n    });\n\n    it(\"Should parse CR line endings\", function() {\n        var js = '/*!one\\r2\\r3*///comment\\rfunction f(x) {\\r if (x)\\r//comment\\r  return 3;\\r}\\r';\n        var result = UglifyJS.minify(js, options);\n        assert.strictEqual(result.code, expected_code);\n    });\n\n    it(\"Should not allow line terminators in regexp\", function() {\n        var inputs = [\n            \"/\\n/\",\n            \"/\\r/\",\n            \"/\\u2028/\",\n            \"/\\u2029/\",\n            \"/\\\\\\n/\",\n            \"/\\\\\\r/\",\n            \"/\\\\\\u2028/\",\n            \"/\\\\\\u2029/\",\n            \"/someRandomTextLike[]()*AndThen\\n/\"\n        ]\n        var test = function(input) {\n            return function() {\n                UglifyJS.parse(input);\n            }\n        }\n        var fail = function(e) {\n            return e instanceof UglifyJS.JS_Parse_Error\n                && e.message === \"Unexpected line terminator\";\n        }\n        for (var i = 0; i < inputs.length; i++) {\n            assert.throws(test(inputs[i]), fail);\n        }\n    });\n});\n"
  },
  {
    "path": "test/mocha/minify-file-map.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../..\");\n\ndescribe(\"Input file as map\", function() {\n    it(\"Should accept object\", function() {\n        var jsMap = {\n            '/scripts/foo.js': 'var foo = {\"x\": 1, y: 2, \\'z\\': 3};'\n        };\n        var result = UglifyJS.minify(jsMap, {\n            sourceMap: true,\n        });\n        if (result.error) throw result.error;\n        var map = JSON.parse(result.map);\n        assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');\n        assert.deepEqual(map.sources, ['/scripts/foo.js']);\n        assert.strictEqual(map.file, undefined);\n\n        result = UglifyJS.minify(jsMap);\n        assert.strictEqual(result.map, undefined);\n\n        result = UglifyJS.minify(jsMap, {sourceMap: {filename: 'out.js'}});\n        map = JSON.parse(result.map);\n        assert.strictEqual(map.file, 'out.js');\n    });\n\n    it(\"Should accept array of strings\", function() {\n        var jsSeq = [\n            'var foo = {\"x\": 1, y: 2, \\'z\\': 3};',\n            'var bar = 15;'\n        ];\n        var result = UglifyJS.minify(jsSeq, {\n            sourceMap: true,\n        });\n        if (result.error) throw result.error;\n        var map = JSON.parse(result.map);\n        assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');\n        assert.deepEqual(map.sources, ['0', '1']);\n    });\n\n    it(\"Should correctly include source\", function() {\n        var jsMap = {\n            '/scripts/foo.js': 'var foo = {\"x\": 1, y: 2, \\'z\\': 3};'\n        };\n        var result = UglifyJS.minify(jsMap, {\n            sourceMap: {\n                includeSources: true,\n            },\n        });\n        if (result.error) throw result.error;\n        var map = JSON.parse(result.map);\n        assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');\n        assert.deepEqual(map.sourcesContent, ['var foo = {\"x\": 1, y: 2, \\'z\\': 3};']);\n    });\n});\n"
  },
  {
    "path": "test/mocha/minify.js",
    "content": "var assert = require(\"assert\");\nvar readFileSync = require(\"fs\").readFileSync;\nvar run_code = require(\"../sandbox\").run_code;\nvar semver = require(\"semver\");\nvar UglifyJS = require(\"../..\");\n\nfunction read(path) {\n    return readFileSync(path, \"utf8\");\n}\n\ndescribe(\"minify\", function() {\n    it(\"Should test basic sanity of minify with default options\", function() {\n        var js = \"function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }\";\n        var result = UglifyJS.minify(js);\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, \"function foo(n){return n?3:7}\");\n    });\n    it(\"Should not mutate minify `options`\", function() {\n        var options = {\n            compress: true,\n            mangle: false,\n            output: {\n                v8: false,\n            },\n            webkit: true,\n        };\n        var value = JSON.stringify(options);\n        var result = UglifyJS.minify(\"print(6 * 7);\", options);\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, \"print(42);\");\n        assert.strictEqual(JSON.stringify(options), value);\n    });\n    it(\"Should skip inherited keys from `files`\", function() {\n        var files = Object.create({ skip: this });\n        files[0] = \"alert(1 + 1)\";\n        var result = UglifyJS.minify(files);\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, \"alert(2);\");\n    });\n    it(\"Should work with mangle.cache\", function() {\n        var cache = {};\n        var original = \"\";\n        var compressed = \"\";\n        [\n            \"bar.es5\",\n            \"baz.es5\",\n            \"foo.es5\",\n            \"qux.js\",\n        ].forEach(function(file) {\n            var code = read(\"test/input/issue-1242/\" + file);\n            var result = UglifyJS.minify(code, {\n                mangle: {\n                    cache: cache,\n                    toplevel: true,\n                },\n            });\n            if (result.error) throw result.error;\n            original += code;\n            compressed += result.code;\n        });\n        assert.strictEqual(JSON.stringify(cache).slice(0, 10), '{\"props\":{');\n        assert.strictEqual(compressed, [\n            \"function n(n){return 3*n}\",\n            \"function r(n){return n/2}\",\n            \"var c=console.log.bind(console);\",\n            'function o(o){c(\"Foo:\",2*o)}',\n            \"var a=n(3),b=r(12);\",\n            'c(\"qux\",a,b),o(11);',\n        ].join(\"\"));\n        assert.strictEqual(run_code(compressed, true), run_code(original, true));\n    });\n    it(\"Should work with nameCache\", function() {\n        var cache = {};\n        var original = \"\";\n        var compressed = \"\";\n        [\n            \"bar.es5\",\n            \"baz.es5\",\n            \"foo.es5\",\n            \"qux.js\",\n        ].forEach(function(file) {\n            var code = read(\"test/input/issue-1242/\" + file);\n            var result = UglifyJS.minify(code, {\n                mangle: {\n                    toplevel: true,\n                },\n                nameCache: cache,\n            });\n            if (result.error) throw result.error;\n            original += code;\n            compressed += result.code;\n        });\n        assert.strictEqual(JSON.stringify(cache).slice(0, 18), '{\"vars\":{\"props\":{');\n        assert.strictEqual(compressed, [\n            \"function n(n){return 3*n}\",\n            \"function r(n){return n/2}\",\n            \"var c=console.log.bind(console);\",\n            'function o(o){c(\"Foo:\",2*o)}',\n            \"var a=n(3),b=r(12);\",\n            'c(\"qux\",a,b),o(11);',\n        ].join(\"\"));\n        assert.strictEqual(run_code(compressed, true), run_code(original, true));\n    });\n    it(\"Should avoid cached names when mangling top-level variables\", function() {\n        var cache = {};\n        var original = \"\";\n        var compressed = \"\";\n        [\n            '\"xxxyy\";var i={s:1};',\n            '\"xxyyy\";var j={t:2,u:3},k=4;',\n            'console.log(i.s,j.t,j.u,k);',\n        ].forEach(function(code) {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                mangle: {\n                    properties: {\n                        domprops: true,\n                    },\n                    toplevel: true,\n                },\n                nameCache: cache,\n            });\n            if (result.error) throw result.error;\n            original += code;\n            compressed += result.code;\n        });\n        assert.strictEqual(compressed, [\n            '\"xxxyy\";var x={x:1};',\n            '\"xxyyy\";var y={y:2,a:3},a=4;',\n            'console.log(x.x,y.y,y.a,a);',\n        ].join(\"\"));\n        assert.strictEqual(run_code(compressed, true), run_code(original, true));\n    });\n    it(\"Should avoid cached names when mangling inner-scoped variables\", function() {\n        var cache = {};\n        var original = \"\";\n        var compressed = \"\";\n        [\n            'var extend = function(a, b) { console.log(\"extend\"); a(); b(); }; function A() { console.log(\"A\"); };',\n            'var B = function(A) { function B() { console.log(\"B\") }; extend(B, A); return B; }(A);',\n        ].forEach(function(code) {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                nameCache: cache,\n                toplevel: true,\n            });\n            if (result.error) throw result.error;\n            original += code;\n            compressed += result.code;\n        });\n        assert.strictEqual(compressed, [\n            'var o=function(o,n){console.log(\"extend\");o();n()};function n(){console.log(\"A\")}',\n            'var e=function(n){function e(){console.log(\"B\")}o(e,n);return e}(n);',\n        ].join(\"\"));\n        assert.strictEqual(run_code(compressed, true), run_code(original, true));\n    });\n    it(\"Should not parse invalid use of reserved words\", function() {\n        assert.strictEqual(UglifyJS.minify(\"function enum(){}\").error, undefined);\n        assert.strictEqual(UglifyJS.minify(\"function static(){}\").error, undefined);\n        assert.strictEqual(UglifyJS.minify(\"function this(){}\").error.message, \"Unexpected token: name «this»\");\n    });\n\n    describe(\"keep_quoted_props\", function() {\n        it(\"Should preserve quotes in object literals\", function() {\n            var js = 'var foo = {\"x\": 1, y: 2, \\'z\\': 3};';\n            var result = UglifyJS.minify(js, {\n                output: {\n                    keep_quoted_props: true,\n                },\n            });\n            assert.strictEqual(result.code, 'var foo={\"x\":1,y:2,\"z\":3};');\n        });\n        it(\"Should preserve quote styles when quote_style is 3\", function() {\n            var js = 'var foo = {\"x\": 1, y: 2, \\'z\\': 3};';\n            var result = UglifyJS.minify(js, {\n                output: {\n                    keep_quoted_props: true,\n                    quote_style: 3,\n                },\n            });\n            assert.strictEqual(result.code, 'var foo={\"x\":1,y:2,\\'z\\':3};');\n        });\n        it(\"Should not preserve quotes in object literals when disabled\", function() {\n            var js = 'var foo = {\"x\": 1, y: 2, \\'z\\': 3};';\n            var result = UglifyJS.minify(js, {\n                output: {\n                    keep_quoted_props: false,\n                    quote_style: 3,\n                },\n            });\n            assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');\n        });\n    });\n\n    describe(\"mangleProperties\", function() {\n        it(\"Shouldn't mangle quoted properties\", function() {\n            var js = 'a[\"foo\"] = \"bar\"; a.color = \"red\"; x = {\"bar\": 10};';\n            var result = UglifyJS.minify(js, {\n                compress: true,\n                mangle: {\n                    properties: {\n                        domprops: true,\n                        keep_quoted: true,\n                    },\n                },\n                output: {\n                    keep_quoted_props: true,\n                    quote_style: 3,\n                },\n            });\n            assert.strictEqual(result.code, 'a[\"foo\"]=\"bar\",a.a=\"red\",x={\"bar\":10};');\n        });\n        it(\"Should not mangle quoted property within dead code\", function() {\n            var result = UglifyJS.minify('({ \"keep\": 1 }); g.keep = g.change = 42;', {\n                mangle: {\n                    properties: {\n                        keep_quoted: true,\n                    },\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, \"g.keep=g.g=42;\");\n        });\n    });\n\n    describe(\"#__PURE__\", function() {\n        it(\"Should drop #__PURE__ hint after use\", function() {\n            var result = UglifyJS.minify('//@__PURE__ comment1 #__PURE__ comment2\\n foo(), bar();', {\n                output: {\n                    comments: \"all\",\n                    beautify: false,\n                },\n            });\n            var code = result.code;\n            assert.strictEqual(code, \"//  comment1   comment2\\nbar();\");\n        });\n        it(\"Should drop #__PURE__ hint if function is retained\", function() {\n            var result = UglifyJS.minify(\"var a = /*#__PURE__*/(function(){ foo(); })();\", {\n                output: {\n                    comments: \"all\",\n                    beautify: false,\n                },\n            });\n            var code = result.code;\n            assert.strictEqual(code, \"var a=(()=>{foo()})();\");\n        });\n    });\n\n    describe(\"JS_Parse_Error\", function() {\n        it(\"Should return syntax error\", function() {\n            var result = UglifyJS.minify(\"function f(a{}\");\n            var err = result.error;\n            assert.ok(err instanceof Error);\n            assert.strictEqual(err.stack.split(/\\n/)[0], \"SyntaxError: Unexpected token: punc «{», expected: punc «,»\");\n            assert.strictEqual(err.filename, \"0\");\n            assert.strictEqual(err.line, 1);\n            assert.strictEqual(err.col, 12);\n        });\n        it(\"Should reject duplicated label name\", function() {\n            var result = UglifyJS.minify(\"L:{L:{}}\");\n            var err = result.error;\n            assert.ok(err instanceof Error);\n            assert.strictEqual(err.stack.split(/\\n/)[0], \"SyntaxError: Label L defined twice\");\n            assert.strictEqual(err.filename, \"0\");\n            assert.strictEqual(err.line, 1);\n            assert.strictEqual(err.col, 4);\n        });\n    });\n\n    describe(\"global_defs\", function() {\n        it(\"Should throw for non-trivial expressions\", function() {\n            var result = UglifyJS.minify(\"alert(42);\", {\n                compress: {\n                    global_defs: {\n                        \"@alert\": \"debugger\"\n                    }\n                }\n            });\n            var err = result.error;\n            assert.ok(err instanceof Error);\n            assert.strictEqual(err.stack.split(/\\n/)[0], \"SyntaxError: Unexpected token: keyword «debugger»\");\n        });\n        it(\"Should skip inherited properties\", function() {\n            var foo = Object.create({ skip: this });\n            foo.bar = 42;\n            var result = UglifyJS.minify(\"alert(FOO);\", {\n                compress: {\n                    global_defs: {\n                        FOO: foo\n                    }\n                }\n            });\n            assert.strictEqual(result.code, \"alert({bar:42});\");\n        });\n    });\n\n    describe(\"collapse_vars\", function() {\n        it(\"Should not produce invalid AST\", function() {\n            var code = [\n                \"function f(a) {\",\n                \"    a = x();\",\n                \"    return a;\",\n                \"}\",\n                \"f();\",\n            ].join(\"\\n\");\n            var ast = UglifyJS.minify(code, {\n                compress: false,\n                mangle: false,\n                output: {\n                    ast: true,\n                },\n            }).ast;\n            assert.strictEqual(ast.TYPE, \"Toplevel\");\n            assert.strictEqual(ast.body.length, 2);\n            assert.strictEqual(ast.body[0].TYPE, \"Defun\");\n            assert.strictEqual(ast.body[0].body.length, 2);\n            assert.strictEqual(ast.body[0].body[0].TYPE, \"SimpleStatement\");\n            var stat = ast.body[0].body[0];\n            UglifyJS.minify(ast, {\n                compress: {\n                    sequences: false,\n                },\n                mangle: false,\n            });\n            assert.ok(stat.body);\n            assert.strictEqual(stat.print_to_string(), \"a=x()\");\n        });\n    });\n\n    describe(\"module\", function() {\n        var code = [\n            \"console.log(function() {\",\n            \"    return typeof await;\",\n            \"}());\",\n        ].join(\"\\n\");\n        it(\"Should inline `await` variables\", function() {\n            var result = UglifyJS.minify(code, {\n                module: false,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, \"console.log(typeof await);\");\n            assert.strictEqual(run_code(code), \"undefined\\n\");\n            assert.strictEqual(run_code(result.code), \"undefined\\n\");\n        });\n        it(\"Should not inline `await` variables in ES modules\", function() {\n            var result = UglifyJS.minify(code, {\n                module: true,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, \"console.log((()=>typeof await)());\");\n            if (semver.satisfies(process.version, \">=8\")) {\n                assert.strictEqual(run_code(\"(async function(){\" + code + \"})();\"), \"undefined\\n\");\n                assert.strictEqual(run_code(\"(async function(){\" + result.code + \"})();\"), \"undefined\\n\");\n            }\n        });\n    });\n\n    describe(\"rename\", function() {\n        it(\"Should be repeatable\", function() {\n            var code = \"!function(x){return x(x)}(y);\";\n            for (var i = 0; i < 2; i++) {\n                assert.strictEqual(UglifyJS.minify(code, {\n                    compress: {\n                        toplevel: true,\n                    },\n                    rename: true,\n                }).code, \"var a;(a=y)(a);\");\n            }\n        });\n    });\n\n    describe(\"enclose\", function() {\n        var code = read(\"test/input/enclose/input.js\");\n        it(\"Should work with true\", function() {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                enclose: true,\n                mangle: false,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, '(function(){function enclose(){console.log(\"test enclose\")}enclose()})();');\n        });\n        it(\"Should work with arg\", function() {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                enclose: 'undefined',\n                mangle: false,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, '(function(undefined){function enclose(){console.log(\"test enclose\")}enclose()})();');\n        });\n        it(\"Should work with arg:value\", function() {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                enclose: 'window,undefined:window',\n                mangle: false,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, '(function(window,undefined){function enclose(){console.log(\"test enclose\")}enclose()})(window);');\n        });\n        it(\"Should work alongside wrap\", function() {\n            var result = UglifyJS.minify(code, {\n                compress: false,\n                enclose: 'window,undefined:window',\n                mangle: false,\n                wrap: 'exports',\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, '(function(exports){(function(window,undefined){function enclose(){console.log(\"test enclose\")}enclose()})(window)})(typeof exports==\"undefined\"?exports={}:exports);');\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/number-literal.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"Number literals\", function() {\n    it(\"Should allow legacy octal literals in non-strict mode\", function() {\n        [\n            \"'use strict'\\n.slice()\\n00\",\n            '\"use strict\"\\n.slice()\\nvar foo = 00',\n        ].forEach(function(input) {\n            UglifyJS.parse(input);\n        });\n    });\n    it(\"Should not allow legacy octal literals in strict mode\", function() {\n        var inputs = [\n            '\"use strict\";00;',\n            '\"use strict\"; var foo = 00;',\n        ];\n        var test = function(input) {\n            return function() {\n                UglifyJS.parse(input);\n            }\n        };\n        var error = function(e) {\n            return e instanceof UglifyJS.JS_Parse_Error\n                && e.message === \"Legacy octal literals are not allowed in strict mode\";\n        };\n        for (var i = 0; i < inputs.length; i++) {\n            assert.throws(test(inputs[i]), error, inputs[i]);\n        }\n    });\n    it(\"Should parse binary, hexadecimal, octal and underscore correctly\", function() {\n        [\n            \"42\",\n            \"4_2\",\n            \"052\",\n            \"0o52\",\n            \"0O52\",\n            \"0o5_2\",\n            \"0x2a\",\n            \"0X2A\",\n            \"0x2_a\",\n            \"0b101010\",\n            \"0B101010\",\n            \"0b101_010\",\n            \"0.0000000042e+10\",\n            \"0.0000000042E+10\",\n            \"0.0_000000042e+10\",\n            \"0.0000000042e+1_0\",\n            \"0.000_000_004_2e+1_0\",\n            \"0.000_000_004_2e+1_0-0B101_010+0x2_A-0o5_2+4_2\",\n        ].forEach(function(code) {\n            var result = UglifyJS.minify(code, {\n                expression: true,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, \"42\");\n        });\n    });\n    it(\"Should reject invalid use of underscore\", function() {\n        [\n            \"_42\",\n            \"_+42\",\n            \"+_42\",\n        ].forEach(function(code) {\n            var node = UglifyJS.parse(code, {\n                expression: true,\n            });\n            assert.ok(!node.is_constant(), code);\n            assert.ok(!(node instanceof UglifyJS.AST_Statement), code);\n        });\n        [\n            \"42_\",\n            \"4__2\",\n            \"0_52\",\n            \"05_2\",\n            \"0_o52\",\n            \"0o_52\",\n            \"0.0000000042_e10\",\n            \"0.0000000042e_10\",\n            \"0.0000000042e_+10\",\n            \"0.0000000042e+_10\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject invalid syntax under expression=true\", function() {\n        assert.throws(function() {\n            UglifyJS.parse(\"42.g\", {\n                expression: true,\n            });\n        }, function(e) {\n            return e instanceof UglifyJS.JS_Parse_Error;\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/operator.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../..\");\n\ndescribe(\"operator\", function() {\n    it(\"Should handle mixing of ++/+/--/- correctly\", function() {\n        function evaluate(exp) {\n            return new Function(\"var a=1,b=2,c=\" + exp + \";return{a:a,b:b,c:c}\")();\n        }\n\n        [ \"\", \"+\", \"-\" ].forEach(function(p) {\n            [ \"++a\", \"--a\", \"a\", \"a--\", \"a++\" ].forEach(function(a) {\n                [ \"+\", \"-\" ].forEach(function(o) {\n                    [ \"\", \"+\", \"-\" ].forEach(function(q) {\n                        [ \"++b\", \"--b\", \"b\", \"b--\", \"b++\" ].forEach(function(b) {\n                            var exp = [p, a, o, q, b].join(\" \");\n                            var orig = evaluate(exp);\n                            var uglify = evaluate(UglifyJS.parse(exp).print_to_string());\n                            assert.strictEqual(orig.a, uglify.a);\n                            assert.strictEqual(orig.b, uglify.b);\n                            assert.strictEqual(orig.c, uglify.c);\n                            var beautify = evaluate(UglifyJS.parse(exp).print_to_string({\n                                beautify: true\n                            }));\n                            assert.strictEqual(orig.a, beautify.a);\n                            assert.strictEqual(orig.b, beautify.b);\n                            assert.strictEqual(orig.c, beautify.c);\n                        });\n                    });\n                });\n            });\n        });\n    });\n    it(\"Should remove extraneous spaces\", function() {\n        [\n            [ \"++a + ++b\", \"++a+ ++b\" ],\n            [ \"++a + --b\", \"++a+--b\" ],\n            [ \"++a + b\", \"++a+b\" ],\n            [ \"++a + b--\", \"++a+b--\" ],\n            [ \"++a + b++\", \"++a+b++\" ],\n            [ \"++a + + ++b\", \"++a+ + ++b\" ],\n            [ \"++a + + --b\", \"++a+ +--b\" ],\n            [ \"++a + + b\", \"++a+ +b\" ],\n            [ \"++a + + b--\", \"++a+ +b--\" ],\n            [ \"++a + + b++\", \"++a+ +b++\" ],\n            [ \"++a + - ++b\", \"++a+-++b\" ],\n            [ \"++a + - --b\", \"++a+- --b\" ],\n            [ \"++a + - b\", \"++a+-b\" ],\n            [ \"++a + - b--\", \"++a+-b--\" ],\n            [ \"++a + - b++\", \"++a+-b++\" ],\n            [ \"++a - ++b\", \"++a-++b\" ],\n            [ \"++a - --b\", \"++a- --b\" ],\n            [ \"++a - b\", \"++a-b\" ],\n            [ \"++a - b--\", \"++a-b--\" ],\n            [ \"++a - b++\", \"++a-b++\" ],\n            [ \"++a - + ++b\", \"++a-+ ++b\" ],\n            [ \"++a - + --b\", \"++a-+--b\" ],\n            [ \"++a - + b\", \"++a-+b\" ],\n            [ \"++a - + b--\", \"++a-+b--\" ],\n            [ \"++a - + b++\", \"++a-+b++\" ],\n            [ \"++a - - ++b\", \"++a- -++b\" ],\n            [ \"++a - - --b\", \"++a- - --b\" ],\n            [ \"++a - - b\", \"++a- -b\" ],\n            [ \"++a - - b--\", \"++a- -b--\" ],\n            [ \"++a - - b++\", \"++a- -b++\" ],\n            [ \"--a + ++b\", \"--a+ ++b\" ],\n            [ \"--a + --b\", \"--a+--b\" ],\n            [ \"--a + b\", \"--a+b\" ],\n            [ \"--a + b--\", \"--a+b--\" ],\n            [ \"--a + b++\", \"--a+b++\" ],\n            [ \"--a + + ++b\", \"--a+ + ++b\" ],\n            [ \"--a + + --b\", \"--a+ +--b\" ],\n            [ \"--a + + b\", \"--a+ +b\" ],\n            [ \"--a + + b--\", \"--a+ +b--\" ],\n            [ \"--a + + b++\", \"--a+ +b++\" ],\n            [ \"--a + - ++b\", \"--a+-++b\" ],\n            [ \"--a + - --b\", \"--a+- --b\" ],\n            [ \"--a + - b\", \"--a+-b\" ],\n            [ \"--a + - b--\", \"--a+-b--\" ],\n            [ \"--a + - b++\", \"--a+-b++\" ],\n            [ \"--a - ++b\", \"--a-++b\" ],\n            [ \"--a - --b\", \"--a- --b\" ],\n            [ \"--a - b\", \"--a-b\" ],\n            [ \"--a - b--\", \"--a-b--\" ],\n            [ \"--a - b++\", \"--a-b++\" ],\n            [ \"--a - + ++b\", \"--a-+ ++b\" ],\n            [ \"--a - + --b\", \"--a-+--b\" ],\n            [ \"--a - + b\", \"--a-+b\" ],\n            [ \"--a - + b--\", \"--a-+b--\" ],\n            [ \"--a - + b++\", \"--a-+b++\" ],\n            [ \"--a - - ++b\", \"--a- -++b\" ],\n            [ \"--a - - --b\", \"--a- - --b\" ],\n            [ \"--a - - b\", \"--a- -b\" ],\n            [ \"--a - - b--\", \"--a- -b--\" ],\n            [ \"--a - - b++\", \"--a- -b++\" ],\n            [ \"a + ++b\", \"a+ ++b\" ],\n            [ \"a + --b\", \"a+--b\" ],\n            [ \"a + b\", \"a+b\" ],\n            [ \"a + b--\", \"a+b--\" ],\n            [ \"a + b++\", \"a+b++\" ],\n            [ \"a + + ++b\", \"a+ + ++b\" ],\n            [ \"a + + --b\", \"a+ +--b\" ],\n            [ \"a + + b\", \"a+ +b\" ],\n            [ \"a + + b--\", \"a+ +b--\" ],\n            [ \"a + + b++\", \"a+ +b++\" ],\n            [ \"a + - ++b\", \"a+-++b\" ],\n            [ \"a + - --b\", \"a+- --b\" ],\n            [ \"a + - b\", \"a+-b\" ],\n            [ \"a + - b--\", \"a+-b--\" ],\n            [ \"a + - b++\", \"a+-b++\" ],\n            [ \"a - ++b\", \"a-++b\" ],\n            [ \"a - --b\", \"a- --b\" ],\n            [ \"a - b\", \"a-b\" ],\n            [ \"a - b--\", \"a-b--\" ],\n            [ \"a - b++\", \"a-b++\" ],\n            [ \"a - + ++b\", \"a-+ ++b\" ],\n            [ \"a - + --b\", \"a-+--b\" ],\n            [ \"a - + b\", \"a-+b\" ],\n            [ \"a - + b--\", \"a-+b--\" ],\n            [ \"a - + b++\", \"a-+b++\" ],\n            [ \"a - - ++b\", \"a- -++b\" ],\n            [ \"a - - --b\", \"a- - --b\" ],\n            [ \"a - - b\", \"a- -b\" ],\n            [ \"a - - b--\", \"a- -b--\" ],\n            [ \"a - - b++\", \"a- -b++\" ],\n            [ \"a-- + ++b\", \"a--+ ++b\" ],\n            [ \"a-- + --b\", \"a--+--b\" ],\n            [ \"a-- + b\", \"a--+b\" ],\n            [ \"a-- + b--\", \"a--+b--\" ],\n            [ \"a-- + b++\", \"a--+b++\" ],\n            [ \"a-- + + ++b\", \"a--+ + ++b\" ],\n            [ \"a-- + + --b\", \"a--+ +--b\" ],\n            [ \"a-- + + b\", \"a--+ +b\" ],\n            [ \"a-- + + b--\", \"a--+ +b--\" ],\n            [ \"a-- + + b++\", \"a--+ +b++\" ],\n            [ \"a-- + - ++b\", \"a--+-++b\" ],\n            [ \"a-- + - --b\", \"a--+- --b\" ],\n            [ \"a-- + - b\", \"a--+-b\" ],\n            [ \"a-- + - b--\", \"a--+-b--\" ],\n            [ \"a-- + - b++\", \"a--+-b++\" ],\n            [ \"a-- - ++b\", \"a---++b\" ],\n            [ \"a-- - --b\", \"a--- --b\" ],\n            [ \"a-- - b\", \"a---b\" ],\n            [ \"a-- - b--\", \"a---b--\" ],\n            [ \"a-- - b++\", \"a---b++\" ],\n            [ \"a-- - + ++b\", \"a---+ ++b\" ],\n            [ \"a-- - + --b\", \"a---+--b\" ],\n            [ \"a-- - + b\", \"a---+b\" ],\n            [ \"a-- - + b--\", \"a---+b--\" ],\n            [ \"a-- - + b++\", \"a---+b++\" ],\n            [ \"a-- - - ++b\", \"a--- -++b\" ],\n            [ \"a-- - - --b\", \"a--- - --b\" ],\n            [ \"a-- - - b\", \"a--- -b\" ],\n            [ \"a-- - - b--\", \"a--- -b--\" ],\n            [ \"a-- - - b++\", \"a--- -b++\" ],\n            [ \"a++ + ++b\", \"a+++ ++b\" ],\n            [ \"a++ + --b\", \"a+++--b\" ],\n            [ \"a++ + b\", \"a+++b\" ],\n            [ \"a++ + b--\", \"a+++b--\" ],\n            [ \"a++ + b++\", \"a+++b++\" ],\n            [ \"a++ + + ++b\", \"a+++ + ++b\" ],\n            [ \"a++ + + --b\", \"a+++ +--b\" ],\n            [ \"a++ + + b\", \"a+++ +b\" ],\n            [ \"a++ + + b--\", \"a+++ +b--\" ],\n            [ \"a++ + + b++\", \"a+++ +b++\" ],\n            [ \"a++ + - ++b\", \"a+++-++b\" ],\n            [ \"a++ + - --b\", \"a+++- --b\" ],\n            [ \"a++ + - b\", \"a+++-b\" ],\n            [ \"a++ + - b--\", \"a+++-b--\" ],\n            [ \"a++ + - b++\", \"a+++-b++\" ],\n            [ \"a++ - ++b\", \"a++-++b\" ],\n            [ \"a++ - --b\", \"a++- --b\" ],\n            [ \"a++ - b\", \"a++-b\" ],\n            [ \"a++ - b--\", \"a++-b--\" ],\n            [ \"a++ - b++\", \"a++-b++\" ],\n            [ \"a++ - + ++b\", \"a++-+ ++b\" ],\n            [ \"a++ - + --b\", \"a++-+--b\" ],\n            [ \"a++ - + b\", \"a++-+b\" ],\n            [ \"a++ - + b--\", \"a++-+b--\" ],\n            [ \"a++ - + b++\", \"a++-+b++\" ],\n            [ \"a++ - - ++b\", \"a++- -++b\" ],\n            [ \"a++ - - --b\", \"a++- - --b\" ],\n            [ \"a++ - - b\", \"a++- -b\" ],\n            [ \"a++ - - b--\", \"a++- -b--\" ],\n            [ \"a++ - - b++\", \"a++- -b++\" ],\n            [ \"+ ++a + ++b\", \"+ ++a+ ++b\" ],\n            [ \"+ ++a + --b\", \"+ ++a+--b\" ],\n            [ \"+ ++a + b\", \"+ ++a+b\" ],\n            [ \"+ ++a + b--\", \"+ ++a+b--\" ],\n            [ \"+ ++a + b++\", \"+ ++a+b++\" ],\n            [ \"+ ++a + + ++b\", \"+ ++a+ + ++b\" ],\n            [ \"+ ++a + + --b\", \"+ ++a+ +--b\" ],\n            [ \"+ ++a + + b\", \"+ ++a+ +b\" ],\n            [ \"+ ++a + + b--\", \"+ ++a+ +b--\" ],\n            [ \"+ ++a + + b++\", \"+ ++a+ +b++\" ],\n            [ \"+ ++a + - ++b\", \"+ ++a+-++b\" ],\n            [ \"+ ++a + - --b\", \"+ ++a+- --b\" ],\n            [ \"+ ++a + - b\", \"+ ++a+-b\" ],\n            [ \"+ ++a + - b--\", \"+ ++a+-b--\" ],\n            [ \"+ ++a + - b++\", \"+ ++a+-b++\" ],\n            [ \"+ ++a - ++b\", \"+ ++a-++b\" ],\n            [ \"+ ++a - --b\", \"+ ++a- --b\" ],\n            [ \"+ ++a - b\", \"+ ++a-b\" ],\n            [ \"+ ++a - b--\", \"+ ++a-b--\" ],\n            [ \"+ ++a - b++\", \"+ ++a-b++\" ],\n            [ \"+ ++a - + ++b\", \"+ ++a-+ ++b\" ],\n            [ \"+ ++a - + --b\", \"+ ++a-+--b\" ],\n            [ \"+ ++a - + b\", \"+ ++a-+b\" ],\n            [ \"+ ++a - + b--\", \"+ ++a-+b--\" ],\n            [ \"+ ++a - + b++\", \"+ ++a-+b++\" ],\n            [ \"+ ++a - - ++b\", \"+ ++a- -++b\" ],\n            [ \"+ ++a - - --b\", \"+ ++a- - --b\" ],\n            [ \"+ ++a - - b\", \"+ ++a- -b\" ],\n            [ \"+ ++a - - b--\", \"+ ++a- -b--\" ],\n            [ \"+ ++a - - b++\", \"+ ++a- -b++\" ],\n            [ \"+ --a + ++b\", \"+--a+ ++b\" ],\n            [ \"+ --a + --b\", \"+--a+--b\" ],\n            [ \"+ --a + b\", \"+--a+b\" ],\n            [ \"+ --a + b--\", \"+--a+b--\" ],\n            [ \"+ --a + b++\", \"+--a+b++\" ],\n            [ \"+ --a + + ++b\", \"+--a+ + ++b\" ],\n            [ \"+ --a + + --b\", \"+--a+ +--b\" ],\n            [ \"+ --a + + b\", \"+--a+ +b\" ],\n            [ \"+ --a + + b--\", \"+--a+ +b--\" ],\n            [ \"+ --a + + b++\", \"+--a+ +b++\" ],\n            [ \"+ --a + - ++b\", \"+--a+-++b\" ],\n            [ \"+ --a + - --b\", \"+--a+- --b\" ],\n            [ \"+ --a + - b\", \"+--a+-b\" ],\n            [ \"+ --a + - b--\", \"+--a+-b--\" ],\n            [ \"+ --a + - b++\", \"+--a+-b++\" ],\n            [ \"+ --a - ++b\", \"+--a-++b\" ],\n            [ \"+ --a - --b\", \"+--a- --b\" ],\n            [ \"+ --a - b\", \"+--a-b\" ],\n            [ \"+ --a - b--\", \"+--a-b--\" ],\n            [ \"+ --a - b++\", \"+--a-b++\" ],\n            [ \"+ --a - + ++b\", \"+--a-+ ++b\" ],\n            [ \"+ --a - + --b\", \"+--a-+--b\" ],\n            [ \"+ --a - + b\", \"+--a-+b\" ],\n            [ \"+ --a - + b--\", \"+--a-+b--\" ],\n            [ \"+ --a - + b++\", \"+--a-+b++\" ],\n            [ \"+ --a - - ++b\", \"+--a- -++b\" ],\n            [ \"+ --a - - --b\", \"+--a- - --b\" ],\n            [ \"+ --a - - b\", \"+--a- -b\" ],\n            [ \"+ --a - - b--\", \"+--a- -b--\" ],\n            [ \"+ --a - - b++\", \"+--a- -b++\" ],\n            [ \"+ a + ++b\", \"+a+ ++b\" ],\n            [ \"+ a + --b\", \"+a+--b\" ],\n            [ \"+ a + b\", \"+a+b\" ],\n            [ \"+ a + b--\", \"+a+b--\" ],\n            [ \"+ a + b++\", \"+a+b++\" ],\n            [ \"+ a + + ++b\", \"+a+ + ++b\" ],\n            [ \"+ a + + --b\", \"+a+ +--b\" ],\n            [ \"+ a + + b\", \"+a+ +b\" ],\n            [ \"+ a + + b--\", \"+a+ +b--\" ],\n            [ \"+ a + + b++\", \"+a+ +b++\" ],\n            [ \"+ a + - ++b\", \"+a+-++b\" ],\n            [ \"+ a + - --b\", \"+a+- --b\" ],\n            [ \"+ a + - b\", \"+a+-b\" ],\n            [ \"+ a + - b--\", \"+a+-b--\" ],\n            [ \"+ a + - b++\", \"+a+-b++\" ],\n            [ \"+ a - ++b\", \"+a-++b\" ],\n            [ \"+ a - --b\", \"+a- --b\" ],\n            [ \"+ a - b\", \"+a-b\" ],\n            [ \"+ a - b--\", \"+a-b--\" ],\n            [ \"+ a - b++\", \"+a-b++\" ],\n            [ \"+ a - + ++b\", \"+a-+ ++b\" ],\n            [ \"+ a - + --b\", \"+a-+--b\" ],\n            [ \"+ a - + b\", \"+a-+b\" ],\n            [ \"+ a - + b--\", \"+a-+b--\" ],\n            [ \"+ a - + b++\", \"+a-+b++\" ],\n            [ \"+ a - - ++b\", \"+a- -++b\" ],\n            [ \"+ a - - --b\", \"+a- - --b\" ],\n            [ \"+ a - - b\", \"+a- -b\" ],\n            [ \"+ a - - b--\", \"+a- -b--\" ],\n            [ \"+ a - - b++\", \"+a- -b++\" ],\n            [ \"+ a-- + ++b\", \"+a--+ ++b\" ],\n            [ \"+ a-- + --b\", \"+a--+--b\" ],\n            [ \"+ a-- + b\", \"+a--+b\" ],\n            [ \"+ a-- + b--\", \"+a--+b--\" ],\n            [ \"+ a-- + b++\", \"+a--+b++\" ],\n            [ \"+ a-- + + ++b\", \"+a--+ + ++b\" ],\n            [ \"+ a-- + + --b\", \"+a--+ +--b\" ],\n            [ \"+ a-- + + b\", \"+a--+ +b\" ],\n            [ \"+ a-- + + b--\", \"+a--+ +b--\" ],\n            [ \"+ a-- + + b++\", \"+a--+ +b++\" ],\n            [ \"+ a-- + - ++b\", \"+a--+-++b\" ],\n            [ \"+ a-- + - --b\", \"+a--+- --b\" ],\n            [ \"+ a-- + - b\", \"+a--+-b\" ],\n            [ \"+ a-- + - b--\", \"+a--+-b--\" ],\n            [ \"+ a-- + - b++\", \"+a--+-b++\" ],\n            [ \"+ a-- - ++b\", \"+a---++b\" ],\n            [ \"+ a-- - --b\", \"+a--- --b\" ],\n            [ \"+ a-- - b\", \"+a---b\" ],\n            [ \"+ a-- - b--\", \"+a---b--\" ],\n            [ \"+ a-- - b++\", \"+a---b++\" ],\n            [ \"+ a-- - + ++b\", \"+a---+ ++b\" ],\n            [ \"+ a-- - + --b\", \"+a---+--b\" ],\n            [ \"+ a-- - + b\", \"+a---+b\" ],\n            [ \"+ a-- - + b--\", \"+a---+b--\" ],\n            [ \"+ a-- - + b++\", \"+a---+b++\" ],\n            [ \"+ a-- - - ++b\", \"+a--- -++b\" ],\n            [ \"+ a-- - - --b\", \"+a--- - --b\" ],\n            [ \"+ a-- - - b\", \"+a--- -b\" ],\n            [ \"+ a-- - - b--\", \"+a--- -b--\" ],\n            [ \"+ a-- - - b++\", \"+a--- -b++\" ],\n            [ \"+ a++ + ++b\", \"+a+++ ++b\" ],\n            [ \"+ a++ + --b\", \"+a+++--b\" ],\n            [ \"+ a++ + b\", \"+a+++b\" ],\n            [ \"+ a++ + b--\", \"+a+++b--\" ],\n            [ \"+ a++ + b++\", \"+a+++b++\" ],\n            [ \"+ a++ + + ++b\", \"+a+++ + ++b\" ],\n            [ \"+ a++ + + --b\", \"+a+++ +--b\" ],\n            [ \"+ a++ + + b\", \"+a+++ +b\" ],\n            [ \"+ a++ + + b--\", \"+a+++ +b--\" ],\n            [ \"+ a++ + + b++\", \"+a+++ +b++\" ],\n            [ \"+ a++ + - ++b\", \"+a+++-++b\" ],\n            [ \"+ a++ + - --b\", \"+a+++- --b\" ],\n            [ \"+ a++ + - b\", \"+a+++-b\" ],\n            [ \"+ a++ + - b--\", \"+a+++-b--\" ],\n            [ \"+ a++ + - b++\", \"+a+++-b++\" ],\n            [ \"+ a++ - ++b\", \"+a++-++b\" ],\n            [ \"+ a++ - --b\", \"+a++- --b\" ],\n            [ \"+ a++ - b\", \"+a++-b\" ],\n            [ \"+ a++ - b--\", \"+a++-b--\" ],\n            [ \"+ a++ - b++\", \"+a++-b++\" ],\n            [ \"+ a++ - + ++b\", \"+a++-+ ++b\" ],\n            [ \"+ a++ - + --b\", \"+a++-+--b\" ],\n            [ \"+ a++ - + b\", \"+a++-+b\" ],\n            [ \"+ a++ - + b--\", \"+a++-+b--\" ],\n            [ \"+ a++ - + b++\", \"+a++-+b++\" ],\n            [ \"+ a++ - - ++b\", \"+a++- -++b\" ],\n            [ \"+ a++ - - --b\", \"+a++- - --b\" ],\n            [ \"+ a++ - - b\", \"+a++- -b\" ],\n            [ \"+ a++ - - b--\", \"+a++- -b--\" ],\n            [ \"+ a++ - - b++\", \"+a++- -b++\" ],\n            [ \"- ++a + ++b\", \"-++a+ ++b\" ],\n            [ \"- ++a + --b\", \"-++a+--b\" ],\n            [ \"- ++a + b\", \"-++a+b\" ],\n            [ \"- ++a + b--\", \"-++a+b--\" ],\n            [ \"- ++a + b++\", \"-++a+b++\" ],\n            [ \"- ++a + + ++b\", \"-++a+ + ++b\" ],\n            [ \"- ++a + + --b\", \"-++a+ +--b\" ],\n            [ \"- ++a + + b\", \"-++a+ +b\" ],\n            [ \"- ++a + + b--\", \"-++a+ +b--\" ],\n            [ \"- ++a + + b++\", \"-++a+ +b++\" ],\n            [ \"- ++a + - ++b\", \"-++a+-++b\" ],\n            [ \"- ++a + - --b\", \"-++a+- --b\" ],\n            [ \"- ++a + - b\", \"-++a+-b\" ],\n            [ \"- ++a + - b--\", \"-++a+-b--\" ],\n            [ \"- ++a + - b++\", \"-++a+-b++\" ],\n            [ \"- ++a - ++b\", \"-++a-++b\" ],\n            [ \"- ++a - --b\", \"-++a- --b\" ],\n            [ \"- ++a - b\", \"-++a-b\" ],\n            [ \"- ++a - b--\", \"-++a-b--\" ],\n            [ \"- ++a - b++\", \"-++a-b++\" ],\n            [ \"- ++a - + ++b\", \"-++a-+ ++b\" ],\n            [ \"- ++a - + --b\", \"-++a-+--b\" ],\n            [ \"- ++a - + b\", \"-++a-+b\" ],\n            [ \"- ++a - + b--\", \"-++a-+b--\" ],\n            [ \"- ++a - + b++\", \"-++a-+b++\" ],\n            [ \"- ++a - - ++b\", \"-++a- -++b\" ],\n            [ \"- ++a - - --b\", \"-++a- - --b\" ],\n            [ \"- ++a - - b\", \"-++a- -b\" ],\n            [ \"- ++a - - b--\", \"-++a- -b--\" ],\n            [ \"- ++a - - b++\", \"-++a- -b++\" ],\n            [ \"- --a + ++b\", \"- --a+ ++b\" ],\n            [ \"- --a + --b\", \"- --a+--b\" ],\n            [ \"- --a + b\", \"- --a+b\" ],\n            [ \"- --a + b--\", \"- --a+b--\" ],\n            [ \"- --a + b++\", \"- --a+b++\" ],\n            [ \"- --a + + ++b\", \"- --a+ + ++b\" ],\n            [ \"- --a + + --b\", \"- --a+ +--b\" ],\n            [ \"- --a + + b\", \"- --a+ +b\" ],\n            [ \"- --a + + b--\", \"- --a+ +b--\" ],\n            [ \"- --a + + b++\", \"- --a+ +b++\" ],\n            [ \"- --a + - ++b\", \"- --a+-++b\" ],\n            [ \"- --a + - --b\", \"- --a+- --b\" ],\n            [ \"- --a + - b\", \"- --a+-b\" ],\n            [ \"- --a + - b--\", \"- --a+-b--\" ],\n            [ \"- --a + - b++\", \"- --a+-b++\" ],\n            [ \"- --a - ++b\", \"- --a-++b\" ],\n            [ \"- --a - --b\", \"- --a- --b\" ],\n            [ \"- --a - b\", \"- --a-b\" ],\n            [ \"- --a - b--\", \"- --a-b--\" ],\n            [ \"- --a - b++\", \"- --a-b++\" ],\n            [ \"- --a - + ++b\", \"- --a-+ ++b\" ],\n            [ \"- --a - + --b\", \"- --a-+--b\" ],\n            [ \"- --a - + b\", \"- --a-+b\" ],\n            [ \"- --a - + b--\", \"- --a-+b--\" ],\n            [ \"- --a - + b++\", \"- --a-+b++\" ],\n            [ \"- --a - - ++b\", \"- --a- -++b\" ],\n            [ \"- --a - - --b\", \"- --a- - --b\" ],\n            [ \"- --a - - b\", \"- --a- -b\" ],\n            [ \"- --a - - b--\", \"- --a- -b--\" ],\n            [ \"- --a - - b++\", \"- --a- -b++\" ],\n            [ \"- a + ++b\", \"-a+ ++b\" ],\n            [ \"- a + --b\", \"-a+--b\" ],\n            [ \"- a + b\", \"-a+b\" ],\n            [ \"- a + b--\", \"-a+b--\" ],\n            [ \"- a + b++\", \"-a+b++\" ],\n            [ \"- a + + ++b\", \"-a+ + ++b\" ],\n            [ \"- a + + --b\", \"-a+ +--b\" ],\n            [ \"- a + + b\", \"-a+ +b\" ],\n            [ \"- a + + b--\", \"-a+ +b--\" ],\n            [ \"- a + + b++\", \"-a+ +b++\" ],\n            [ \"- a + - ++b\", \"-a+-++b\" ],\n            [ \"- a + - --b\", \"-a+- --b\" ],\n            [ \"- a + - b\", \"-a+-b\" ],\n            [ \"- a + - b--\", \"-a+-b--\" ],\n            [ \"- a + - b++\", \"-a+-b++\" ],\n            [ \"- a - ++b\", \"-a-++b\" ],\n            [ \"- a - --b\", \"-a- --b\" ],\n            [ \"- a - b\", \"-a-b\" ],\n            [ \"- a - b--\", \"-a-b--\" ],\n            [ \"- a - b++\", \"-a-b++\" ],\n            [ \"- a - + ++b\", \"-a-+ ++b\" ],\n            [ \"- a - + --b\", \"-a-+--b\" ],\n            [ \"- a - + b\", \"-a-+b\" ],\n            [ \"- a - + b--\", \"-a-+b--\" ],\n            [ \"- a - + b++\", \"-a-+b++\" ],\n            [ \"- a - - ++b\", \"-a- -++b\" ],\n            [ \"- a - - --b\", \"-a- - --b\" ],\n            [ \"- a - - b\", \"-a- -b\" ],\n            [ \"- a - - b--\", \"-a- -b--\" ],\n            [ \"- a - - b++\", \"-a- -b++\" ],\n            [ \"- a-- + ++b\", \"-a--+ ++b\" ],\n            [ \"- a-- + --b\", \"-a--+--b\" ],\n            [ \"- a-- + b\", \"-a--+b\" ],\n            [ \"- a-- + b--\", \"-a--+b--\" ],\n            [ \"- a-- + b++\", \"-a--+b++\" ],\n            [ \"- a-- + + ++b\", \"-a--+ + ++b\" ],\n            [ \"- a-- + + --b\", \"-a--+ +--b\" ],\n            [ \"- a-- + + b\", \"-a--+ +b\" ],\n            [ \"- a-- + + b--\", \"-a--+ +b--\" ],\n            [ \"- a-- + + b++\", \"-a--+ +b++\" ],\n            [ \"- a-- + - ++b\", \"-a--+-++b\" ],\n            [ \"- a-- + - --b\", \"-a--+- --b\" ],\n            [ \"- a-- + - b\", \"-a--+-b\" ],\n            [ \"- a-- + - b--\", \"-a--+-b--\" ],\n            [ \"- a-- + - b++\", \"-a--+-b++\" ],\n            [ \"- a-- - ++b\", \"-a---++b\" ],\n            [ \"- a-- - --b\", \"-a--- --b\" ],\n            [ \"- a-- - b\", \"-a---b\" ],\n            [ \"- a-- - b--\", \"-a---b--\" ],\n            [ \"- a-- - b++\", \"-a---b++\" ],\n            [ \"- a-- - + ++b\", \"-a---+ ++b\" ],\n            [ \"- a-- - + --b\", \"-a---+--b\" ],\n            [ \"- a-- - + b\", \"-a---+b\" ],\n            [ \"- a-- - + b--\", \"-a---+b--\" ],\n            [ \"- a-- - + b++\", \"-a---+b++\" ],\n            [ \"- a-- - - ++b\", \"-a--- -++b\" ],\n            [ \"- a-- - - --b\", \"-a--- - --b\" ],\n            [ \"- a-- - - b\", \"-a--- -b\" ],\n            [ \"- a-- - - b--\", \"-a--- -b--\" ],\n            [ \"- a-- - - b++\", \"-a--- -b++\" ],\n            [ \"- a++ + ++b\", \"-a+++ ++b\" ],\n            [ \"- a++ + --b\", \"-a+++--b\" ],\n            [ \"- a++ + b\", \"-a+++b\" ],\n            [ \"- a++ + b--\", \"-a+++b--\" ],\n            [ \"- a++ + b++\", \"-a+++b++\" ],\n            [ \"- a++ + + ++b\", \"-a+++ + ++b\" ],\n            [ \"- a++ + + --b\", \"-a+++ +--b\" ],\n            [ \"- a++ + + b\", \"-a+++ +b\" ],\n            [ \"- a++ + + b--\", \"-a+++ +b--\" ],\n            [ \"- a++ + + b++\", \"-a+++ +b++\" ],\n            [ \"- a++ + - ++b\", \"-a+++-++b\" ],\n            [ \"- a++ + - --b\", \"-a+++- --b\" ],\n            [ \"- a++ + - b\", \"-a+++-b\" ],\n            [ \"- a++ + - b--\", \"-a+++-b--\" ],\n            [ \"- a++ + - b++\", \"-a+++-b++\" ],\n            [ \"- a++ - ++b\", \"-a++-++b\" ],\n            [ \"- a++ - --b\", \"-a++- --b\" ],\n            [ \"- a++ - b\", \"-a++-b\" ],\n            [ \"- a++ - b--\", \"-a++-b--\" ],\n            [ \"- a++ - b++\", \"-a++-b++\" ],\n            [ \"- a++ - + ++b\", \"-a++-+ ++b\" ],\n            [ \"- a++ - + --b\", \"-a++-+--b\" ],\n            [ \"- a++ - + b\", \"-a++-+b\" ],\n            [ \"- a++ - + b--\", \"-a++-+b--\" ],\n            [ \"- a++ - + b++\", \"-a++-+b++\" ],\n            [ \"- a++ - - ++b\", \"-a++- -++b\" ],\n            [ \"- a++ - - --b\", \"-a++- - --b\" ],\n            [ \"- a++ - - b\", \"-a++- -b\" ],\n            [ \"- a++ - - b--\", \"-a++- -b--\" ],\n            [ \"- a++ - - b++\", \"-a++- -b++\" ],\n        ].forEach(function(exp) {\n            assert.strictEqual(UglifyJS.parse(exp[0]).print_to_string(), exp[1] + \";\");\n        });\n    });\n    it(\"Should preserve space between /regex/ and `in`\", function() {\n        [\n            \"/regex/ in {}\",\n            \"/regex/g in {}\",\n            \"0 + /regex/ in {}\",\n            \"0 + /regex/g in {}\",\n        ].forEach(function(exp) {\n            var code = UglifyJS.parse(exp).print_to_string();\n            try {\n                assert.strictEqual(UglifyJS.parse(code).print_to_string(), code);\n            } catch (ex) {\n                assert.fail(\"Failed to reparse: \" + exp + \"\\n\" + ex);\n            }\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/parentheses.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../..\");\n\ndescribe(\"parentheses\", function() {\n    it(\"Should add trailing parentheses for new expressions with zero arguments in beautify mode\", function() {\n        var tests = [\n            \"new x(1);\",\n            \"new x;\",\n            \"new new x;\",\n            \"new (function(foo){this.foo=foo;})(1);\",\n            \"new (function(foo){this.foo=foo;})();\",\n            \"new (function test(foo){this.foo=foo;})(1);\",\n            \"new (function test(foo){this.foo=foo;})();\",\n            \"new true;\",\n            \"new (0);\",\n            \"new (!0);\",\n            \"new (bar = function(foo) {this.foo=foo;})(123);\",\n            \"new (bar = function(foo) {this.foo=foo;})();\"\n        ];\n        var expected = [\n            \"new x(1);\",\n            \"new x();\",\n            \"new new x()();\",\n            \"new function(foo) {\\n    this.foo = foo;\\n}(1);\",\n            \"new function(foo) {\\n    this.foo = foo;\\n}();\",\n            \"new function test(foo) {\\n    this.foo = foo;\\n}(1);\",\n            \"new function test(foo) {\\n    this.foo = foo;\\n}();\",\n            \"new true();\",\n            \"new 0();\",\n            \"new (!0)();\",\n            \"new (bar = function(foo) {\\n    this.foo = foo;\\n})(123);\",\n            \"new (bar = function(foo) {\\n    this.foo = foo;\\n})();\"\n        ];\n        for (var i = 0; i < tests.length; i++) {\n            assert.strictEqual(\n                UglifyJS.minify(tests[i], {\n                    output: {beautify: true},\n                    compress: false,\n                    mangle: false\n                }).code,\n                expected[i]\n            );\n        }\n    });\n\n    it(\"Should not add trailing parentheses for new expressions with zero arguments in non-beautify mode\", function() {\n        var tests = [\n            \"new x(1);\",\n            \"new x;\",\n            \"new new x;\",\n            \"new (function(foo){this.foo=foo;})(1);\",\n            \"new (function(foo){this.foo=foo;})();\",\n            \"new (function test(foo){this.foo=foo;})(1);\",\n            \"new (function test(foo){this.foo=foo;})();\",\n            \"new true;\",\n            \"new (0);\",\n            \"new (!0);\",\n            \"new (bar = function(foo) {this.foo=foo;})(123);\",\n            \"new (bar = function(foo) {this.foo=foo;})();\"\n        ];\n        var expected = [\n            \"new x(1);\",\n            \"new x;\",\n            \"new(new x);\",\n            \"new function(foo){this.foo=foo}(1);\",\n            \"new function(foo){this.foo=foo};\",\n            \"new function test(foo){this.foo=foo}(1);\",\n            \"new function test(foo){this.foo=foo};\",\n            \"new true;\",\n            \"new 0;\",\n            \"new(!0);\",\n            \"new(bar=function(foo){this.foo=foo})(123);\",\n            \"new(bar=function(foo){this.foo=foo});\"\n        ];\n        for (var i = 0; i < tests.length; i++) {\n            assert.strictEqual(\n                UglifyJS.minify(tests[i], {\n                    output: {beautify: false},\n                    compress: false,\n                    mangle: false\n                }).code,\n                expected[i]\n            );\n        }\n    });\n\n    it(\"Should compress leading parentheses with reasonable performance\", function() {\n        this.timeout(30000);\n        var code = [\n            \"({}?0:1)&&x();\",\n            \"(function(){}).name;\",\n        ];\n        for (var i = 16; --i >= 0;) {\n            code = code.concat(code);\n        }\n        code = code.join(\"\");\n        var result = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        // Dismal performance for `assert.strictEqual()` in Node.js 6\n        assert.ok(result.code === code);\n    });\n});\n"
  },
  {
    "path": "test/mocha/reduce.js",
    "content": "var assert = require(\"assert\");\nvar fs = require(\"fs\");\nvar reduce_test = require(\"../reduce\");\nvar semver = require(\"semver\");\n\nfunction read(path) {\n    return fs.readFileSync(path, \"utf8\");\n}\n\ndescribe(\"test/reduce.js\", function() {\n    this.timeout(60000);\n    it(\"Should reduce test case\", function() {\n        var result = reduce_test(read(\"test/input/reduce/unsafe_math.js\"), {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        }, {\n            verbose: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, read(\"test/input/reduce/unsafe_math.reduced.js\"));\n    });\n    it(\"Should eliminate unreferenced labels\", function() {\n        var result = reduce_test(read(\"test/input/reduce/label.js\"), {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        }, {\n            verbose: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, read(\"test/input/reduce/label.reduced.js\"));\n    });\n    it(\"Should retain setter arguments\", function() {\n        var result = reduce_test(read(\"test/input/reduce/setter.js\"), {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        }, {\n            verbose: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, read(\"test/input/reduce/setter.reduced.js\"));\n    });\n    it(\"Should handle test cases with --toplevel\", function() {\n        var result = reduce_test([\n            \"var Infinity = 42;\",\n            \"console.log(Infinity);\",\n        ].join(\"\\n\"), {\n            toplevel: true,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"toplevel\": true',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should handle test cases with --compress toplevel\", function() {\n        var result = reduce_test([\n            \"var NaN = 42;\",\n            \"console.log(NaN);\",\n        ].join(\"\\n\"), {\n            compress: {\n                toplevel: true,\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"compress\": {',\n            '//     \"toplevel\": true',\n            \"//   }\",\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should handle test cases with --mangle toplevel\", function() {\n        var result = reduce_test([\n            \"var undefined = 42;\",\n            \"console.log(undefined);\",\n        ].join(\"\\n\"), {\n            mangle: {\n                toplevel: true,\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"mangle\": {',\n            '//     \"toplevel\": true',\n            \"//   }\",\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should handle test result of NaN\", function() {\n        var result = reduce_test(\"throw 0 / 0;\");\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {}\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should print correct output for irreducible test case\", function() {\n        var result = reduce_test([\n            \"console.log(1 + .1 + .1);\",\n        ].join(\"\\n\"), {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// (beautified)\",\n            \"console.log(1 + .1 + .1);\",\n            \"// output: 1.2000000000000002\",\n            \"// \",\n            \"// minify: 1.2\",\n            \"// \",\n            \"// options: {\",\n            '//   \"compress\": {',\n            '//     \"unsafe_math\": true',\n            \"//   },\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should fail when invalid option is supplied\", function() {\n        var result = reduce_test(\"\", {\n            compress: {\n                unsafe_regex: true,\n            },\n        });\n        var err = result.error;\n        assert.ok(err instanceof Error);\n        assert.strictEqual(err.stack.split(/\\n/)[0], \"DefaultsError: `unsafe_regex` is not a supported option\");\n    });\n    it(\"Should report on test case with invalid syntax\", function() {\n        var result = reduce_test(\"var 0 = 1;\");\n        var err = result.error;\n        assert.ok(err instanceof Error);\n        assert.strictEqual(err.stack.split(/\\n/)[0], \"SyntaxError: Name expected\");\n    });\n    it(\"Should format multi-line output correctly\", function() {\n        var code = [\n            \"var a = 0;\",\n            \"\",\n            \"for (var b in [ 1, 2, 3 ]) {\",\n            \"    a = +a + 1 - .2;\",\n            \"    console.log(a);\",\n            \"}\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// (beautified)\",\n            code,\n            \"// output: 0.8\",\n            \"// 1.6\",\n            \"// 2.4\",\n            \"// \",\n            \"// minify: 0.8\",\n            \"// 1.6\",\n            \"// 2.4000000000000004\",\n            \"// \",\n            \"// options: {\",\n            '//   \"compress\": {',\n            '//     \"unsafe_math\": true',\n            \"//   },\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should reduce `for (const ... in ...)` without invalid intermediate AST\", function() {\n        if (semver.satisfies(process.version, \"<4\")) return;\n        var code = [\n            \"var a = 0;\",\n            \"\",\n            \"for (const b in [ 1, 2, 3 ]) {\",\n            \"    a = +a + 1 - .2;\",\n            \"    console.log(a);\",\n            \"}\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            compress: {\n                unsafe_math: true,\n            },\n        });\n        if (result.error) throw result.error;\n        assert.deepEqual(result.warnings, []);\n    });\n    it(\"Should reduce infinite loops with reasonable performance\", function() {\n        if (semver.satisfies(process.version, \"<=0.10\")) return;\n        this.timeout(120000);\n        var result = reduce_test(\"while (/9/.test(1 - .8));\", {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code.replace(/ timed out after [0-9]+ms/, \" timed out.\"), [\n            \"// (beautified)\",\n            \"while (/9/.test(1 - .8)) {}\",\n            \"// output: Error: Script execution timed out.\",\n            \"// minify: \",\n            \"// options: {\",\n            '//   \"compress\": {',\n            '//     \"unsafe_math\": true',\n            \"//   },\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should ignore difference in Error.message\", function() {\n        var result = reduce_test(\"null[function() {\\n}];\", {\n            module: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, (semver.satisfies(process.version, \"<=0.10\") ? [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"module\": false',\n            \"// }\",\n        ] : [\n            \"// No differences except in error message\",\n            \"// minify options: {\",\n            '//   \"module\": false',\n            \"// }\",\n        ]).join(\"\\n\"));\n    });\n    it(\"Should report trailing whitespace difference in stringified format\", function() {\n        var code = [\n            \"[].forEach.call((1 - .8).toString(), function() {\",\n            \"    console.log();\",\n            \"});\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n            module: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// (beautified)\",\n            code,\n            \"// (stringified)\",\n            '// output: \"\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\\\\n\"',\n            '// minify: \"\\\\n\\\\n\\\\n\"',\n            \"// options: {\",\n            '//   \"compress\": {',\n            '//     \"unsafe_math\": true',\n            '//   },',\n            '//   \"mangle\": false,',\n            '//   \"module\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should reduce test case which differs only in Error.message\", function() {\n        var code = [\n            \"var a=0;\",\n            \"try{\",\n            \"null[function(){}]\",\n            \"}catch(e){\",\n            \"for(var i in e.toString())\",\n            \"a++,console.log()\",\n            \"}\",\n            \"console.log(a);\",\n        ].join(\"\");\n        var result = reduce_test(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                beautify: true,\n            },\n        });\n        if (result.error) throw result.error;\n        assert.deepEqual(result.warnings, []);\n        if (semver.satisfies(process.version, \"<=0.10\")) {\n            assert.strictEqual(result.code, [\n                \"// Can't reproduce test failure\",\n                \"// minify options: {\",\n                '//   \"compress\": false,',\n                '//   \"mangle\": false,',\n                '//   \"output\": {',\n                '//     \"beautify\": true',\n                \"//   }\",\n                \"// }\",\n            ].join(\"\\n\"));\n        } else {\n            var message = result.code.split(/\\n/, 3)[1].slice(\"// output: \".length);\n            assert.strictEqual(result.code, [\n                [\n                    \"try{\",\n                    \"null[function(){}]\",\n                    \"}catch(e){\",\n                    \"console.log(e)\",\n                    \"}\",\n                ].join(\"\"),\n                \"// output: \" + message,\n                \"// \",\n                \"// minify: \" + message.replace(\"(){}\", \"() {}\"),\n                \"// \",\n                \"// options: {\",\n                '//   \"compress\": false,',\n                '//   \"mangle\": false,',\n                '//   \"output\": {',\n                '//     \"beautify\": true',\n                \"//   }\",\n                \"// }\",\n            ].join(\"\\n\"));\n        }\n    });\n    it(\"Should maintain block-scope for const/let\", function() {\n        if (semver.satisfies(process.version, \"<4\")) return;\n        this.timeout(120000);\n        var code = [\n            '\"use strict\";',\n            \"\",\n            \"L: for (let a = (1 - .8).toString(); ;) {\",\n            \"    if (!console.log(a)) {\",\n            \"        break L;\",\n            \"    }\",\n            \"}\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n            module: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// (beautified)\",\n            code,\n            \"// output: 0.19999999999999996\",\n            \"// \",\n            \"// minify: 0.2\",\n            \"// \",\n            \"// options: {\",\n            '//   \"compress\": {',\n            '//     \"unsafe_math\": true',\n            '//   },',\n            '//   \"mangle\": false,',\n            '//   \"module\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should handle corner cases when intermediate case differs only in Error.message\", function() {\n        if (semver.satisfies(process.version, \"<=0.10\")) return;\n        var result = reduce_test(read(\"test/input/reduce/diff_error.js\"), {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n        }, {\n            verbose: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, read(\"test/input/reduce/diff_error.reduced.js\"));\n    });\n    it(\"Should maintain valid LHS in destructuring assignments\", function() {\n        if (semver.satisfies(process.version, \"<6\")) return;\n        var result = reduce_test(read(\"test/input/reduce/destructured_assign.js\"), {\n            compress: {\n                unsafe_math: true,\n            },\n            mangle: false,\n            validate: true,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, read(\"test/input/reduce/destructured_assign.reduced.js\"));\n    });\n    it(\"Should handle destructured catch expressions\", function() {\n        if (semver.satisfies(process.version, \"<6\")) return;\n        var result = reduce_test(read(\"test/input/reduce/destructured_catch.js\"), {\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, read(\"test/input/reduce/destructured_catch.reduced.js\"));\n    });\n    it(\"Should not enumerate `toString` over global context\", function() {\n        if (semver.satisfies(process.version, \"<8\")) return;\n        var code = [\n            \"(async function() {});\",\n            \"for (var k in this);\",\n            \"console.log(k, 42 + this);\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should reduce object with method syntax without invalid intermediate AST\", function() {\n        if (semver.satisfies(process.version, \"<4\")) return;\n        var code = [\n            \"console.log({\",\n            \"    f() {\",\n            \"        return 1 - .8;\",\n            \"    },\",\n            \"}.f());\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            compress: {\n                unsafe_math: true,\n            },\n        });\n        if (result.error) throw result.error;\n        assert.deepEqual(result.warnings, []);\n    });\n    it(\"Should handle thrown falsy values gracefully\", function() {\n        var code = [\n            \"throw 0;\",\n            \"setTimeout(null, 42);\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should transform `export default class` correctly\", function() {\n        var result = reduce_test(read(\"test/input/reduce/export_default.js\"), {\n            compress: false,\n            toplevel: true,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"compress\": false,',\n            '//   \"toplevel\": true',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should transform `export default function` correctly\", function() {\n        if (semver.satisfies(process.version, \"<8\")) return;\n        var code = [\n            \"export default function f(a) {\",\n            \"    for (var k in a)\",\n            \"        console.log(k);\",\n            \"    (async function() {})();\",\n            \"}\",\n            \"f(this);\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should transform `export default (function)` correctly\", function() {\n        var code = [\n            \"for (var k in this)\",\n            \"    console.log(k);\",\n            \"export default (function f() {});\",\n            \"console.log(k);\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n    it(\"Should transform `export default (42)` correctly\", function() {\n        var code = [\n            \"export default (42);\",\n            \"for (var k in this)\",\n            \"    console.log(k);\",\n        ].join(\"\\n\");\n        var result = reduce_test(code, {\n            compress: false,\n            mangle: false,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, [\n            \"// Can't reproduce test failure\",\n            \"// minify options: {\",\n            '//   \"compress\": false,',\n            '//   \"mangle\": false',\n            \"// }\",\n        ].join(\"\\n\"));\n    });\n});\n"
  },
  {
    "path": "test/mocha/sourcemaps.js",
    "content": "var assert = require(\"assert\");\nvar fs = require(\"fs\");\nvar UglifyJS = require(\"../node\");\n\nfunction read(path) {\n    return fs.readFileSync(path, \"utf8\");\n}\n\nfunction source_map(code) {\n    var result = UglifyJS.minify(code, {\n        compress: false,\n        mangle: false,\n        sourceMap: true,\n    });\n    if (result.error) throw result.error;\n    return JSON.parse(result.map);\n}\n\nfunction get_map() {\n    return {\n        \"version\": 3,\n        \"sources\": [ \"index.js\" ],\n        \"names\": [],\n        \"mappings\": \";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ\",\n        \"file\": \"bundle.js\",\n        \"sourcesContent\": [ \"let foo = x => \\\"foo \\\" + x;\\nconsole.log(foo(\\\"bar\\\"));\" ],\n    };\n}\n\nfunction prepare_map(sourceMap) {\n    var code = [\n        '\"use strict\";',\n        \"\",\n        \"var foo = function foo(x) {\",\n        '  return \"foo \" + x;',\n        \"};\",\n        'console.log(foo(\"bar\"));',\n        \"\",\n        \"//# sourceMappingURL=bundle.js.map\",\n    ].join(\"\\n\");\n    var result = UglifyJS.minify(code, {\n        sourceMap: {\n            content: sourceMap,\n            includeSources: true,\n        },\n    });\n    if (result.error) throw result.error;\n    return JSON.parse(result.map);\n}\n\ndescribe(\"sourcemaps\", function() {\n    it(\"Should give correct version\", function() {\n        var map = source_map(\"var x = 1 + 1;\");\n        assert.strictEqual(map.version, 3);\n        assert.deepEqual(map.names, [ \"x\" ]);\n    });\n    it(\"Should give correct names\", function() {\n        var map = source_map([\n            \"({\",\n            \"    get enabled() {\",\n            \"        return 3;\",\n            \"    },\",\n            \"    set enabled(x) {\",\n            \"        ;\",\n            \"    }\",\n            \"});\",\n        ].join(\"\\n\"));\n        assert.deepEqual(map.names, [ \"enabled\", \"x\" ]);\n    });\n    it(\"Should work with sourceMap.names=true\", function() {\n        var result = UglifyJS.minify([\n            \"var obj = {\",\n            \"    p: a,\",\n            \"    q: b\",\n            \"};\",\n        ].join(\"\\n\"), {\n            compress: false,\n            mangle: false,\n            sourceMap: {\n                names: true,\n            },\n        });\n        if (result.error) throw result.error;\n        var map = JSON.parse(result.map);\n        assert.deepEqual(map.names, [ \"obj\", \"p\", \"a\", \"q\", \"b\" ]);\n    });\n    it(\"Should work with sourceMap.names=false\", function() {\n        var result = UglifyJS.minify([\n            \"var obj = {\",\n            \"    p: a,\",\n            \"    q: b\",\n            \"};\",\n        ].join(\"\\n\"), {\n            compress: false,\n            mangle: false,\n            sourceMap: {\n                names: false,\n            },\n        });\n        if (result.error) throw result.error;\n        var map = JSON.parse(result.map);\n        assert.deepEqual(map.names, []);\n    });\n    it(\"Should mark class properties\", function() {\n        var result = UglifyJS.minify([\n            \"class A {\",\n            \"    static P = 42\",\n            \"    set #q(v) {}\",\n            \"}\",\n        ].join(\"\\n\"), {\n            sourceMap: true,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, \"class A{static P=42;set#q(s){}}\");\n        assert.strictEqual(result.map, '{\"version\":3,\"sources\":[\"0\"],\"names\":[\"A\",\"P\",\"#q\",\"v\"],\"mappings\":\"MAAMA,EACFC,SAAW,GACXC,MAAOC,IACX\"}');\n    });\n    it(\"Should mark array/object literals\", function() {\n        var result = UglifyJS.minify([\n            \"var obj = {};\",\n            \"obj.wat([]);\",\n        ].join(\"\\n\"), {\n            sourceMap: true,\n            toplevel: true,\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, \"({}).wat([]);\");\n        assert.strictEqual(result.map, '{\"version\":3,\"sources\":[\"0\"],\"names\":[\"wat\"],\"mappings\":\"CAAU,IACNA,IAAI,EAAE\"}');\n    });\n    it(\"Should give correct sourceRoot\", function() {\n        var code = \"console.log(42);\";\n        var result = UglifyJS.minify(code, {\n            sourceMap: {\n                root: \"//foo.bar/\",\n            },\n        });\n        if (result.error) throw result.error;\n        assert.strictEqual(result.code, code);\n        assert.strictEqual(result.map, '{\"version\":3,\"sourceRoot\":\"//foo.bar/\",\"sources\":[\"0\"],\"names\":[\"console\",\"log\"],\"mappings\":\"AAAAA,QAAQC,IAAI,EAAE\"}');\n    });\n    it(\"Should produce same source map with DOS or UNIX line endings\", function() {\n        var code = [\n            'console.log(\"\\\\',\n            'hello\",',\n            '\"world\");',\n        ];\n        var dos = UglifyJS.minify(code.join(\"\\r\\n\"), {\n            sourceMap: true,\n        });\n        if (dos.error) throw dos.error;\n        var unix = UglifyJS.minify(code.join(\"\\n\"), {\n            sourceMap: true,\n        });\n        if (unix.error) throw unix.error;\n        assert.strictEqual(dos.map, unix.map);\n    });\n\n    describe(\"inSourceMap\", function() {\n        it(\"Should read the given string filename correctly when sourceMapIncludeSources is enabled\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-1236/simple.js\"), {\n                sourceMap: {\n                    content: read(\"test/input/issue-1236/simple.js.map\"),\n                    filename: \"simple.min.js\",\n                    includeSources: true,\n                },\n            });\n            if (result.error) throw result.error;\n            var map = JSON.parse(result.map);\n            assert.equal(map.file, \"simple.min.js\");\n            assert.equal(map.sourcesContent.length, 1);\n            assert.equal(map.sourcesContent[0], 'let foo = x => \"foo \" + x;\\nconsole.log(foo(\"bar\"));');\n        });\n        it(\"Should process inline source map\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-520/input.js\"), {\n                compress: { toplevel: true },\n                sourceMap: {\n                    content: \"inline\",\n                    includeSources: true,\n                    url: \"inline\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code + \"\\n\", read(\"test/input/issue-520/output.js\"));\n        });\n        it(\"Should warn for missing inline source map\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-1323/sample.js\"), {\n                mangle: false,\n                sourceMap: {\n                    content: \"inline\",\n                },\n                warnings: true,\n            });\n            assert.strictEqual(result.code, \"var bar=function(bar){return bar};\");\n            assert.deepEqual(result.warnings, [ \"WARN: inline source map not found: 0\" ]);\n        });\n        it(\"Should handle multiple input and inline source map\", function() {\n            var result = UglifyJS.minify([\n                read(\"test/input/issue-520/input.js\"),\n                read(\"test/input/issue-1323/sample.js\"),\n            ], {\n                sourceMap: {\n                    content: \"inline\",\n                    url: \"inline\",\n                },\n                warnings: true,\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, [\n                \"var Foo=function(){console.log(3)},bar=(new Foo,function(o){return o});\",\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwiMSJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFdBQWdCQyxRQUFRQyxJQUFJLENBQUcsQ0FBRSxFQ0F2Q0MsS0RBMkMsSUFBSUgsSUNDL0MsU0FBY0csR0FDVixPQUFPQSxDQUNYIn0=\",\n            ].join(\"\\n\"));\n            assert.deepEqual(result.warnings, [ \"WARN: inline source map not found: 1\" ]);\n        });\n        it(\"Should drop source contents for includeSources=false\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-520/input.js\"), {\n                compress: false,\n                mangle: false,\n                sourceMap: {\n                    content: \"inline\",\n                    includeSources: true,\n                },\n            });\n            if (result.error) throw result.error;\n            var map = JSON.parse(result.map);\n            assert.strictEqual(map.sourcesContent.length, 1);\n            result = UglifyJS.minify(result.code, {\n                compress: false,\n                mangle: false,\n                sourceMap: {\n                    content: result.map,\n                },\n            });\n            if (result.error) throw result.error;\n            map = JSON.parse(result.map);\n            assert.ok(!(\"sourcesContent\" in map));\n        });\n        it(\"Should parse the correct sourceMappingURL\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-3294/input.js\"), {\n                compress: { toplevel: true },\n                sourceMap: {\n                    content: \"inline\",\n                    includeSources: true,\n                    url: \"inline\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code + \"\\n\", read(\"test/input/issue-3294/output.js\"));\n        });\n        it(\"Should work in presence of unrecognized annotations\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-3441/input.js\"), {\n                compress: false,\n                mangle: false,\n                sourceMap: {\n                    content: \"inline\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, '(function(){console.log(\"hello\")}).call(this);');\n            assert.strictEqual(result.map, '{\"version\":3,\"sources\":[\"main.coffee\"],\"names\":[\"console\",\"log\"],\"mappings\":\"CAAA,WAAAA,QAAQC,IAAI,OAAZ\"}');\n        });\n        it(\"Should not overwrite existing sourcesContent\", function() {\n            var result = UglifyJS.minify({\n                \"in.js\": [\n                    '\"use strict\";',\n                    \"\",\n                    \"var _window$foo = window.foo,\",\n                    \"    a = _window$foo[0],\",\n                    \"    b = _window$foo[1];\",\n                ].join(\"\\n\"),\n            }, {\n                compress: false,\n                mangle: false,\n                sourceMap: {\n                    content: {\n                        version: 3,\n                        sources: [ \"in.js\" ],\n                        names: [\n                            \"window\",\n                            \"foo\",\n                            \"a\",\n                            \"b\",\n                        ],\n                        mappings: \";;kBAAaA,MAAM,CAACC,G;IAAfC,C;IAAGC,C\",\n                        file: \"in.js\",\n                        sourcesContent: [ \"let [a, b] = window.foo;\\n\" ],\n                    },\n                    includeSources: true,\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, '\"use strict\";var _window$foo=window.foo,a=_window$foo[0],b=_window$foo[1];');\n            assert.strictEqual(result.map, '{\"version\":3,\"sources\":[\"in.js\"],\"sourcesContent\":[\"let [a, b] = window.foo;\\\\n\"],\"names\":[\"window\",\"foo\",\"a\",\"b\"],\"mappings\":\"6BAAaA,OAAOC,IAAfC,E,eAAGC,E\"}');\n        });\n    });\n\n    describe(\"sourceMapInline\", function() {\n        it(\"Should append source map to output js when sourceMapInline is enabled\", function() {\n            var result = UglifyJS.minify('var a = function(foo) { return foo; };', {\n                sourceMap: {\n                    url: \"inline\",\n                },\n            });\n            if (result.error) throw result.error;\n            var code = result.code;\n            assert.strictEqual(code, \"var a=function(n){return n};\\n\" +\n                \"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ==\");\n        });\n        it(\"Should not append source map to output js when sourceMapInline is not enabled\", function() {\n            var result = UglifyJS.minify(\"var a = function(foo) { return foo; };\");\n            if (result.error) throw result.error;\n            var code = result.code;\n            assert.strictEqual(code, \"var a=function(n){return n};\");\n        });\n        it(\"Should work with max_line_len\", function() {\n            var result = UglifyJS.minify(read(\"test/input/issue-505/input.js\"), {\n                compress: {\n                    directives: false,\n                },\n                output: {\n                    max_line_len: 20,\n                },\n                sourceMap: {\n                    url: \"inline\",\n                },\n            });\n            if (result.error) throw result.error;\n            assert.strictEqual(result.code, read(\"test/input/issue-505/output.js\"));\n        });\n        it(\"Should work with unicode characters\", function() {\n            var code = [\n                \"var tëst = '→unicøde←';\",\n                \"alert(tëst);\",\n            ].join(\"\\n\");\n            var result = UglifyJS.minify(code, {\n                sourceMap: {\n                    includeSources: true,\n                    url: \"inline\",\n                },\n            });\n            if (result.error) throw result.error;\n            var map = JSON.parse(result.map);\n            assert.strictEqual(map.sourcesContent.length, 1);\n            assert.strictEqual(map.sourcesContent[0], code);\n            var encoded = result.code.slice(result.code.lastIndexOf(\",\") + 1);\n            map = JSON.parse(UglifyJS.to_ascii(encoded));\n            assert.strictEqual(map.sourcesContent.length, 1);\n            assert.strictEqual(map.sourcesContent[0], code);\n            result = UglifyJS.minify(result.code, {\n                sourceMap: {\n                    content: \"inline\",\n                    includeSources: true,\n                },\n            });\n            if (result.error) throw result.error;\n            map = JSON.parse(result.map);\n            assert.strictEqual(map.names.length, 2);\n            assert.strictEqual(map.names[0], \"tëst\");\n            assert.strictEqual(map.names[1], \"alert\");\n        });\n    });\n\n    describe(\"input sourcemaps\", function() {\n        it(\"Should not modify input source map\", function() {\n            var orig = get_map();\n            var original = JSON.stringify(orig);\n            prepare_map(orig);\n            assert.strictEqual(JSON.stringify(orig), original);\n        });\n        it(\"Should copy over original sourcesContent\", function() {\n            var orig = get_map();\n            var map = prepare_map(orig);\n            assert.strictEqual(map.sources.length, 1);\n            assert.strictEqual(map.sources[0], \"index.js\");\n            assert.strictEqual(map.sourcesContent.length, 1);\n            assert.equal(map.sourcesContent[0], orig.sourcesContent[0]);\n        });\n        it(\"Should copy sourcesContent if sources are relative\", function() {\n            var relativeMap = get_map();\n            relativeMap.sources = ['./index.js'];\n            var map = prepare_map(relativeMap);\n            assert.strictEqual(map.sources.length, 1);\n            assert.strictEqual(map.sources[0], \"./index.js\");\n            assert.strictEqual(map.sourcesContent.length, 1);\n            assert.equal(map.sourcesContent[0], relativeMap.sourcesContent[0]);\n        });\n        it(\"Should not have invalid mappings from inputSourceMap\", function() {\n            var map = prepare_map(get_map());\n            // The original source has only 2 lines, check that mappings don't have more lines\n            var msg = \"Mapping should not have higher line number than the original file had\";\n            var lines = map.mappings.split(/;/);\n            assert.ok(lines.length <= 2, msg);\n            var indices = [ 0, 0, 1, 0, 0];\n            lines.forEach(function(segments) {\n                indices[0] = 0;\n                segments.split(/,/).forEach(function(segment) {\n                    UglifyJS.vlq_decode(indices, segment);\n                    assert.ok(indices[2] <= 2, msg);\n                });\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/spidermonkey.js",
    "content": "var assert = require(\"assert\");\nvar exec = require(\"child_process\").exec;\nvar semver = require(\"semver\");\nvar UglifyJS = require(\"../..\");\n\ndescribe(\"spidermonkey export/import sanity test\", function() {\n    it(\"Should produce a functional build when using --self with spidermonkey\", function(done) {\n        this.timeout(120000);\n        var uglifyjs = '\"' + process.argv[0] + '\" bin/uglifyjs';\n        var options = [\n            semver.satisfies(process.version, \"<4\") ? \"--no-module\" : \"--module\",\n            semver.satisfies(process.version, \"<=0.12\") ? \"-mc hoist_funs\" : \"-mc\",\n        ];\n        var command = [\n            [\n                uglifyjs,\n                \"--self\",\n                \"--wrap SpiderUglify\",\n                \"-o spidermonkey\",\n            ].concat(options).join(\" \"),\n            [\n                uglifyjs,\n                \"-p spidermonkey\",\n            ].concat(options).join(\" \"),\n        ].join(\" | \");\n        exec(command, { maxBuffer: 1048576 }, function(err, stdout) {\n            if (err) throw err;\n            eval(stdout);\n            assert.strictEqual(typeof SpiderUglify, \"object\");\n            var result = SpiderUglify.minify(\"foo([true,,2+3]);\");\n            assert.strictEqual(result.error, undefined);\n            assert.strictEqual(result.code, \"foo([!0,,5]);\");\n            done();\n        });\n    });\n\n    it(\"Should not add unnecessary escape slashes to RegExp\", function() {\n        var input = \"/[\\\\\\\\/]/;\";\n        var ast = UglifyJS.parse(input).to_mozilla_ast();\n        assert.strictEqual(UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(), input);\n    });\n\n    it(\"Should judge between directives and strings correctly on import\", function() {\n        var tests = [\n            {\n                input: '\"use strict\";;\"use sloppy\"',\n                directives: 1,\n                strings: 1\n            },\n            {\n                input: ';\"use strict\"',\n                directives: 0,\n                strings: 1\n            },\n            {\n                input: '\"use strict\"; \"use something else\";',\n                directives: 2,\n                strings: 0\n            },\n            {\n                input: 'function foo() {\"use strict\";;\"use sloppy\" }',\n                directives: 1,\n                strings: 1\n            },\n            {\n                input: 'function foo() {;\"use strict\" }',\n                directives: 0,\n                strings: 1\n            },\n            {\n                input: 'function foo() {\"use strict\"; \"use something else\"; }',\n                directives: 2,\n                strings: 0\n            },\n            {\n                input: 'var foo = function() {\"use strict\";;\"use sloppy\" }',\n                directives: 1,\n                strings: 1\n            },\n            {\n                input: 'var foo = function() {;\"use strict\" }',\n                directives: 0,\n                strings: 1\n            },\n            {\n                input: 'var foo = function() {\"use strict\"; \"use something else\"; }',\n                directives: 2,\n                strings: 0\n            },\n            {\n                input: '{\"use strict\";;\"use sloppy\" }',\n                directives: 0,\n                strings: 2\n            },\n            {\n                input: '{;\"use strict\" }',\n                directives: 0,\n                strings: 1\n            },\n            {\n                input: '{\"use strict\"; \"use something else\"; }',\n                directives: 0,\n                strings: 2\n            }\n        ];\n\n        var counter_directives;\n        var counter_strings;\n\n        var checkWalker = new UglifyJS.TreeWalker(function(node, descend) {\n            if (node instanceof UglifyJS.AST_String) {\n                counter_strings++;\n            } else if (node instanceof UglifyJS.AST_Directive) {\n                counter_directives++;\n            }\n        });\n\n        for (var i = 0; i < tests.length; i++) {\n            counter_directives = 0;\n            counter_strings = 0;\n\n            var ast = UglifyJS.parse(tests[i].input);\n            var moz_ast = ast.to_mozilla_ast();\n            var from_moz_ast = UglifyJS.AST_Node.from_mozilla_ast(moz_ast);\n\n            from_moz_ast.walk(checkWalker);\n\n            assert.strictEqual(counter_directives, tests[i].directives, \"Directives count mismatch for test \" + tests[i].input);\n            assert.strictEqual(counter_strings, tests[i].strings, \"String count mismatch for test \" + tests[i].input);\n        }\n    });\n});\n"
  },
  {
    "path": "test/mocha/string-literal.js",
    "content": "var assert = require(\"assert\");\nvar run_code = require(\"../sandbox\").run_code;\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"String literals\", function() {\n    it(\"Should throw syntax error if a string literal contains a newline\", function() {\n        [\n            \"'\\n'\",\n            \"'\\r'\",\n            '\"\\r\\n\"',\n            \"'\\u2028'\",\n            '\"\\u2029\"',\n        ].forEach(function(input) {\n            assert.throws(function() {\n                UglifyJS.parse(input);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && e.message === \"Unterminated string constant\";\n            });\n        });\n    });\n    it(\"Should handle line continuation correctly\", function() {\n        [\n            '\"\\\\\\r\"',\n            '\"\\\\\\n\"',\n            '\"\\\\\\r\\n\"',\n        ].forEach(function(str) {\n            var code = \"console.log(\" + str + \");\";\n            var result = UglifyJS.minify(code);\n            if (result.error) throw result.error;\n            assert.strictEqual(run_code(result.code), run_code(code));\n        });\n    });\n    it(\"Should not throw syntax error if a string has a line continuation\", function() {\n        var ast = UglifyJS.parse('var a = \"a\\\\\\nb\";');\n        assert.equal(ast.print_to_string(), 'var a=\"ab\";');\n    });\n    it(\"Should throw error in strict mode if string contains escaped octalIntegerLiteral\", function() {\n        [\n            '\"use strict\";\\n\"\\\\76\";',\n            '\"use strict\";\\nvar foo = \"\\\\76\";',\n            '\"use strict\";\\n\"\\\\1\";',\n            '\"use strict\";\\n\"\\\\07\";',\n            '\"use strict\";\\n\"\\\\011\"',\n        ].forEach(function(input) {\n            assert.throws(function() {\n                UglifyJS.parse(input);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && e.message === \"Legacy octal escape sequences are not allowed in strict mode\";\n            });\n        });\n    });\n    it(\"Should not throw error outside strict mode if string contains escaped octalIntegerLiteral\", function() {\n        [\n            [ ';\"\\\\76\";', ';\">\";' ],\n            [ ';\"\\\\0\";', ';\"\\\\0\";' ],\n            [ ';\"\\\\08\"', ';\"\\\\x008\";' ],\n            [ ';\"\\\\008\"', ';\"\\\\x008\";' ],\n            [ ';\"\\\\0008\"', ';\"\\\\x008\";' ],\n            [ ';\"use\\\\\\n strict\";\\n\"\\\\07\";', ';\"use strict\";\"\\07\";' ],\n            [ '\"use strict\" === \"use strict\";\\n\"\\\\76\";', '\"use strict\"===\"use strict\";\">\";' ],\n        ].forEach(function(test) {\n            var ast = UglifyJS.parse(test[0]);\n            assert.equal(ast.print_to_string(), test[1]);\n        });\n    });\n    it(\"Should not throw error when digit is 8 or 9\", function() {\n        assert.equal(UglifyJS.parse('\"use strict\";;\"\\\\08\"').print_to_string(), '\"use strict\";;\"\\\\x008\";');\n        assert.equal(UglifyJS.parse('\"use strict\";;\"\\\\09\"').print_to_string(), '\"use strict\";;\"\\\\x009\";');\n    });\n    it(\"Should not unescape unpaired surrogates\", function() {\n        var code = [];\n        for (var i = 0; i <= 0xF; i++) {\n            code.push(\"\\\\u000\" + i.toString(16));\n        }\n        for (;i <= 0xFF; i++) {\n            code.push(\"\\\\u00\" + i.toString(16));\n        }\n        for (;i <= 0xFFF; i++) {\n            code.push(\"\\\\u0\" + i.toString(16));\n        }\n        for (; i <= 0xFFFF; i++) {\n            code.push(\"\\\\u\" + i.toString(16));\n        }\n        code = ';\"' + code.join() + '\"';\n        var normal = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                ascii_only: false\n            }\n        });\n        if (normal.error) throw normal.error;\n        assert.ok(code.length > normal.code.length);\n        assert.strictEqual(eval(code), eval(normal.code));\n        var ascii = UglifyJS.minify(code, {\n            compress: false,\n            mangle: false,\n            output: {\n                ascii_only: false\n            }\n        });\n        if (ascii.error) throw ascii.error;\n        assert.ok(code.length > ascii.code.length);\n        assert.strictEqual(eval(code), eval(ascii.code));\n    });\n    it(\"Should reject invalid Unicode escape sequence\", function() {\n        [\n            'var foo = \"\\\\u-111\"',\n            'var bar = \"\\\\u{-1}\"',\n            'var baz = \"\\\\ugggg\"',\n        ].forEach(function(test) {\n            assert.throws(function() {\n                UglifyJS.parse(test);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && /^Invalid escape sequence: \\\\u/.test(e.message);\n            }, test);\n        });\n    });\n    it(\"Should reject invalid code points in Unicode escape sequence\", function() {\n        [\n            // A bit over the valid range\n            '\"\\\\u{110000}\"',\n            // 32-bit overflow resulting in \"a\"\n            '\"\\\\u{100000061}\"',\n        ].forEach(function(test) {\n            assert.throws(function() {\n                UglifyJS.parse(test);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && /^Invalid escape sequence: \\\\u{1/.test(e.message);\n            }, test);\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/templates.js",
    "content": "var assert = require(\"assert\");\nvar run_code = require(\"../sandbox\").run_code;\nvar semver = require(\"semver\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"Template literals\", function() {\n    it(\"Should reject invalid literal\", function() {\n        [\n            \"`foo\\\\`\",\n            \"`foo${bar`\",\n            \"`foo${bar}\",\n        ].forEach(function(input) {\n            assert.throws(function() {\n                UglifyJS.parse(input);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error\n                    && e.message === \"Unterminated template literal\";\n            }, input);\n        });\n    });\n    it(\"Should reject invalid expression\", function() {\n        [\n            \"`foo${bar;}`\",\n            \"`foo${42bar}`\",\n        ].forEach(function(input) {\n            assert.throws(function() {\n                UglifyJS.parse(input);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, input);\n        });\n    });\n    it(\"Should process line-break characters correctly\", function() {\n        [\n            // native line breaks\n            [ \"`foo\\nbar`\", \"`foo\\nbar`\" ],\n            [ \"`foo\\rbar`\", \"`foo\\nbar`\" ],\n            [ \"`foo\\r\\nbar`\", \"`foo\\nbar`\" ],\n            [ \"`foo\\r\\n\\rbar`\", \"`foo\\n\\nbar`\" ],\n            // escaped line breaks\n            [ \"`foo\\\\nbar`\", \"`foo\\\\nbar`\" ],\n            [ \"`foo\\\\rbar`\", \"`foo\\\\rbar`\" ],\n            [ \"`foo\\r\\\\nbar`\", \"`foo\\n\\\\nbar`\" ],\n            [ \"`foo\\\\r\\nbar`\", \"`foo\\\\r\\nbar`\" ],\n            [ \"`foo\\\\r\\\\nbar`\", \"`foo\\\\r\\\\nbar`\" ],\n            // continuation\n            [ \"`foo\\\\\\nbar`\", \"`foo\\\\\\nbar`\" ],\n            [ \"`foo\\\\\\rbar`\", \"`foo\\\\\\nbar`\" ],\n            [ \"`foo\\\\\\r\\nbar`\", \"`foo\\\\\\nbar`\" ],\n            [ \"`foo\\\\\\r\\n\\rbar`\", \"`foo\\\\\\n\\nbar`\" ],\n            [ \"`foo\\\\\\\\nbar`\", \"`foo\\\\\\\\nbar`\" ],\n            [ \"`foo\\\\\\\\rbar`\", \"`foo\\\\\\\\rbar`\" ],\n            [ \"`foo\\\\\\\\r\\nbar`\", \"`foo\\\\\\\\r\\nbar`\" ],\n        ].forEach(function(test) {\n            var input = \"console.log(\" + test[0] + \");\";\n            var result = UglifyJS.minify(input, {\n                compress: false,\n                mangle: false,\n            });\n            if (result.error) throw result.error;\n            var expected = \"console.log(\" + test[1] + \");\";\n            assert.strictEqual(result.code, expected, test[0]);\n            if (semver.satisfies(process.version, \"<4\")) return;\n            assert.strictEqual(run_code(result.code), run_code(input), test[0]);\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha/tokens.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../..\");\n\ndescribe(\"tokens\", function() {\n    it(\"Should give correct positions for accessors\", function() {\n        // location               0         1         2         3         4\n        //                        01234567890123456789012345678901234567890123456789\n        var ast = UglifyJS.parse(\"var obj = { get [prop]() { return undefined; } }\");\n        // test all AST_ObjectProperty tokens are set as expected\n        var found = false;\n        ast.walk(new UglifyJS.TreeWalker(function(node) {\n            if (node instanceof UglifyJS.AST_ObjectProperty) {\n                found = true;\n                assert.equal(node.start.pos, 12);\n                assert.equal(node.end.endpos, 46);\n                assert(node.key instanceof UglifyJS.AST_SymbolRef);\n                assert.equal(node.key.start.pos, 17);\n                assert.equal(node.key.end.endpos, 21);\n                assert(node.value instanceof UglifyJS.AST_Accessor);\n                assert.equal(node.value.start.pos, 22);\n                assert.equal(node.value.end.endpos, 46);\n            }\n        }));\n        assert(found, \"AST_ObjectProperty not found\");\n    });\n});\n"
  },
  {
    "path": "test/mocha/with.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"With\", function() {\n    it(\"Should throw syntaxError when using with statement in strict mode\", function() {\n        var code = '\"use strict\";\\nthrow NotEarlyError;\\nwith ({}) { }';\n        var test = function() {\n            UglifyJS.parse(code);\n        }\n        var error = function(e) {\n            return e instanceof UglifyJS.JS_Parse_Error\n                && e.message === \"Strict mode may not include a with statement\";\n        }\n        assert.throws(test, error);\n    });\n    it(\"Should set uses_with for scopes involving With statements\", function() {\n        var ast = UglifyJS.parse(\"with(e) {f(1, 2)}\");\n        ast.figure_out_scope();\n        assert.equal(ast.uses_with, true);\n        assert.equal(ast.body[0].expression.scope.resolve().uses_with, true);\n        assert.equal(ast.body[0].body.body[0].body.expression.scope.resolve().uses_with, true);\n    });\n});\n"
  },
  {
    "path": "test/mocha/yields.js",
    "content": "var assert = require(\"assert\");\nvar UglifyJS = require(\"../node\");\n\ndescribe(\"generator\", function() {\n    it(\"Should reject `yield` as symbol name within generator functions only\", function() {\n        [\n            \"function yield() {}\",\n            \"function(yield) {}\",\n            \"function() { yield: {} }\",\n            \"function() { var yield; }\",\n            \"function() { function yield() {} }\",\n            \"function() { try {} catch (yield) {} }\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(\"(\" + code + \")();\");\n            assert.strictEqual(ast.TYPE, \"Toplevel\");\n            assert.strictEqual(ast.body.length, 1);\n            assert.strictEqual(ast.body[0].TYPE, \"SimpleStatement\");\n            assert.strictEqual(ast.body[0].body.TYPE, \"Call\");\n            assert.strictEqual(ast.body[0].body.expression.TYPE, \"Function\");\n            assert.throws(function() {\n                UglifyJS.parse(\"(\" + code.replace(/^function/, \"function*\") + \")();\");\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject `yield` expression outside of generator functions\", function() {\n        [\n            \"yield 42;\",\n            \"function f() { yield 42; }\",\n            \"function* f() { function g() { yield 42; } }\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should reject `yield` expression directly on computed key of function argument\", function() {\n        [\n            \"function f({ [yield 42]: a }) {}\",\n            \"function* f({ [yield 42]: a }) {}\",\n        ].forEach(function(code) {\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n    it(\"Should accept `yield` expression nested within computed key of function argument\", function() {\n        [\n            \"function f({ [function*() { yield 42; }()]: a }) {}\",\n            \"function* f({ [function*() { yield 42; }()]: a }) {}\",\n        ].forEach(function(code) {\n            var ast = UglifyJS.parse(code);\n            assert.strictEqual(ast.TYPE, \"Toplevel\");\n            assert.strictEqual(ast.body.length, 1);\n            assert.strictEqual(ast.body[0].argnames.length, 1);\n            assert.strictEqual(ast.body[0].argnames[0].TYPE, \"DestructuredObject\");\n        });\n    });\n    it(\"Should reject `yield*` without an expression\", function() {\n        [\n            \"yield*\",\n            \"yield*;\",\n            \"yield*,\",\n            \"(yield*)\",\n            \"[ yield* ]\",\n            \"42[yield*]\",\n            \"yield* && 42\",\n        ].forEach(function(code) {\n            code = \"function* f() { \" + code + \" }\";\n            assert.throws(function() {\n                UglifyJS.parse(code);\n            }, function(e) {\n                return e instanceof UglifyJS.JS_Parse_Error;\n            }, code);\n        });\n    });\n});\n"
  },
  {
    "path": "test/mocha.js",
    "content": "var fs = require(\"fs\");\n\nvar config = {\n    timeout: function(limit) {\n        this.limit = limit + lag;\n    },\n};\nvar lag = +process.env[\"UGLIFY_GITHUB_LAG\"] || 0;\nvar tasks = [];\nvar titles = [];\nconfig.timeout(10000);\ndescribe = function(title, fn) {\n    config = Object.create(config);\n    titles.push(title);\n    fn.call(config);\n    titles.pop();\n    config = Object.getPrototypeOf(config);\n};\nit = function(title, fn) {\n    fn.limit = config.limit;\n    fn.titles = titles.slice();\n    fn.titles.push(title);\n    tasks.push(fn);\n};\n(function(arg) {\n    return arg ? [ arg ] : fs.readdirSync(\"test/mocha\").filter(function(file) {\n        return /\\.js$/.test(file);\n    });\n})(process.argv[2]).forEach(function(file) {\n    require(\"./mocha/\" + file);\n});\n\nfunction log_titles(log, current, marker) {\n    var indent = \"\";\n    var writing = false;\n    for (var i = 0; i < current.length; i++, indent += \"  \") {\n        if (titles[i] != current[i]) writing = true;\n        if (writing) log(indent + (i == current.length - 1 && marker || \"\") + current[i]);\n    }\n    titles = current;\n}\n\nfunction red(text) {\n    return \"\\u001B[31m\" + text + \"\\u001B[39m\";\n}\n\nfunction green(text) {\n    return \"\\u001B[32m\" + text + \"\\u001B[39m\";\n}\n\nvar errors = [];\nvar total = tasks.length;\ntitles = [];\nprocess.nextTick(function run() {\n    var task = tasks.shift();\n    if (task) try {\n        var elapsed = Date.now();\n        var timer;\n        var done = function() {\n            elapsed = Date.now() - elapsed;\n            if (elapsed > task.limit) {\n                throw new Error(\"Timed out: \" + elapsed + \"ms > \" + task.limit + \"ms\");\n            }\n            reset();\n            log_titles(console.log, task.titles, green('\\u221A '));\n            process.nextTick(run);\n        };\n        if (task.length) {\n            task.timeout = function(limit) {\n                clearTimeout(timer);\n                limit += lag;\n                task.limit = limit;\n                timer = setTimeout(function() {\n                    raise(new Error(\"Timed out: exceeds \" + limit + \"ms\"));\n                }, limit);\n            };\n            task.timeout(task.limit - lag);\n            process.on(\"uncaughtException\", raise);\n            task.call(task, done);\n        } else {\n            task.timeout = config.timeout;\n            task.call(task);\n            done();\n        }\n    } catch (err) {\n        raise(err);\n    } else if (errors.length) {\n        console.error();\n        console.log(red(errors.length + \" test(s) failed!\"));\n        titles = [];\n        errors.forEach(function(titles, index) {\n            console.error();\n            log_titles(console.error, titles, (index + 1) + \") \");\n            var lines = titles.error.stack.split('\\n');\n            console.error(red(lines[0]));\n            console.error(lines.slice(1).join(\"\\n\"));\n        });\n        process.exit(1);\n    } else {\n        console.log();\n        console.log(green(total + \" test(s) passed.\"));\n    }\n\n    function raise(err) {\n        reset();\n        task.titles.error = err;\n        errors.push(task.titles);\n        log_titles(console.log, task.titles, red('\\u00D7 '));\n        process.nextTick(run);\n    }\n\n    function reset() {\n        clearTimeout(timer);\n        done = function() {};\n        process.removeListener(\"uncaughtException\", raise);\n    }\n});\n"
  },
  {
    "path": "test/mozilla-ast.js",
    "content": "// Testing UglifyJS <-> SpiderMonkey AST conversion\n\"use strict\";\n\nvar acorn = require(\"acorn\");\nvar ufuzz = require(\"./ufuzz\");\nvar UglifyJS = require(\"..\");\n\nfunction beautify(ast) {\n    var beautified = UglifyJS.minify(ast, {\n        compress: false,\n        mangle: false,\n        module: ufuzz.module,\n        output: {\n            ast: true,\n            beautify: true,\n            braces: true,\n        },\n    });\n    if (!beautified.error) {\n        var verify = UglifyJS.minify(beautified.code, {\n            compress: false,\n            mangle: false,\n            module: ufuzz.module,\n        });\n        if (verify.error) return verify;\n    }\n    return beautified;\n}\n\nfunction validate(ast) {\n    try {\n        ast.walk(new UglifyJS.TreeWalker(function(node) {\n            node.validate();\n        }));\n    } catch (e) {\n        return { error: e };\n    }\n    return UglifyJS.minify(ast, {\n        compress: false,\n        mangle: false,\n        module: ufuzz.module,\n        output: {\n            ast: true,\n        },\n        validate: true,\n    });\n}\n\nfunction patch_import(code) {\n    return code.replace(/\\bimport\\s*\\{\\s*\\}\\s*from\\s*(['\"])/g, \"import$1\")\n        .replace(/\\b(import\\b.*?)\\s*,\\s*\\{\\s*\\}\\s*(from\\s*['\"])/g, \"$1 $2\");\n}\n\nfunction equals(input, transformed) {\n    if (input.code === transformed.code) return true;\n    return patch_import(input.code) === patch_import(transformed.code);\n}\n\nfunction test(input, to_moz, description, skip_on_error, beautified) {\n    try {\n        var ast = UglifyJS.AST_Node.from_mozilla_ast(to_moz(input));\n    } catch (e) {\n        if (skip_on_error) return true;\n        console.error(\"//=============================================================\");\n        console.error(\"//\", description, \"failed... round\", round);\n        console.error(e);\n        console.error(\"// original code\");\n        if (beautified === true) console.error(\"// (beautified)\");\n        console.error(input.code);\n        return false;\n    }\n    var transformed = validate(ast);\n    if (transformed.error || !equals(input, transformed)) {\n        if (!beautified) {\n            beautified = beautify(input.ast);\n            if (!beautified.error) {\n                beautified.raw = beautified.code;\n                if (!test(beautified, to_moz, description, skip_on_error, true)) return false;\n            }\n        }\n        console.error(\"//=============================================================\");\n        console.error(\"// !!!!!! Failed... round\", round);\n        console.error(\"// original code\");\n        if (beautified.error) {\n            console.error(\"// !!! beautify failed !!!\");\n            console.error(beautified.error.stack);\n        } else if (beautified === true) {\n            console.error(\"// (beautified)\");\n        }\n        console.error(input.raw);\n        console.error();\n        console.error();\n        console.error(\"//-------------------------------------------------------------\");\n        console.error(\"//\", description);\n        if (transformed.error) {\n            console.error(transformed.error.stack);\n        } else {\n            beautified = beautify(transformed.ast);\n            if (beautified.error) {\n                console.error(\"// !!! beautify failed !!!\");\n                console.error(beautified.error.stack);\n                console.error(transformed.code);\n            } else {\n                console.error(\"// (beautified)\");\n                console.error(beautified.code);\n            }\n        }\n        console.error(\"!!!!!! Failed... round\", round);\n        return false;\n    }\n    return true;\n}\n\nvar num_iterations = ufuzz.num_iterations;\nvar minify_options = require(\"./ufuzz/options.json\").map(JSON.stringify);\nminify_options.unshift(null);\nfor (var round = 1; round <= num_iterations; round++) {\n    process.stdout.write(round + \" of \" + num_iterations + \"\\r\");\n    var code = ufuzz.createTopLevelCode();\n    minify_options.forEach(function(options) {\n        var ok = true;\n        var minified;\n        if (options) {\n            var o = JSON.parse(options);\n            o.module = ufuzz.module;\n            minified = UglifyJS.minify(code, o);\n            if (minified.error) {\n                console.log(\"//=============================================================\");\n                console.log(\"// minify() failed... round\", round);\n                console.log(\"// original code\");\n                console.log(code);\n                console.log();\n                console.log();\n                console.log(\"//-------------------------------------------------------------\");\n                console.log(\"minify(options):\");\n                console.log(JSON.stringify(o, null, 2));\n                return;\n            }\n            minified = minified.code;\n        }\n        var input = UglifyJS.minify(minified || code, {\n            compress: false,\n            mangle: false,\n            module: ufuzz.module,\n            output: {\n                ast: true,\n            },\n        });\n        input.raw = options ? input.code : code;\n        if (input.error) {\n            ok = false;\n            console.error(\"//=============================================================\");\n            console.error(\"// parse() failed... round\", round);\n            console.error(\"// original code\");\n            console.error(code);\n            console.error();\n            console.error();\n            if (options) {\n                console.error(\"//-------------------------------------------------------------\");\n                console.error(\"// minified code\");\n                console.error(minified);\n                console.error();\n                console.error();\n                console.error(\"//-------------------------------------------------------------\");\n                console.error(\"minify(options):\");\n                console.error(JSON.stringify(o, null, 2));\n                console.error();\n                console.error();\n            }\n            console.error(\"//-------------------------------------------------------------\");\n            console.error(\"// parse() error\");\n            console.error(input.error);\n        }\n        if (ok) ok = test(input, function(input) {\n            return input.ast.to_mozilla_ast();\n        }, \"AST_Node.to_mozilla_ast()\");\n        if (ok) ok = test(input, function(input) {\n            return acorn.parse(input.raw, {\n                ecmaVersion: \"latest\",\n                locations: true,\n                sourceType: \"module\",\n            });\n        }, \"acorn.parse()\", !ufuzz.verbose);\n        if (!ok && isFinite(num_iterations)) {\n            console.log();\n            process.exit(1);\n        }\n    });\n}\nconsole.log();\n"
  },
  {
    "path": "test/node.js",
    "content": "var fs = require(\"fs\");\n\nnew Function(\"domprops\", \"exports\", require(\"../tools/node\").FILES.map(function(file) {\n    if (/exports\\.js$/.test(file)) file = require.resolve(\"./exports\");\n    return fs.readFileSync(file, \"utf8\");\n}).join(\"\\n\\n\"))(require(\"../tools/domprops.json\"), exports);\n"
  },
  {
    "path": "test/reduce.js",
    "content": "var crypto = require(\"crypto\");\nvar U = require(\"..\");\nvar List = U.List;\nvar os = require(\"os\");\nvar sandbox = require(\"./sandbox\");\n\n// Reduce a test case by iteratively replacing AST nodes with various\n// permutations. Each AST_Statement in the tree is also speculatively dropped\n// to determine whether it is needed.  If the altered tree and the last known\n// good tree produce the same output after being run, then the permutation\n// survives to the next generation and is the basis for subsequent iterations.\n// The test case is reduced as a consequence of complex expressions being\n// replaced with simpler ones.  Note that a reduced test case will have\n// different runtime output - it is not functionally equivalent to the\n// original. The only criteria is that once the generated reduced test case is\n// run without minification, it will produce different output from the code\n// minified with `minify_options`.  Returns a `minify` result object.\n\nError.stackTraceLimit = Infinity;\nmodule.exports = function reduce_test(testcase, minify_options, reduce_options) {\n    minify_options = minify_options || {};\n    reduce_options = reduce_options || {};\n    var parse_options = {\n        module: minify_options.module || minify_options.module === undefined,\n    }\n    var print_options = {};\n    [\n        \"ie\",\n        \"v8\",\n        \"webkit\",\n    ].forEach(function(name) {\n        var value = minify_options[name] || minify_options.output && minify_options.output[name];\n        if (value) print_options[name] = value;\n    });\n    if (testcase instanceof U.AST_Node) testcase = testcase.print_to_string(print_options);\n    var max_iterations = reduce_options.max_iterations || 1000;\n    var max_timeout = reduce_options.max_timeout || 10000;\n    var warnings = [];\n    var log = reduce_options.log || function(msg) {\n        warnings.push(msg);\n    };\n    var verbose = reduce_options.verbose;\n    var minify_options_json = JSON.stringify(minify_options, null, 2);\n    var result_cache = Object.create(null);\n    var test_for_diff = compare_run_code;\n    // the initial timeout to assess the viability of the test case must be large\n    var differs = test_for_diff(testcase, minify_options, result_cache, max_timeout);\n\n    if (verbose) {\n        log(\"// Node.js \" + process.version + \" on \" + os.platform() + \" \" + os.arch());\n    }\n    if (differs && differs.error && [ \"DefaultsError\", \"SyntaxError\" ].indexOf(differs.error.name) < 0) {\n        test_for_diff = test_minify;\n        differs = test_for_diff(testcase, minify_options, result_cache, max_timeout);\n    }\n    // same stdout result produced when minified\n    if (!differs) return {\n        code: [\n            \"// Can't reproduce test failure\",\n            \"// minify options: \" + to_comment(minify_options_json)\n        ].join(\"\\n\"),\n        warnings: warnings,\n    };\n    if (differs.timed_out) return {\n        code: [\n            \"// Can't reproduce test failure within \" + max_timeout + \"ms\",\n            \"// minify options: \" + to_comment(minify_options_json)\n        ].join(\"\\n\"),\n        warnings: warnings,\n    };\n    if (differs.error) {\n        differs.warnings = warnings;\n        return differs;\n    }\n    if (sandbox.is_error(differs.unminified_result)\n        && sandbox.is_error(differs.minified_result)\n        && differs.unminified_result.name == differs.minified_result.name) return {\n        code: [\n            \"// No differences except in error message\",\n            \"// minify options: \" + to_comment(minify_options_json)\n        ].join(\"\\n\"),\n        warnings: warnings,\n    };\n    max_timeout = Math.min(100 * differs.elapsed, max_timeout);\n    // Replace expressions with constants that will be parsed into\n    // AST_Nodes as required.  Each AST_Node has its own permutation count,\n    // so these replacements can't be shared.\n    // Although simpler replacements are generally faster and better,\n    // feel free to experiment with a different replacement set.\n    var REPLACEMENTS = [\n        // \"null\", \"''\", \"false\", \"'foo'\", \"undefined\", \"9\",\n        \"1\", \"0\",\n    ];\n\n    // There's a relationship between each node's _permute counter and\n    // REPLACEMENTS.length which is why fractional _permutes were needed.\n    // One could scale all _permute operations by a factor of `steps`\n    // to only deal with integer operations, but this works well enough.\n    var steps = 4;        // must be a power of 2\n    var step = 1 / steps; // 0.25 is exactly representable in floating point\n\n    var tt = new U.TreeTransformer(function(node, descend, in_list) {\n        if (CHANGED) return;\n\n        // quick ignores\n        if (node instanceof U.AST_Accessor) return;\n        if (node instanceof U.AST_Directive) return;\n        if (!in_list && node instanceof U.AST_EmptyStatement) return;\n        if (node instanceof U.AST_Label) return;\n        if (node instanceof U.AST_LabelRef) return;\n        if (node instanceof U.AST_Toplevel) return;\n        var parent = tt.parent();\n        if (node instanceof U.AST_SymbolFunarg && parent instanceof U.AST_Accessor) return;\n        if (!in_list && parent.rest !== node && node instanceof U.AST_SymbolDeclaration) return;\n\n        // ensure that the _permute prop is a number.\n        // can not use `node.start._permute |= 0;` as it will erase fractional part.\n        if (typeof node.start._permute === \"undefined\") node.start._permute = 0;\n\n        // if node reached permutation limit - skip over it.\n        // no structural AST changes before this point.\n        if (node.start._permute >= REPLACEMENTS.length) return;\n\n        // ignore lvalues\n        if (parent instanceof U.AST_Assign && parent.left === node) return;\n        if (parent instanceof U.AST_DefaultValue && parent.name === node) return;\n        if (parent instanceof U.AST_DestructuredKeyVal && parent.value === node) return;\n        if (parent instanceof U.AST_Unary && parent.expression === node) switch (parent.operator) {\n          case \"++\":\n          case \"--\":\n          case \"delete\":\n            return;\n        }\n        if (parent instanceof U.AST_VarDef && parent.name === node) return;\n        // preserve class methods\n        if (parent instanceof U.AST_ClassMethod && parent.value === node) return;\n        // preserve exports\n        if (parent instanceof U.AST_ExportDeclaration) return;\n        if (parent instanceof U.AST_ExportDefault) return;\n        if (parent instanceof U.AST_ExportForeign) return;\n        if (parent instanceof U.AST_ExportReferences) return;\n        // preserve sole definition of an export statement\n        if (node instanceof U.AST_VarDef\n            && parent.definitions.length == 1\n            && tt.parent(1) instanceof U.AST_ExportDeclaration) {\n            return;\n        }\n        // preserve for (var xxx; ...)\n        if (parent instanceof U.AST_For && parent.init === node && node instanceof U.AST_Definitions) return node;\n        // preserve for (xxx in/of ...)\n        if (parent instanceof U.AST_ForEnumeration && parent.init === node) return node;\n        // preserve super(...)\n        if (node.TYPE == \"Call\" && node.expression instanceof U.AST_Super) return;\n        if (node instanceof U.AST_Super && parent.TYPE == \"Call\" && parent.expression === node) return node;\n\n        // node specific permutations with no parent logic\n\n        if (node instanceof U.AST_Array) {\n            var expr = node.elements[0];\n            if (expr && !(expr instanceof U.AST_Hole)) {\n                node.start._permute++;\n                CHANGED = true;\n                return expr instanceof U.AST_Spread ? expr.expression : expr;\n            }\n        }\n        else if (node instanceof U.AST_Await) {\n            node.start._permute++;\n            CHANGED = true;\n            return node.expression;\n        }\n        else if (node instanceof U.AST_Binary) {\n            var permute = ((node.start._permute += step) * steps | 0) % 4;\n            var expr = [\n                node.left,\n                node.right,\n            ][ permute & 1 ];\n            if (expr instanceof U.AST_Destructured) expr = expr.transform(new U.TreeTransformer(function(node, descend) {\n                if (node instanceof U.AST_DefaultValue) return new U.AST_Assign({\n                    operator: \"=\",\n                    left: node.name.transform(this),\n                    right: node.value,\n                    start: {},\n                });\n                if (node instanceof U.AST_DestructuredKeyVal) return new U.AST_ObjectKeyVal(node);\n                if (node instanceof U.AST_Destructured) {\n                    node = new (node instanceof U.AST_DestructuredArray ? U.AST_Array : U.AST_Object)(node);\n                    descend(node, this);\n                }\n                return node;\n            }));\n            CHANGED = true;\n            return permute < 2 ? expr : wrap_with_console_log(expr);\n        }\n        else if (node instanceof U.AST_BlockStatement) {\n            if (in_list && node.body.filter(function(node) {\n                return node instanceof U.AST_Const || node instanceof U.AST_Let;\n            }).length == 0) {\n                node.start._permute++;\n                CHANGED = true;\n                return List.splice(node.body);\n            }\n        }\n        else if (node instanceof U.AST_Call) {\n            var expr = [\n                !(node.expression instanceof U.AST_Super) && node.expression,\n                node.args[0],\n                null,  // intentional\n            ][ ((node.start._permute += step) * steps | 0) % 3 ];\n            if (expr) {\n                CHANGED = true;\n                return expr instanceof U.AST_Spread ? expr.expression : expr;\n            }\n            if (node.expression instanceof U.AST_Arrow && node.expression.value) {\n                var seq = node.args.slice();\n                seq.push(node.expression.value);\n                CHANGED = true;\n                return to_sequence(seq);\n            }\n            if (node.expression instanceof U.AST_Function) {\n                // hoist and return expressions from the IIFE function expression\n                var scope = tt.find_parent(U.AST_Scope), seq = [];\n                node.expression.body.forEach(function(node) {\n                    var expr = node instanceof U.AST_Exit ? node.value : node.body;\n                    if (expr instanceof U.AST_Node && !U.is_statement(expr) && can_hoist(expr, scope)) {\n                        // collect expressions from each statement's body\n                        seq.push(expr);\n                    }\n                });\n                CHANGED = true;\n                return to_sequence(seq);\n            }\n        }\n        else if (node instanceof U.AST_Catch) {\n            // drop catch block\n            node.start._permute++;\n            CHANGED = true;\n            return null;\n        }\n        else if (node instanceof U.AST_Conditional) {\n            CHANGED = true;\n            return [\n                node.condition,\n                node.consequent,\n                node.alternative,\n            ][ ((node.start._permute += step) * steps | 0) % 3 ];\n        }\n        else if (node instanceof U.AST_DefaultValue) {\n            node.start._permute++;\n            CHANGED = true;\n            return node.name;\n        }\n        else if (node instanceof U.AST_Defun) {\n            switch (((node.start._permute += step) * steps | 0) % 2) {\n              case 0:\n                CHANGED = true;\n                return List.skip;\n              default:\n                if (can_hoist(node, tt.find_parent(U.AST_Scope))) {\n                    // hoist function declaration body\n                    var body = node.body;\n                    node.body = [];\n                    // retain function with empty body to be dropped later\n                    body.push(node);\n                    CHANGED = true;\n                    return List.splice(body);\n                }\n            }\n        }\n        else if (node instanceof U.AST_DestructuredArray) {\n            var expr = node.elements[0];\n            if (expr && !(expr instanceof U.AST_Hole)) {\n                node.start._permute++;\n                CHANGED = true;\n                return expr;\n            }\n        }\n        else if (node instanceof U.AST_DestructuredObject) {\n            // first property's value\n            var expr = node.properties[0];\n            if (expr) {\n                node.start._permute++;\n                CHANGED = true;\n                return expr.value;\n            }\n        }\n        else if (node instanceof U.AST_DWLoop) {\n            var expr = [\n                node.condition,\n                node.body,\n                null,  // intentional\n            ][ (node.start._permute * steps | 0) % 3 ];\n            node.start._permute += step;\n            if (!expr) {\n                if (node.body[0] instanceof U.AST_Break) {\n                    if (node instanceof U.AST_Do) {\n                        CHANGED = true;\n                        return List.skip;\n                    }\n                    expr = node.condition; // AST_While - fall through\n                }\n            }\n            if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {\n                CHANGED = true;\n                return to_statement(expr);\n            }\n        }\n        else if (node instanceof U.AST_ExportDeclaration) {\n            node.start._permute++;\n            CHANGED = true;\n            return node.body;\n        }\n        else if (node instanceof U.AST_ExportDefault) {\n            node.start._permute++;\n            CHANGED = true;\n            return to_statement(node.body);\n        }\n        else if (node instanceof U.AST_Finally) {\n            // drop finally block\n            node.start._permute++;\n            CHANGED = true;\n            return null;\n        }\n        else if (node instanceof U.AST_For) {\n            var expr = [\n                node.init,\n                node.condition,\n                node.step,\n                node.body,\n            ][ (node.start._permute * steps | 0) % 4 ];\n            node.start._permute += step;\n            if (expr && (expr !== node.body || !has_loopcontrol(expr, node, parent))) {\n                CHANGED = true;\n                return to_statement_init(expr);\n            }\n        }\n        else if (node instanceof U.AST_ForEnumeration) {\n            var expr;\n            switch ((node.start._permute * steps | 0) % 4) {\n              case 0:\n                expr = node.object;\n                break;\n              case 1:\n                expr = wrap_with_console_log(node.object);\n                break;\n              case 2:\n                if (has_loopcontrol(node.body, node, parent)) break;\n                expr = node.body;\n                break;\n              case 3:\n                if (!(node.init instanceof U.AST_Var)) break;\n                if (node.init.definitions[0].name instanceof U.AST_Destructured) break;\n                expr = node.init;\n                break;\n            }\n            node.start._permute += step;\n            if (expr) {\n                CHANGED = true;\n                return to_statement_init(expr);\n            }\n        }\n        else if (node instanceof U.AST_If) {\n            var expr = [\n                node.condition,\n                node.body,\n                node.alternative,\n                node,\n            ][ (node.start._permute * steps | 0) % 4 ];\n            node.start._permute += step;\n            if (expr === node) {\n                if (node.alternative) {\n                    expr = node.clone();\n                    expr.alternative = null;\n                    CHANGED = true;\n                    return expr;\n                }\n            } else if (expr) {\n                // replace if statement with its condition, then block or else block\n                CHANGED = true;\n                return to_statement(expr);\n            }\n        }\n        else if (node instanceof U.AST_LabeledStatement) {\n            if (node.body instanceof U.AST_Statement\n                && !has_loopcontrol(node.body, node.body, node)) {\n                // replace labelled statement with its non-labelled body\n                node.start._permute = REPLACEMENTS.length;\n                CHANGED = true;\n                return node.body;\n            }\n        }\n        else if (node instanceof U.AST_Object) {\n            // first property's value\n            var expr = node.properties[0];\n            if (expr instanceof U.AST_ObjectKeyVal) {\n                expr = expr.value;\n            } else if (expr instanceof U.AST_Spread) {\n                expr = expr.expression;\n            } else if (expr && expr.key instanceof U.AST_Node) {\n                expr = expr.key;\n            } else {\n                expr = null;\n            }\n            if (expr) {\n                node.start._permute++;\n                CHANGED = true;\n                return expr;\n            }\n        }\n        else if (node instanceof U.AST_PropAccess) {\n            var expr = [\n                !(node.expression instanceof U.AST_Super) && node.expression,\n                node.property instanceof U.AST_Node && !(parent instanceof U.AST_Destructured) && node.property,\n            ][ node.start._permute++ % 2 ];\n            if (expr) {\n                CHANGED = true;\n                return expr;\n            }\n        }\n        else if (node instanceof U.AST_SimpleStatement) {\n            if (node.body instanceof U.AST_Call && node.body.expression instanceof U.AST_Function) {\n                // hoist simple statement IIFE function expression body\n                node.start._permute++;\n                if (can_hoist(node.body.expression, tt.find_parent(U.AST_Scope))) {\n                    CHANGED = true;\n                    return List.splice(node.body.expression.body);\n                }\n            }\n        }\n        else if (node instanceof U.AST_Switch) {\n            var expr = [\n                node.expression,                         // switch expression\n                node.body[0] && node.body[0].expression, // first case expression or undefined\n                node.body[0],                            // first case body or undefined\n            ][ (node.start._permute * steps | 0) % 4 ];\n            node.start._permute += step;\n            if (expr && (!(expr instanceof U.AST_Statement) || !has_loopcontrol(expr, node, parent))) {\n                CHANGED = true;\n                return expr instanceof U.AST_SwitchBranch ? new U.AST_BlockStatement({\n                    body: expr.body.slice(),\n                    start: {},\n                }) : to_statement(expr);\n            }\n        }\n        else if (node instanceof U.AST_Try) {\n            var body = [\n                node.body,\n                node.bcatch && node.bcatch.body,\n                node.bfinally && node.bfinally.body,\n                null,  // intentional\n            ][ (node.start._permute * steps | 0) % 4 ];\n            node.start._permute += step;\n            if (body) {\n                // replace try statement with try block, catch block, or finally block\n                CHANGED = true;\n                return new U.AST_BlockStatement({\n                    body: body,\n                    start: {},\n                });\n            } else {\n                // replace try with a break or return if first in try statement\n                if (node.body[0] instanceof U.AST_Break\n                    || node.body[0] instanceof U.AST_Return) {\n                    CHANGED = true;\n                    return node.body[0];\n                }\n            }\n        }\n        else if (node instanceof U.AST_Unary) {\n            node.start._permute++;\n            CHANGED = true;\n            return node.expression;\n        }\n        else if (node instanceof U.AST_Var) {\n            if (node.definitions.length == 1 && node.definitions[0].value) {\n                // first declaration value\n                node.start._permute++;\n                CHANGED = true;\n                return to_statement(node.definitions[0].value);\n            }\n        }\n        else if (node instanceof U.AST_VarDef) {\n            if (node.value && !(node.name instanceof U.AST_Destructured || parent instanceof U.AST_Const)) {\n                node.start._permute++;\n                CHANGED = true;\n                return new U.AST_VarDef({\n                    name: node.name,\n                    start: {},\n                });\n            }\n        }\n\n        if (in_list) {\n            // drop switch branches\n            if (parent instanceof U.AST_Switch && parent.expression != node) {\n                node.start._permute++;\n                CHANGED = true;\n                return List.skip;\n            }\n\n            // replace or skip statement\n            if (node instanceof U.AST_Statement) {\n                node.start._permute++;\n                CHANGED = true;\n                return List.skip;\n            }\n\n            // remove this node unless its the sole element of a (transient) sequence\n            if (!(parent instanceof U.AST_Sequence) || parent.expressions.length > 1) {\n                node.start._permute++;\n                CHANGED = true;\n                return List.skip;\n            }\n        } else if (parent.rest === node) {\n            node.start._permute++;\n            CHANGED = true;\n            return null;\n        }\n\n        // replace this node\n        var newNode = U.is_statement(node) ? new U.AST_EmptyStatement({\n            start: {},\n        }) : U.parse(REPLACEMENTS[node.start._permute % REPLACEMENTS.length | 0], {\n            expression: true,\n        });\n        newNode.start._permute = ++node.start._permute;\n        CHANGED = true;\n        return newNode;\n    }, function(node, in_list) {\n        if (node instanceof U.AST_Definitions) {\n            // remove empty var statement\n            if (node.definitions.length == 0) return in_list ? List.skip : new U.AST_EmptyStatement({\n                start: {},\n            });\n        } else if (node instanceof U.AST_ObjectMethod) {\n            if (!/Function$/.test(node.value.TYPE)) return new U.AST_ObjectKeyVal({\n                key: node.key,\n                value: node.value,\n                start: {},\n            });\n        } else if (node instanceof U.AST_Sequence) {\n            // expand single-element sequence\n            if (node.expressions.length == 1) return node.expressions[0];\n        } else if (node instanceof U.AST_Try) {\n            // expand orphaned try block\n            if (!node.bcatch && !node.bfinally) return new U.AST_BlockStatement({\n                body: node.body,\n                start: {},\n            });\n        }\n    });\n\n    var before_iterations, diff_error_message, passes = 3, testcase_ast;\n    for (var pass = 1; pass <= passes; pass++) {\n        if (before_iterations !== testcase) {\n            testcase_ast = U.parse(testcase, parse_options);\n            if (diff_error_message === testcase) {\n                // only difference detected is in error message, so expose that and try again\n                testcase_ast.transform(new U.TreeTransformer(function(node, descend) {\n                    if (node.TYPE == \"Call\" && node.expression.print_to_string() == \"console.log\") {\n                        return to_sequence(node.args);\n                    }\n                    if (node instanceof U.AST_Catch && node.argname instanceof U.AST_SymbolCatch) {\n                        descend(node, this);\n                        node.body.unshift(new U.AST_SimpleStatement({\n                            body: wrap_with_console_log(new U.AST_SymbolRef(node.argname)),\n                            start: {},\n                        }));\n                        return node;\n                    }\n                }));\n                var code = testcase_ast.print_to_string(print_options);\n                var diff = test_for_diff(code, minify_options, result_cache, max_timeout);\n                if (diff && !diff.timed_out && !diff.error) {\n                    testcase = code;\n                    differs = diff;\n                } else {\n                    testcase_ast = U.parse(testcase, parse_options);\n                }\n            }\n            diff_error_message = null;\n            testcase_ast.walk(new U.TreeWalker(function(node) {\n                // unshare start props to retain visit data between iterations\n                node.start = JSON.parse(JSON.stringify(node.start));\n                node.start._permute = 0;\n            }));\n            before_iterations = testcase;\n        }\n        for (var c = 0; c < max_iterations; c++) {\n            if (verbose && c % (pass == 1 ? 25 : 100) == 0) {\n                log(\"// reduce test pass \" + pass + \", iteration \" + c + \": \" + testcase.length + \" bytes\");\n            }\n            var CHANGED = false;\n            var code_ast = testcase_ast.clone(true).transform(tt);\n            if (!CHANGED) break;\n            try {\n                var code = code_ast.print_to_string(print_options);\n            } catch (ex) {\n                // AST is not well formed.\n                // no harm done - just log the error, ignore latest change and continue iterating.\n                log(\"*** Error generating code from AST.\");\n                log(ex.stack);\n                log(\"*** Discarding permutation and continuing.\");\n                continue;\n            }\n            var diff = test_for_diff(code, minify_options, result_cache, max_timeout);\n            if (diff) {\n                if (diff.timed_out) {\n                    // can't trust the validity of `code_ast` and `code` when timed out.\n                    // no harm done - just ignore latest change and continue iterating.\n                } else if (diff.error) {\n                    // something went wrong during minify() - could be malformed AST or genuine bug.\n                    // no harm done - just log code & error, ignore latest change and continue iterating.\n                    log(\"*** Error during minification.\");\n                    log(code);\n                    log(diff.error.stack);\n                    log(\"*** Discarding permutation and continuing.\");\n                } else if (sandbox.is_error(diff.unminified_result)\n                    && sandbox.is_error(diff.minified_result)\n                    && diff.unminified_result.name == diff.minified_result.name) {\n                    // ignore difference in error messages caused by minification\n                    diff_error_message = testcase;\n                } else {\n                    // latest permutation is valid, so use it as the basis of new changes\n                    testcase_ast = code_ast;\n                    testcase = code;\n                    differs = diff;\n                }\n            }\n        }\n        if (before_iterations !== testcase) continue;\n        if (c < max_iterations) break;\n        passes++;\n    }\n    var beautified = U.minify(testcase, {\n        compress: false,\n        mangle: false,\n        module: minify_options.module,\n        output: function() {\n            var options = JSON.parse(JSON.stringify(print_options));\n            options.beautify = true;\n            options.braces = true;\n            options.comments = true;\n            return options;\n        }(),\n    });\n    testcase = {\n        code: testcase,\n    };\n    if (!beautified.error) {\n        diff = test_for_diff(beautified.code, minify_options, result_cache, max_timeout);\n        if (diff && !diff.timed_out && !diff.error) {\n            testcase = beautified;\n            testcase.code = \"// (beautified)\\n\" + testcase.code;\n            differs = diff;\n        }\n    }\n    var lines = [ \"\" ];\n    if (isNaN(max_timeout)) {\n        lines.push(\"// minify error: \" + to_comment(differs.minified_result.stack));\n    } else {\n        var unminified_result = differs.unminified_result;\n        var minified_result = differs.minified_result;\n        if (trim_trailing_whitespace(unminified_result) == trim_trailing_whitespace(minified_result)) {\n            lines.push(\n                \"// (stringified)\",\n                \"// output: \" + JSON.stringify(unminified_result),\n                \"// minify: \" + JSON.stringify(minified_result)\n            );\n        } else {\n            lines.push(\n                \"// output: \" + to_comment(unminified_result),\n                \"// minify: \" + to_comment(minified_result)\n            );\n        }\n    }\n    lines.push(\"// options: \" + to_comment(minify_options_json));\n    testcase.code += lines.join(\"\\n\");\n    testcase.warnings = warnings;\n    return testcase;\n};\n\nfunction to_comment(value) {\n    return (\"\" + value).replace(/\\n/g, \"\\n// \");\n}\n\nfunction trim_trailing_whitespace(value) {\n    return (\"\" + value).replace(/\\s+$/, \"\");\n}\n\nfunction has_loopcontrol(body, loop, label) {\n    var found = false;\n    var tw = new U.TreeWalker(function(node) {\n        if (found) return true;\n        if (node instanceof U.AST_LoopControl && this.loopcontrol_target(node) === loop) {\n            return found = true;\n        }\n    });\n    if (label instanceof U.AST_LabeledStatement) tw.push(label);\n    tw.push(loop);\n    body.walk(tw);\n    return found;\n}\n\nfunction can_hoist(body, scope) {\n    var found = false;\n    var tw = new U.TreeWalker(function(node) {\n        if (found) return true;\n        if (node instanceof U.AST_Exit) return found = true;\n        if (node instanceof U.AST_NewTarget) return found = true;\n        if (node instanceof U.AST_Scope) {\n            if (node === body) return;\n            if (node instanceof U.AST_Arrow || node instanceof U.AST_AsyncArrow) node.argnames.forEach(function(sym) {\n                sym.walk(tw);\n            });\n            // don't descend into nested functions\n            return true;\n        }\n        if (node instanceof U.AST_Super) return found = true;\n        if (node instanceof U.AST_SymbolDeclaration || node instanceof U.AST_SymbolRef) switch (node.name) {\n          case \"await\":\n            if (/^Async/.test(scope.TYPE)) return found = true;\n            return;\n          case \"yield\":\n            if (/Generator/.test(scope.TYPE)) return found = true;\n            return;\n        }\n    });\n    body.walk(tw);\n    return !found;\n}\n\nfunction is_timed_out(result) {\n    return sandbox.is_error(result) && /timed out/.test(result.message);\n}\n\nfunction merge_sequence(array, node) {\n    if (node instanceof U.AST_Sequence) {\n        array.push.apply(array, node.expressions);\n    } else {\n        array.push(node);\n    }\n    return array;\n}\n\nfunction to_sequence(expressions) {\n    if (expressions.length == 0) return new U.AST_Number({value: 0, start: {}});\n    if (expressions.length == 1) return expressions[0];\n    return new U.AST_Sequence({\n        expressions: expressions.reduce(merge_sequence, []),\n        start: {},\n    });\n}\n\nfunction to_statement(node) {\n    return U.is_statement(node) ? node : new U.AST_SimpleStatement({\n        body: node,\n        start: {},\n    });\n}\n\nfunction to_statement_init(node) {\n    return node instanceof U.AST_Const || node instanceof U.AST_Let ? new U.AST_BlockStatement({\n        body: [ node ],\n        start: {},\n    }) : to_statement(node);\n}\n\nfunction wrap_with_console_log(node) {\n    // wrap with console.log()\n    return new U.AST_Call({\n        expression: new U.AST_Dot({\n            expression: new U.AST_SymbolRef({\n                name: \"console\",\n                start: {},\n            }),\n            property: \"log\",\n            start: {},\n        }),\n        args: [ node ],\n        start: {},\n    });\n}\n\nfunction run_code(code, toplevel, result_cache, timeout) {\n    var key = crypto.createHash(\"sha1\").update(code).digest(\"base64\");\n    var value = result_cache[key];\n    if (!value) {\n        var start = Date.now();\n        result_cache[key] = value = {\n            result: sandbox.run_code(code, toplevel, timeout),\n            elapsed: Date.now() - start,\n        };\n    }\n    return value;\n}\n\nfunction compare_run_code(code, minify_options, result_cache, max_timeout) {\n    var minified = U.minify(code, minify_options);\n    if (minified.error) return minified;\n\n    var toplevel = sandbox.has_toplevel(minify_options);\n    var unminified = run(code, max_timeout);\n    var timeout = Math.min(100 * unminified.elapsed, max_timeout);\n    var minified_result = run(minified.code, timeout).result;\n\n    if (sandbox.same_stdout(unminified.result, minified_result)) {\n        return is_timed_out(unminified.result) && is_timed_out(minified_result) && {\n            timed_out: true,\n        };\n    }\n    return {\n        unminified_result: unminified.result,\n        minified_result: minified_result,\n        elapsed: unminified.elapsed,\n    };\n\n    function run(code, timeout) {\n        return run_code(sandbox.patch_module_statements(code, minify_options.module), toplevel, result_cache, timeout);\n    }\n}\n\nfunction test_minify(code, minify_options) {\n    var minified = U.minify(code, minify_options);\n    return minified.error && {\n        minified_result: minified.error,\n    };\n}\n"
  },
  {
    "path": "test/release/acorn.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/acorn \\\n&& git clone https://github.com/acornjs/acorn.git tmp/acorn \\\n&& cd tmp/acorn \\\n&& rm -rf .git/hooks \\\n&& git checkout 74b59384320ced82e09da2e8fdbed16810f7379a \\\n&& patch -l -p1 <<EOF\ndiff --git a/acorn-loose/rollup.config.js b/acorn-loose/rollup.config.js\nindex d2389b2..c37882b 100644\n--- a/acorn-loose/rollup.config.js\n+++ b/acorn-loose/rollup.config.js\n@@ -1,2 +0,0 @@\n-import buble from \"rollup-plugin-buble\"\n-\n@@ -23 +20,0 @@ export default {\n-    buble({transforms: {dangerousForOf: true}})\ndiff --git a/acorn-walk/rollup.config.js b/acorn-walk/rollup.config.js\nindex 67dd613..8c28807 100644\n--- a/acorn-walk/rollup.config.js\n+++ b/acorn-walk/rollup.config.js\n@@ -1,2 +0,0 @@\n-import buble from \"rollup-plugin-buble\"\n-\n@@ -19 +16,0 @@ export default {\n-    buble({transforms: {dangerousForOf: true}})\ndiff --git a/acorn/rollup.config.bin.js b/acorn/rollup.config.bin.js\nindex 8a082b0..b3eda60 100644\n--- a/acorn/rollup.config.bin.js\n+++ b/acorn/rollup.config.bin.js\n@@ -1,2 +0,0 @@\n-import buble from \"rollup-plugin-buble\"\n-\n@@ -11 +9 @@ export default {\n-  plugins: [buble()]\n+  plugins: []\ndiff --git a/acorn/rollup.config.js b/acorn/rollup.config.js\nindex c775a0c..cfd4c68 100644\n--- a/acorn/rollup.config.js\n+++ b/acorn/rollup.config.js\n@@ -1,2 +0,0 @@\n-import buble from \"rollup-plugin-buble\"\n-\n@@ -19 +16,0 @@ export default {\n-    buble({transforms: {dangerousForOf: true}})\ndiff --git a/package.json b/package.json\nindex 382f59e..4612a75 100644\n--- a/package.json\n+++ b/package.json\n@@ -24,4 +24 @@\n-    \"prepare\": \"npm run test\",\n-    \"test\": \"node test/run.js && node test/lint.js\",\n-    \"pretest\": \"npm run build:main && npm run build:loose\",\n-    \"test:test262\": \"node bin/run_test262.js\",\n+    \"test\": \"node test/run.js\",\n@@ -32,2 +29 @@\n-    \"build:bin\": \"rollup -c acorn/rollup.config.bin.js\",\n-    \"lint\": \"eslint acorn/src/ acorn-walk/src/ acorn-loose/src/\"\n+    \"build:bin\": \"rollup -c acorn/rollup.config.bin.js\"\n@@ -36,6 +31,0 @@\n-    \"eslint\": \"^4.10.0\",\n-    \"eslint-config-standard\": \"^10.2.1\",\n-    \"eslint-plugin-import\": \"^2.2.0\",\n-    \"eslint-plugin-node\": \"^5.2.1\",\n-    \"eslint-plugin-promise\": \"^3.5.0\",\n-    \"eslint-plugin-standard\": \"^3.0.1\",\n@@ -43,4 +32,0 @@\n-    \"rollup-plugin-buble\": \"^0.19.0\",\n-    \"test262\": \"git+https://github.com/tc39/test262.git#a6c819ad0f049f23f1a37af6b89dbb79fe3b9216\",\n-    \"test262-parser-runner\": \"^0.5.0\",\n-    \"test262-stream\": \"^1.2.1\",\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nminify_in_situ \"acorn/src\" \\\n&& minify_in_situ \"acorn-loose/src\" \\\n&& minify_in_situ \"acorn-walk/src\" \\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& rm -rf acorn/dist acorn-loose/dist acorn-walk/dist \\\n&& npm run build \\\n&& minify_in_situ \"acorn/dist\" \\\n&& minify_in_situ \"acorn-loose/dist\" \\\n&& minify_in_situ \"acorn-walk/dist\" \\\n&& npm test\n"
  },
  {
    "path": "test/release/benchmark.js",
    "content": "require(\"./run\")([\n    \"-mb braces\",\n    \"--toplevel -c\",\n    \"--no-module -mc\",\n    \"-mc passes=3,unsafe\",\n    \"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto\",\n].map(function(options) {\n    var args = options.split(/ /);\n    args.unshift(\"test/benchmark.js\", \"--validate\");\n    return args;\n}));\n"
  },
  {
    "path": "test/release/bootstrap.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/bootstrap \\\n&& git clone --depth 1 --branch v5.0.0-beta2 https://github.com/twbs/bootstrap.git tmp/bootstrap \\\n&& cd tmp/bootstrap \\\n&& rm -rf .git/hooks \\\n&& patch -p1 <<EOF\n--- a/.babelrc.js\n+++ /dev/null\n@@ -1,12 +0,0 @@\n-module.exports = {\n-  presets: [\n-    [\n-      '@babel/preset-env',\n-      {\n-        loose: true,\n-        bugfixes: true,\n-        modules: false\n-      }\n-    ]\n-  ]\n-};\n--- a/.gitattributes\n+++ b/.gitattributes\n@@ -5,0 +6 @@\n+*.png binary\n--- a/build/build-plugins.js\n+++ b/build/build-plugins.js\n@@ -14 +13,0 @@ const rollup = require('rollup')\n-const { babel } = require('@rollup/plugin-babel')\n@@ -19,6 +17,0 @@ const plugins = [\n-  babel({\n-    // Only transpile our source code\n-    exclude: 'node_modules/**',\n-    // Include the helpers in each file, at most one copy of each\n-    babelHelpers: 'bundled'\n-  })\n--- a/build/rollup.config.js\n+++ b/build/rollup.config.js\n@@ -4 +3,0 @@ const path = require('path')\n-const { babel } = require('@rollup/plugin-babel')\n@@ -15,6 +13,0 @@ const plugins = [\n-  babel({\n-    // Only transpile our source code\n-    exclude: 'node_modules/**',\n-    // Include the helpers in the bundle, at most one copy of each\n-    babelHelpers: 'bundled'\n-  })\n--- a/js/tests/integration/rollup.bundle.js\n+++ b/js/tests/integration/rollup.bundle.js\n@@ -3 +2,0 @@\n-const { babel } = require('@rollup/plugin-babel')\n@@ -18,4 +16,0 @@ module.exports = {\n-    babel({\n-      exclude: 'node_modules/**',\n-      babelHelpers: 'bundled'\n-    })\n--- a/js/tests/karma.conf.js\n+++ b/js/tests/karma.conf.js\n@@ -7,2 +6,0 @@ const ip = require('ip')\n-const { babel } = require('@rollup/plugin-babel')\n-const istanbul = require('rollup-plugin-istanbul')\n@@ -84,13 +81,0 @@ const conf = {\n-      istanbul({\n-        exclude: [\n-          'node_modules/**',\n-          'js/tests/unit/**/*.spec.js',\n-          'js/tests/helpers/**/*.js'\n-        ]\n-      }),\n-      babel({\n-        // Only transpile our source code\n-        exclude: 'node_modules/**',\n-        // Inline the required helpers in each file\n-        babelHelpers: 'inline'\n-      }),\n@@ -142 +126,0 @@ if (BROWSERSTACK) {\n-    'karma-coverage-istanbul-reporter'\n@@ -144 +127,0 @@ if (BROWSERSTACK) {\n-  reporters.push('coverage-istanbul')\n--- a/package.json\n+++ b/package.json\n@@ -23 +23 @@\n-    \"start\": \"npm-run-all --parallel watch docs-serve\",\n+    \"start\": \"npm-run-all --parallel watch\",\n@@ -28,3 +27,0 @@\n-    \"css-lint\": \"npm-run-all --continue-on-error --parallel css-lint-*\",\n-    \"css-lint-stylelint\": \"stylelint \\\"**/*.{css,scss}\\\" --cache --cache-location .cache/.stylelintcache --rd\",\n-    \"css-lint-vars\": \"fusv scss/ site/assets/scss/\",\n@@ -44 +40,0 @@\n-    \"js-lint\": \"eslint --cache --cache-location .cache/.eslintcache --report-unused-disable-directives .\",\n@@ -46,3 +42,3 @@\n-    \"js-minify-standalone\": \"terser --compress passes=2 --mangle --comments \\\"/^!/\\\" --source-map \\\"content=dist/js/bootstrap.js.map,includeSources,url=bootstrap.min.js.map\\\" --output dist/js/bootstrap.min.js dist/js/bootstrap.js\",\n-    \"js-minify-standalone-esm\": \"terser --compress passes=2 --mangle --comments \\\"/^!/\\\" --source-map \\\"content=dist/js/bootstrap.esm.js.map,includeSources,url=bootstrap.esm.min.js.map\\\" --output dist/js/bootstrap.esm.min.js dist/js/bootstrap.esm.js\",\n-    \"js-minify-bundle\": \"terser --compress passes=2 --mangle --comments \\\"/^!/\\\" --source-map \\\"content=dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\\\" --output dist/js/bootstrap.bundle.min.js dist/js/bootstrap.bundle.js\",\n+    \"js-minify-standalone\": \"../../bin/uglifyjs --compress passes=2 --mangle --comments \\\"/^!/\\\" --source-map \\\"content=dist/js/bootstrap.js.map,includeSources,url=bootstrap.min.js.map\\\" --output dist/js/bootstrap.min.js dist/js/bootstrap.js\",\n+    \"js-minify-standalone-esm\": \"../../bin/uglifyjs --compress passes=2 --mangle --comments \\\"/^!/\\\" --source-map \\\"content=dist/js/bootstrap.esm.js.map,includeSources,url=bootstrap.esm.min.js.map\\\" --output dist/js/bootstrap.esm.min.js dist/js/bootstrap.esm.js\",\n+    \"js-minify-bundle\": \"../../bin/uglifyjs --compress passes=2 --mangle --comments \\\"/^!/\\\" --source-map \\\"content=dist/js/bootstrap.bundle.js.map,includeSources,url=bootstrap.bundle.min.js.map\\\" --output dist/js/bootstrap.bundle.min.js dist/js/bootstrap.bundle.js\",\n@@ -56,25 +52 @@\n-    \"lint\": \"npm-run-all --parallel js-lint css-lint lockfile-lint\",\n-    \"docs\": \"npm-run-all docs-build docs-lint\",\n-    \"docs-build\": \"hugo --cleanDestinationDir\",\n-    \"docs-compile\": \"npm run docs-build\",\n-    \"docs-linkinator\": \"linkinator _gh_pages --recurse --silent --skip \\\"^(?!http://localhost)\\\"\",\n-    \"docs-vnu\": \"node build/vnu-jar.js\",\n-    \"docs-lint\": \"npm-run-all --parallel docs-vnu docs-linkinator\",\n-    \"docs-serve\": \"hugo server --port 9001 --disableFastRender\",\n-    \"docs-serve-only\": \"npx sirv-cli _gh_pages --port 9001\",\n-    \"lockfile-lint\": \"lockfile-lint --allowed-hosts npm --allowed-schemes https: --empty-hostname false --type npm --path package-lock.json\",\n-    \"update-deps\": \"ncu -u -x karma-browserstack-launcher,terser && npm update && echo Manually update site/assets/js/vendor\",\n-    \"release\": \"npm-run-all dist release-sri docs-build release-zip*\",\n-    \"release-sri\": \"node build/generate-sri.js\",\n-    \"release-version\": \"node build/change-version.js\",\n-    \"release-zip\": \"cross-env-shell \\\"rm -rf bootstrap-\\$npm_package_version-dist && cp -r dist/ bootstrap-\\$npm_package_version-dist && zip -r9 bootstrap-\\$npm_package_version-dist.zip bootstrap-\\$npm_package_version-dist && rm -rf bootstrap-\\$npm_package_version-dist\\\"\",\n-    \"release-zip-examples\": \"node build/zip-examples.js\",\n-    \"dist\": \"npm-run-all --parallel css js\",\n-    \"test\": \"npm-run-all lint dist js-test docs-build docs-lint\",\n-    \"netlify\": \"cross-env-shell HUGO_BASEURL=\\$DEPLOY_PRIME_URL npm-run-all dist release-sri docs-build\",\n-    \"watch\": \"npm-run-all --parallel watch-*\",\n-    \"watch-css-main\": \"nodemon --watch scss/ --ext scss --exec \\\"npm-run-all css-lint css-compile css-prefix\\\"\",\n-    \"watch-css-dist\": \"nodemon --watch dist/css/ --ext css --ignore \\\"dist/css/*.rtl.*\\\" --exec \\\"npm run css-rtl\\\"\",\n-    \"watch-css-docs\": \"nodemon --watch site/assets/scss/ --ext scss --exec \\\"npm run css-lint\\\"\",\n-    \"watch-js-main\": \"nodemon --watch js/src/ --ext js --exec \\\"npm-run-all js-lint js-compile\\\"\",\n-    \"watch-js-docs\": \"nodemon --watch site/assets/js/ --ext js --exec \\\"npm run js-lint\\\"\"\n+    \"dist\": \"npm run css && npm run js\"\n@@ -103,3 +74,0 @@\n-    \"@babel/cli\": \"^7.12.13\",\n-    \"@babel/core\": \"^7.12.13\",\n-    \"@babel/preset-env\": \"^7.12.13\",\n@@ -107 +75,0 @@\n-    \"@rollup/plugin-babel\": \"^5.2.3\",\n@@ -115,4 +82,0 @@\n-    \"eslint\": \"^7.19.0\",\n-    \"eslint-config-xo\": \"^0.34.0\",\n-    \"eslint-plugin-import\": \"^2.22.1\",\n-    \"eslint-plugin-unicorn\": \"^27.0.0\",\n@@ -122 +85,0 @@\n-    \"hugo-bin\": \"^0.68.0\",\n@@ -128 +90,0 @@\n-    \"karma-coverage-istanbul-reporter\": \"^3.0.3\",\n@@ -134,2 +95,0 @@\n-    \"linkinator\": \"^2.13.4\",\n-    \"lockfile-lint\": \"^4.3.7\",\n@@ -141 +100,0 @@\n-    \"rollup-plugin-istanbul\": \"^3.0.0\",\n@@ -144,5 +103 @@\n-    \"shelljs\": \"^0.8.4\",\n-    \"stylelint\": \"^13.9.0\",\n-    \"stylelint-config-twbs-bootstrap\": \"^2.1.0\",\n-    \"terser\": \"5.1.0\",\n-    \"vnu-jar\": \"21.2.5\"\n+    \"shelljs\": \"^0.8.4\"\n@@ -155,3 +109,0 @@\n-  \"hugo-bin\": {\n-    \"buildTags\": \"extended\"\n-  },\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nrm -rf node_modules \\\n&& npm_install \\\n&& minify_in_situ \"node_modules/@popperjs/core\" \\\n&& rm -rf dist/js/* \\\n&& minify_in_situ \"build\" \\\n&& minify_in_situ \"js\" \\\n&& minify_in_situ \"site\" \\\n&& npm run dist \\\n&& minify_in_situ \"dist\" \\\n&& npm run js-test\n"
  },
  {
    "path": "test/release/buble.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/buble \\\n&& git clone https://github.com/bublejs/buble.git tmp/buble \\\n&& cd tmp/buble \\\n&& rm -rf .git/hooks \\\n&& git checkout dcc5ab02c9af6ddaad94e587c4911677340ec100 \\\n&& patch -l -p1 <<EOF\n--- a/package.json\n+++ b/package.json\n@@ -29 +28,0 @@\n-    \"prepublish\": \"npm test\",\n@@ -67,3 +66 @@\n-    \"source-map-support\": \"^0.5.16\",\n-    \"test262\": \"git+https://github.com/tc39/test262.git#4f1155c566a222238fd86f179c6635ecb4c289bb\",\n-    \"test262-stream\": \"^1.3.0\"\n+    \"source-map-support\": \"^0.5.16\"\n--- a/src/program/BlockStatement.js\n+++ b/src/program/BlockStatement.js\n@@ -309 +309 @@ export default class BlockStatement extends Node {\n-                               let cont = false; // TODO implement proper continue...\n+                               let cont = !declarations; // TODO implement proper continue...\n--- a/src/program/types/VariableDeclaration.js\n+++ b/src/program/types/VariableDeclaration.js\n@@ -38 +38 @@ export default class VariableDeclaration extends Node {\n-                                               code.remove(c, declarator.id.start);\n+                                               code.remove(c, declarator.id.start, lastDeclaratorIsPattern);\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nminify_in_situ \"src\" \\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& rm -rf dist \\\n&& npm run build \\\n&& minify_in_situ \"dist\" \\\n&& node_modules/.bin/mocha\n"
  },
  {
    "path": "test/release/butternut.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/butternut \\\n&& git clone https://github.com/Rich-Harris/butternut.git tmp/butternut \\\n&& cd tmp/butternut \\\n&& rm -rf .git/hooks \\\n&& patch -l -p1 <<EOF\n--- a/package.json\n+++ b/package.json\n@@ -25 +24,0 @@\n-    \"prepublish\": \"npm run test:min\",\n--- a/rollup.config.js\n+++ b/rollup.config.js\n@@ -1 +0,0 @@\n-import buble from 'rollup-plugin-buble';\n@@ -28,6 +26,0 @@ const config = {\n-               buble({\n-                       include: ['src/**', 'node_modules/acorn/**'],\n-                       transforms: {\n-                               dangerousForOf: true\n-                       }\n-               }),\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nminify_in_situ \"src\" \\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& rm -rf dist \\\n&& npm run build \\\n&& minify_in_situ \"dist\" \\\n&& node_modules/.bin/mocha test/test.js\n"
  },
  {
    "path": "test/release/install.sh",
    "content": "echo \"::group::GitHub Environment Variables\"\necho \"CI: $CI\"\necho \"GITHUB_WORKFLOW: $GITHUB_WORKFLOW\"\necho \"GITHUB_RUN_ID: $GITHUB_RUN_ID\"\necho \"GITHUB_RUN_NUMBER: $GITHUB_RUN_NUMBER\"\necho \"GITHUB_ACTION: $GITHUB_ACTION\"\necho \"GITHUB_ACTIONS: $GITHUB_ACTIONS\"\necho \"GITHUB_ACTOR: $GITHUB_ACTOR\"\necho \"GITHUB_REPOSITORY: $GITHUB_REPOSITORY\"\necho \"GITHUB_EVENT_NAME: $GITHUB_EVENT_NAME\"\necho \"GITHUB_EVENT_PATH: $GITHUB_EVENT_PATH\"\necho \"GITHUB_WORKSPACE: $GITHUB_WORKSPACE\"\necho \"GITHUB_SHA: $GITHUB_SHA\"\necho \"GITHUB_REF: $GITHUB_REF\"\necho \"GITHUB_HEAD_REF: $GITHUB_HEAD_REF\"\necho \"GITHUB_BASE_REF: $GITHUB_BASE_REF\"\necho \"GITHUB_SERVER_URL: $GITHUB_SERVER_URL\"\necho \"GITHUB_API_URL: $GITHUB_API_URL\"\necho \"GITHUB_GRAPHQL_URL: $GITHUB_GRAPHQL_URL\"\necho \"::endgroup::\"\n\nif command -v timeout &> /dev/null; then NATIVE=1; fi\ntimeout() {\n    T=$1\n    shift\n    shift\n    shift\n    expect <<EOF\nset timeout $T\nspawn -noecho sh -c \"$@\"\nexpect timeout { exit 124 } eof\ncatch wait ret\nexit [lindex \\$ret 3]\nEOF\n    return $?\n}\nif [ $NATIVE ]; then unset -f timeout; fi\n\nwhile !(git clone --branch v1.6.2 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs); do\n    rm -rf ~/.nvs\ndone\nwhile ! timeout 60 bash -c \". ~/.nvs/nvs.sh add $NODE && nvs use $NODE\"; do\n    cd ~/.nvs\n    while !(git clean -xdf); do echo \"'git clean' failed - retrying...\"; done\n    cd -\ndone\n. ~/.nvs/nvs.sh --version\nnvs use $NODE\nnode --version\nnpm config set audit false\nnpm config set fund false\nnpm config set loglevel error\nnpm config set omit optional || true\nnpm config set optional false || true\nnpm config set save false\nnpm config set strict-ssl false\nnpm config set update-notifier false\nnpm --version\nwhile !(npm install); do\n    while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\ndone\n"
  },
  {
    "path": "test/release/jetstream.js",
    "content": "require(\"./run\")([\n    \"-mc\",\n    \"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto\",\n].map(function(options) {\n    var args = options.split(/ /);\n    args.unshift(\"test/jetstream.js\");\n    args.push(\"-O\", \"webkit\");\n    args.push(\"--no-module\");\n    return args;\n}));\n"
  },
  {
    "path": "test/release/mathjs.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=\"--annotations $@\"\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    for i in `find $DIRS -type f -name '*.mjs'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/mathjs \\\n&& git clone --depth 1 --branch v9.2.0 https://github.com/josdejong/mathjs.git tmp/mathjs \\\n&& cd tmp/mathjs \\\n&& rm -rf .git/hooks \\\n&& patch -l -p1 <<EOF\n--- a/gulpfile.cjs\n+++ b/gulpfile.cjs\n@@ -74 +74 @@ const webpackConfig = {\n-  mode: 'production',\n+  mode: 'development',\n--- a/package.json\n+++ b/package.json\n@@ -132,2 +131,0 @@\n-    \"prepublishOnly\": \"npm run test:all && npm run lint\",\n-    \"prepare\": \"npm run build\",\n--- a/src/utils/string.js\n+++ b/src/utils/string.js\n@@ -15,0 +16,7 @@ export function endsWith (text, search) {\n+export function HACK (value) {\n+  if (typeof value == \"object\") {\n+    (value = Object.create(value)).valueOf = function() { return this }\n+  }\n+  return value\n+}\n+\n@@ -68 +75 @@ export function format (value, options) {\n-      return value.toString()\n+      return HACK(value).toString()\n--- a/test/node-tests/cli/cli.test.js\n+++ b/test/node-tests/cli/cli.test.js\n@@ -36 +35,0 @@ describe('command line interface', function () {\n-    const path2 = path.join(__dirname, 'script2')\n@@ -38,2 +37,2 @@ describe('command line interface', function () {\n-    run('\"' + path1 + '\" \"' + path2 + '\"', function (e, result) {\n-      assert.strictEqual(result, '2\\n8\\n')\n+    run('\"' + path1 + '\"', function (e, result) {\n+      assert.strictEqual(result, '2\\n')\n--- a/test/unit-tests/expression/node/Node.test.js\n+++ b/test/unit-tests/expression/node/Node.test.js\n@@ -157 +157 @@ describe('Node', function () {\n-    assert.throws(function () {\n+    if (0) assert.throws(function () {\n--- a/test/unit-tests/expression/parse.test.js\n+++ b/test/unit-tests/expression/parse.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../src/utils/string.js'\n@@ -333 +334 @@ describe('parse', function () {\n-      assert.strictEqual(fmath.parse('1/3').compile().evaluate().toString(), '0.(3)')\n+      assert.strictEqual(HACK(fmath.parse('1/3').compile().evaluate()).toString(), '0.(3)')\n--- a/test/unit-tests/function/arithmetic/abs.test.js\n+++ b/test/unit-tests/function/arithmetic/abs.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -35,3 +36,3 @@ describe('abs', function () {\n-    assert.strictEqual(abs(a).toString(), '0.(3)')\n-    assert.strictEqual(a.toString(), '-0.(3)')\n-    assert.strictEqual(abs(fraction('1/3')).toString(), '0.(3)')\n+    assert.strictEqual(HACK(abs(a)).toString(), '0.(3)')\n+    assert.strictEqual(HACK(a).toString(), '-0.(3)')\n+    assert.strictEqual(HACK(abs(fraction('1/3'))).toString(), '0.(3)')\n--- a/test/unit-tests/function/arithmetic/addScalar.test.js\n+++ b/test/unit-tests/function/arithmetic/addScalar.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -71 +72 @@ describe('addScalar', function () {\n-    assert.strictEqual(a.toString(), '0.(3)')\n+    assert.strictEqual(HACK(a).toString(), '0.(3)')\n@@ -73 +74 @@ describe('addScalar', function () {\n-    assert.strictEqual(add(math.fraction(1), math.fraction(1, 3)).toString(), '1.(3)')\n+    assert.strictEqual(HACK(add(math.fraction(1), math.fraction(1, 3))).toString(), '1.(3)')\n--- a/test/unit-tests/function/arithmetic/ceil.test.js\n+++ b/test/unit-tests/function/arithmetic/ceil.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -88 +89 @@ describe('ceil', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n@@ -105 +106 @@ describe('ceil', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n@@ -107 +108 @@ describe('ceil', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n--- a/test/unit-tests/function/arithmetic/fix.test.js\n+++ b/test/unit-tests/function/arithmetic/fix.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -107 +108 @@ describe('fix', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n@@ -124 +125 @@ describe('fix', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n@@ -127 +128 @@ describe('fix', function () {\n-    assert.strictEqual(b.toString(), '-0.(6)')\n+    assert.strictEqual(HACK(b).toString(), '-0.(6)')\n--- a/test/unit-tests/function/arithmetic/floor.test.js\n+++ b/test/unit-tests/function/arithmetic/floor.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -96 +97 @@ describe('floor', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n--- a/test/unit-tests/function/arithmetic/gcd.test.js\n+++ b/test/unit-tests/function/arithmetic/gcd.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -62 +63 @@ describe('gcd', function () {\n-    assert.strictEqual(gcd(a, math.fraction(3, 7)).toString(), '0.017(857142)')\n+    assert.strictEqual(HACK(gcd(a, math.fraction(3, 7))).toString(), '0.017(857142)')\n--- a/test/unit-tests/function/arithmetic/multiply.test.js\n+++ b/test/unit-tests/function/arithmetic/multiply.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -129 +130 @@ describe('multiply', function () {\n-      assert.strictEqual(multiply(math.fraction(2), math.fraction(1, 3)).toString(), '0.(6)')\n+      assert.strictEqual(HACK(multiply(math.fraction(2), math.fraction(1, 3))).toString(), '0.(6)')\n--- a/test/unit-tests/function/arithmetic/round.test.js\n+++ b/test/unit-tests/function/arithmetic/round.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -82 +83 @@ describe('round', function () {\n-    assert.strictEqual(a.toString(), '0.(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(6)')\n--- a/test/unit-tests/function/arithmetic/subtract.test.js\n+++ b/test/unit-tests/function/arithmetic/subtract.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -76,2 +77,2 @@ describe('subtract', function () {\n-    assert.strictEqual(subtract(a, math.fraction(1, 6)).toString(), '0.1(6)')\n-    assert.strictEqual(a.toString(), '0.(3)')\n+    assert.strictEqual(HACK(subtract(a, math.fraction(1, 6))).toString(), '0.1(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(3)')\n@@ -80 +81 @@ describe('subtract', function () {\n-    assert.strictEqual(subtract(math.fraction(1), math.fraction(1, 3)).toString(), '0.(6)')\n+    assert.strictEqual(HACK(subtract(math.fraction(1), math.fraction(1, 3))).toString(), '0.(6)')\n--- a/test/unit-tests/function/arithmetic/unaryMinus.test.js\n+++ b/test/unit-tests/function/arithmetic/unaryMinus.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -31 +32 @@ describe('unaryMinus', function () {\n-    assert.deepStrictEqual(math.unaryMinus(bignumber(0)).toString(), '0')\n+    assert.deepStrictEqual(HACK(math.unaryMinus(bignumber(0))).toString(), '0')\n--- a/test/unit-tests/function/relational/compare.test.js\n+++ b/test/unit-tests/function/relational/compare.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -76,2 +77,2 @@ describe('compare', function () {\n-    assert.strictEqual(a.toString(), '0.(3)')\n-    assert.strictEqual(b.toString(), '0.1(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(3)')\n+    assert.strictEqual(HACK(b).toString(), '0.1(6)')\n--- a/test/unit-tests/function/relational/compareNatural.test.js\n+++ b/test/unit-tests/function/relational/compareNatural.test.js\n@@ -0,0 +1 @@\n+import { HACK } from '../../../../src/utils/string.js'\n@@ -57,2 +58,2 @@ describe('compareNatural', function () {\n-    assert.strictEqual(a.toString(), '0.(3)')\n-    assert.strictEqual(b.toString(), '0.1(6)')\n+    assert.strictEqual(HACK(a).toString(), '0.(3)')\n+    assert.strictEqual(HACK(b).toString(), '0.1(6)')\n--- a/test/unit-tests/type/matrix/Matrix.test.js\n+++ b/test/unit-tests/type/matrix/Matrix.test.js\n@@ -44 +44 @@ describe('matrix', function () {\n-      assert.throws(function () { m.toString() }, /Cannot invoke toString on a Matrix interface/)\n+      if (0) assert.throws(function () { m.toString() }, /Cannot invoke toString on a Matrix interface/)\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nminify_in_situ \"bin\" \\\n&& minify_in_situ \"src\" \\\n&& minify_in_situ \"test\" \\\n&& minify_in_situ \"tools\" \\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& rm -rf lib \\\n&& npm run build \\\n&& minify_in_situ \"lib\" \\\n&& npm run test:all\n"
  },
  {
    "path": "test/release/rollup-es.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/rollup \\\n&& git clone https://github.com/rollup/rollup.git tmp/rollup \\\n&& cd tmp/rollup \\\n&& rm -rf .git/hooks \\\n&& git checkout 3d80c06f895eab41e648ee99786fa68c72458b80 \\\n&& patch -l -p1 <<EOF\n--- a/package.json\n+++ b/package.json\n@@ -23 +22,0 @@\n-    \"prepublishOnly\": \"npm run lint && npm run test:only && npm run test:leak\",\n--- a/rollup.config.js\n+++ b/rollup.config.js\n@@ -1,5 +1,4 @@\n import { readFileSync } from 'fs';\n-import buble from 'rollup-plugin-buble';\n import resolve from 'rollup-plugin-node-resolve';\n import commonjs from 'rollup-plugin-commonjs';\n import json from 'rollup-plugin-json';\n@@ -25,12 +24,6 @@ export default [\n         input: 'src/node-entry.js',\n         plugins: [\n             json(),\n-            buble({\n-                include: ['src/**', 'node_modules/acorn/**'],\n-                target: {\n-                    node: '4'\n-                }\n-            }),\n             resolve(),\n             commonjs()\n         ],\n@@ -48,12 +41,6 @@ export default [\n         input: 'src/browser-entry.js',\n         plugins: [\n             json(),\n-            buble({\n-                include: ['src/**', 'node_modules/acorn/**'],\n-                target: {\n-                    node: '4'\n-                }\n-            }),\n             resolve(),\n             commonjs(),\n             {\n@@ -80,7 +67,6 @@ export default [\n         plugins: [\n             string({ include: '**/*.md' }),\n             json(),\n-            buble({ target: { node: 4 } }),\n             commonjs({\n                 include: 'node_modules/**'\n             }),\n--- a/test/mocha.opts\n+++ b/test/mocha.opts\n@@ -1,2 +1 @@\n---require buble/register\n test/test.js\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nminify_in_situ \"bin\" \\\n&& minify_in_situ \"browser\" \\\n&& minify_in_situ \"src\" \\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& rm -rf dist \\\n&& npm run build \\\n&& minify_in_situ \"dist\" \\\n&& node_modules/.bin/mocha\n"
  },
  {
    "path": "test/release/rollup-ts.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> esbuild' $DIRS\n    for i in `find $DIRS -type f -name '*.ts' | grep -v '\\.d\\.ts'`\n    do\n        echo \"$i\"\n        CODE=`cat \"$i\"`\n        node_modules/.bin/esbuild --loader=ts --target=esnext > \"$i\" <<EOF\n$CODE\nEOF\n        ARGS=\"$ARGS $i\"\n    done\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/rollup \\\n&& git clone --depth 1 --branch v2.39.1 https://github.com/rollup/rollup.git tmp/rollup \\\n&& cd tmp/rollup \\\n&& rm -rf .git/hooks \\\n&& patch -l -p1 <<EOF\n--- a/package.json\n+++ b/package.json\n@@ -27,4 +26,0 @@\n-    \"postinstall\": \"husky install\",\n-    \"postpublish\": \"pinst --enable\",\n-    \"prepare\": \"npm run build\",\n-    \"prepublishOnly\": \"pinst --disable && npm ci && npm run lint:nofix && npm run security && npm run build:bootstrap && npm run test:all\",\n@@ -93 +89 @@\n-    \"is-reference\": \"lukastaegert/is-reference#update-class-features\",\n+    \"is-reference\": \"3.0.0\",\n--- a/test/cli/index.js\n+++ b/test/cli/index.js\n@@ -13,0 +14,3 @@ sander.rimrafSync(__dirname, 'node_modules');\n+sander.rimrafSync(__dirname, 'samples', 'watch', 'bundle-error');\n+sander.rimrafSync(__dirname, 'samples', 'watch', 'watch-config-error');\n+sander.rimrafSync(__dirname, 'samples', 'watch', 'watch-config-initial-error');\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nnpm_install esbuild-wasm@0.8.56 \\\n&& minify_in_situ \"cli\" \\\n&& minify_in_situ \"src\" \\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& rm -rf dist \\\n&& npm run build \\\n&& minify_in_situ \"dist\" \\\n&& node_modules/.bin/mocha test/test.js \\\n&& node_modules/.bin/mocha test/browser/index.js\n"
  },
  {
    "path": "test/release/run.js",
    "content": "var child_process = require(\"child_process\");\n\nmodule.exports = function(tasks) {\n    (function next() {\n        if (!tasks.length) return;\n        var args = tasks.shift();\n        console.log();\n        console.log(\"\\u001B[36m$> \" + args.join(\" \") + \"\\u001B[39m\");\n        child_process.spawn(process.argv[0], args, {\n            stdio: [ \"ignore\", 1, 2 ]\n        }).on(\"exit\", function(code) {\n            if (code) process.exit(code);\n            next();\n        });\n    })();\n};\n"
  },
  {
    "path": "test/release/sucrase.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=$PWD/bin/uglifyjs\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> esbuild' $DIRS\n    for i in `find $DIRS -type f -name '*.ts' | grep -v '\\.d\\.ts'`\n    do\n        echo \"$i\"\n        CODE=`cat \"$i\"`\n        node_modules/.bin/esbuild --loader=ts --target=esnext > \"$i\" <<EOF\n$CODE\nEOF\n        ARGS=\"$ARGS $i\"\n    done\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    for i in `find $DIRS -type f -name '*.mjs'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nworkaround() {\n    FILE=\"$1\"\n    echo 'Monkey patching' $FILE\n    CODE=`cat $FILE`\n    sed -E 's/for ?\\((var [^;{]+;)/\\1for\\(;/g' > $FILE <<EOF\n$CODE\nEOF\n}\n\nrm -rf tmp/sucrase \\\n&& git clone https://github.com/alangpierce/sucrase.git tmp/sucrase \\\n&& cd tmp/sucrase \\\n&& rm -rf .git/hooks \\\n&& git checkout 7284b3733aa114b3f4f5371e36ff5a4704ec860e \\\n&& patch -l -p1 <<EOF\n--- a/package.json\n+++ b/package.json\n@@ -25 +24,0 @@\n-    \"prepublishOnly\": \"yarn clean && yarn build\",\n@@ -69 +67,0 @@\n-    \"test262-harness\": \"^10.0.0\",\n--- a/script/build.ts\n+++ b/script/build.ts\n@@ -16 +15,0 @@ async function main(): Promise<void> {\n-    () => buildBenchmark(),\n@@ -18,5 +16,0 @@ async function main(): Promise<void> {\n-    () => buildIntegration(\"./integrations/gulp-plugin\"),\n-    () => buildIntegration(\"./integrations/jest-plugin\"),\n-    () => buildIntegration(\"./integrations/webpack-loader\"),\n-    () => buildIntegration(\"./integrations/webpack-object-rest-spread-plugin\"),\n-    () => buildWebsite(),\n@@ -62,3 +55,0 @@ async function buildSucrase(): Promise<void> {\n-    // Also add in .d.ts files from tsc, which only need to be compiled once.\n-    await run(\\`\\${TSC} --project ./src --outDir ./dist-types\\`);\n-    await mergeDirectoryContents(\"./dist-types/src\", \"./dist/types\");\n@@ -66 +57 @@ async function buildSucrase(): Promise<void> {\n-    await run(\"yarn link\");\n+    await run(\"npm link\");\n--- a/src/identifyShadowedGlobals.ts\n+++ b/src/identifyShadowedGlobals.ts\n@@ -23,0 +24 @@ export default function identifyShadowedGlobals(\n+export { identifyShadowedGlobals as HACK };\n--- a/src/parser/tokenizer/state.ts\n+++ b/src/parser/tokenizer/state.ts\n@@ -106,0 +107 @@ export default class State {\n+export { State as HACK };\n--- a/src/transformers/JSXTransformer.ts\n+++ b/src/transformers/JSXTransformer.ts\n@@ -560,0 +561 @@ export default class JSXTransformer extends Transformer {\n+export { JSXTransformer as HACK };\n--- a/src/util/getClassInfo.ts\n+++ b/src/util/getClassInfo.ts\n@@ -195,0 +196 @@ export default function getClassInfo(\n+export { getClassInfo as HACK };\n--- a/src/util/getDeclarationInfo.ts\n+++ b/src/util/getDeclarationInfo.ts\n@@ -40,0 +41 @@ export default function getDeclarationInfo(tokens: TokenProcessor): DeclarationI\n+export { getDeclarationInfo as HACK };\n--- a/src/util/getImportExportSpecifierInfo.ts\n+++ b/src/util/getImportExportSpecifierInfo.ts\n@@ -87,0 +88 @@ export default function getImportExportSpecifierInfo(\n+export { getImportExportSpecifierInfo as HACK };\n--- a/src/util/getJSXPragmaInfo.ts\n+++ b/src/util/getJSXPragmaInfo.ts\n@@ -14,0 +15 @@ export default function getJSXPragmaInfo(options: Options): JSXPragmaInfo {\n+export { getJSXPragmaInfo as HACK };\n--- a/test/source-maps-test.ts\n+++ b/test/source-maps-test.ts\n@@ -26,0 +27 @@ var _a = require('./a'); var _a2 = _interopRequireDefault(_a);\n+delete result.sourceMap.ignoreList;\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nnpm_install esbuild-wasm@0.8.56 \\\n&& minify_in_situ \"src\" \\\n&& workaround src/parser/plugins/typescript.ts\\\n&& workaround src/transformers/CJSImportTransformer.ts\\\n&& rm -rf node_modules \\\n&& npm_install \\\n&& npm run clean \\\n&& npm run build \\\n&& minify_in_situ \"dist\" \\\n&& minify_in_situ \"dist-self-build\" \\\n&& npm run test-only\n"
  },
  {
    "path": "test/release/web-tooling-benchmark.sh",
    "content": "#!/bin/sh\n\nalias uglify-js=\"node --max-old-space-size=8192 $PWD/bin/uglifyjs\"\nUGLIFY_OPTIONS=$@\n\nminify_in_situ() {\n    ARGS=\"$UGLIFY_OPTIONS --validate --in-situ\"\n    DIRS=\"$1\"\n    echo '> uglify-js' $DIRS $UGLIFY_OPTIONS\n    for i in `find $DIRS -type f -name '*.js'`\n    do\n        ARGS=\"$ARGS $i\"\n    done\n    uglify-js $ARGS\n}\n\nnpm_install() {\n    PKG=\"$1\"\n    while !(npm install $PKG); do\n        while !(npm cache clean --force); do echo \"'npm cache clean' failed - retrying...\"; done\n    done\n}\n\nrm -rf tmp/web-tooling-benchmark \\\n&& git clone --depth 1 --branch v0.5.3 https://github.com/v8/web-tooling-benchmark.git tmp/web-tooling-benchmark \\\n&& cd tmp/web-tooling-benchmark \\\n&& rm -rf .git/hooks \\\n&& patch -l -p1 <<EOF\n--- a/package.json\n+++ b/package.json\n@@ -12 +11,0 @@\n-    \"postinstall\": \"npm run build:terser-bundled && npm run build:uglify-js-bundled && npm run build\",\n--- a/src/bootstrap.js\n+++ b/src/bootstrap.js\n@@ -6 +6 @@ const gmean = require(\"compute-gmean\");\n-const package = require(\"../package.json\");\n+const package_json = require(\"../package.json\");\n@@ -65 +65 @@ function initialize() {\n-  document.title = \\`Web Tooling Benchmark v\\${package.version}\\`;\n+  document.title = \\`Web Tooling Benchmark v\\${package_json.version}\\`;\n@@ -68 +68 @@ function initialize() {\n-  versionDiv.innerHTML = \\`v\\${package.version}\\`;\n+  versionDiv.innerHTML = \\`v\\${package_json.version}\\`;\n--- a/src/cli-flags-helper.js\n+++ b/src/cli-flags-helper.js\n@@ -7 +6,0 @@ const targetList = new Set([\n-  \"chai\",\n--- a/src/cli.js\n+++ b/src/cli.js\n@@ -18,0 +19 @@ suite.on(\"error\", event => {\n+  global.process.exitCode = 42;\nEOF\nERR=$?; if [ \"$ERR\" != \"0\" ]; then echo \"Error: $ERR\"; exit $ERR; fi\nminify_in_situ \"src\" \\\n&& minify_in_situ \"third_party\" \\\n&& rm -rf node_modules \\\n&& npm_install --package-lock \\\n&& rm -rf build/* \\\n&& npm run build:terser-bundled \\\n&& npm run build:uglify-js-bundled \\\n&& minify_in_situ \"build\" \\\n&& rm -rf dist \\\n&& npm run build \\\n&& minify_in_situ \"dist\" \\\n&& node dist/cli.js\n"
  },
  {
    "path": "test/sandbox.js",
    "content": "var readFileSync = require(\"fs\").readFileSync;\nvar semver = require(\"semver\");\nvar spawnSync = require(\"child_process\").spawnSync;\nvar vm = require(\"vm\");\n\nsetup_log();\nvar setup_code = \"(\" + setup + \")(\" + [\n    \"this\",\n    find_builtins(),\n    setup_log,\n    \"function(process) {\" + readFileSync(require.resolve(\"../tools/tty\", \"utf8\")) + \"}\",\n].join(\",\\n\") + \");\\n\";\nexports.has_toplevel = function(options) {\n    return options.toplevel\n        || options.mangle && options.mangle.toplevel\n        || options.compress && options.compress.toplevel;\n};\nexports.is_error = is_error;\nexports.run_code = semver.satisfies(process.version, \"0.8\") ? function(code, toplevel, timeout) {\n    var stdout = run_code_vm(code, toplevel, timeout);\n    if (typeof stdout != \"string\" || !/arguments/.test(code)) return stdout;\n    do {\n        var prev = stdout;\n        stdout = run_code_vm(code, toplevel, timeout);\n    } while (prev !== stdout);\n    return stdout;\n} : semver.satisfies(process.version, \"<0.12\") ? run_code_vm : function(code, toplevel, timeout) {\n    var stdout = ([\n        /\\b(async[ \\t]+function|Promise|setImmediate|setInterval|setTimeout)\\b/,\n        /\\basync([ \\t]+|[ \\t]*#)[^\\s()[\\]{}#:;,.&|!~=*%/+-]+(\\s*\\(|[ \\t]*=>)/,\n        /\\basync[ \\t]*\\*[ \\t]*[^\\s()[\\]{}#:;,.&|!~=*%/+-]+\\s*\\(/,\n        /\\basync([ \\t]*\\*)?[ \\t]*\\[[\\s\\S]*?\\]\\s*\\(/,\n        /\\basync[ \\t]*\\([\\s\\S]*?\\)[ \\t]*=>/,\n    ].some(function(pattern) {\n        return pattern.test(code);\n    }) ? run_code_exec : run_code_vm)(code, toplevel, timeout);\n    var len = typeof stdout == \"string\" && stdout.length;\n    return len > 1000 ? stdout.slice(0, 1000) + \"…《\" + len + \"》\" : stdout;\n};\nexports.same_stdout = semver.satisfies(process.version, \"0.12\") ? function(expected, actual) {\n    if (typeof expected != typeof actual) return false;\n    if (is_error(expected)) {\n        if (expected.name !== actual.name) return false;\n        if (typeof actual.message != \"string\") return false;\n        expected = expected.message.slice(expected.message.lastIndexOf(\"\\n\") + 1);\n        actual = actual.message.slice(actual.message.lastIndexOf(\"\\n\") + 1);\n    }\n    return strip_func_ids(expected) == strip_func_ids(actual);\n} : function(expected, actual) {\n    return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);\n};\nexports.patch_module_statements = function(code, module) {\n    if (module || module === undefined && /\\bawait\\b/.test(code)) {\n        code = [\n            \"(async()=>{\",\n            code,\n            '})().catch(e=>process.on(\"exit\",()=>{throw e}));',\n        ];\n        if (module) code.unshift('\"use strict\";');\n        code = code.join(\"\\n\");\n    }\n    var count = 0, has_default = \"\", imports = [], strict_mode = \"\";\n    code = code.replace(/^\\s*(\"|')use strict\\1\\s*;?/, function(match) {\n        strict_mode = match;\n        return \"\";\n    }).replace(/\\bexport(?:\\s*\\{[^{}]*}\\s*?(?:$|\\n|;)|\\s+default\\b(?:\\s*(\\(|\\{|class\\s*\\{|class\\s+(?=extends\\b)|(?:async\\s+)?function\\s*(?:\\*\\s*)?\\())?|\\b)/g, function(match, header) {\n        if (/^export\\s+default/.test(match)) has_default = \"function _uglify_export_default_() {}\";\n        if (!header) return \";\";\n        if (header.length == 1) return \"0, \" + header;\n        var name = \"_uglify_export_default_\";\n        if (/^class\\b/.test(header)) do {\n            name = \"_uglify_export_default_\" + ++count;\n        } while (code.indexOf(name) >= 0);\n        return header.slice(0, -1) + \" \" + name + header.slice(-1);\n    }).replace(/\\bimport\\.meta\\b/g, function() {\n        return 'Object.create({ url: \"https://example.com/path/index.html\" })';\n    }).replace(/\\bimport\\b(?:\\s*([^\\s('\"][^('\"]*)\\bfrom\\b)?\\s*(['\"]).*?\\2(?:$|\\n|;)/g, function(match, symbols) {\n        if (symbols) {\n            if (!/^[{*]/.test(symbols)) symbols = \"default:\" + symbols;\n            symbols = symbols.replace(/[{}]/g, \"\").trim().replace(/\\s*,\\s*/g, \",\");\n            symbols = symbols.replace(/\\*/, '\"*\"').replace(/\\bas\\s+(?!$|,|as\\s)/g, \":\");\n            imports.push([\n                \"const {\",\n                symbols,\n                \"} = new Proxy(Object.create(null), { get(_, value) { return { value }; } });\",\n            ].join(\"\"));\n        }\n        return \";\";\n    });\n    imports.push(\"\");\n    return strict_mode + has_default + imports.join(\"\\n\") + code;\n};\n\nfunction is_error(result) {\n    return result && typeof result.name == \"string\" && typeof result.message == \"string\";\n}\n\nfunction strip_color_codes(value) {\n    return value.replace(/\\u001b\\[\\d+m/g, \"\");\n}\n\nfunction strip_func_ids(text) {\n    return (\"\" + text).replace(/F[0-9]{6}N/g, \"<F<>N>\");\n}\n\nfunction setup_log() {\n    var inspect = require(\"util\").inspect;\n    if (inspect.defaultOptions) {\n        var log_options = {\n            breakLength: Infinity,\n            colors: false,\n            compact: true,\n            customInspect: false,\n            depth: Infinity,\n            maxArrayLength: Infinity,\n            maxStringLength: Infinity,\n            showHidden: false,\n        };\n        for (var name in log_options) {\n            if (name in inspect.defaultOptions) inspect.defaultOptions[name] = log_options[name];\n        }\n    }\n    return inspect;\n}\n\nfunction find_builtins() {\n    setup_code = \"console.log(Object.keys(this));\";\n    var builtins = run_code_vm(\"\");\n    if (semver.satisfies(process.version, \">=0.12\")) builtins += \".concat(\" + run_code_exec(\"\") + \")\";\n    return builtins;\n}\n\nfunction setup(global, builtins, setup_log, setup_tty) {\n    [ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(f) {\n        f.toString = Function.prototype.toString;\n    });\n    Function.prototype.toString = function() {\n        var configurable = Object.getOwnPropertyDescriptor(Function.prototype, \"name\").configurable;\n        var id = 100000;\n        return function() {\n            var n = this.name;\n            if (!/^F[0-9]{6}N$/.test(n)) {\n                n = \"F\" + ++id + \"N\";\n                if (configurable) Object.defineProperty(this, \"name\", {\n                    get: function() {\n                        return n;\n                    }\n                });\n            }\n            return \"function(){}\";\n        };\n    }();\n    var process = global.process;\n    if (process) {\n        setup_tty(process);\n        var inspect = setup_log();\n        process.on(\"uncaughtException\", function(ex) {\n            var value = ex;\n            if (value instanceof Error) {\n                value = {};\n                for (var name in ex) {\n                    value[name] = ex[name];\n                    delete ex[name];\n                }\n            }\n            var marker = \"\\n\\n-----===== UNCAUGHT EXCEPTION =====-----\\n\\n\";\n            process.stderr.write(marker + inspect(value) + marker);\n            throw ex;\n        }).on(\"unhandledRejection\", function() {});\n    }\n    var log = console.log;\n    var safe_console = {\n        log: function(msg) {\n            if (arguments.length == 1 && typeof msg == \"string\") return log(\"%s\", msg);\n            return log.apply(null, [].map.call(arguments, function(arg) {\n                return safe_log(arg, {\n                    level: 5,\n                    original: [],\n                    replaced: [],\n                });\n            }));\n        },\n    };\n    var props = {\n        // for Node.js v8\n        console: {\n            get: function() {\n                return safe_console;\n            },\n        },\n        global: { get: self },\n        self: { get: self },\n        window: { get: self },\n    };\n    [\n        // for Node.js v0.12\n        \"Buffer\",\n        \"clearImmediate\",\n        \"clearInterval\",\n        \"clearTimeout\",\n        // for Node.js v0.12\n        \"DTRACE_NET_STREAM_END\",\n        // for Node.js v8\n        \"process\",\n        \"setImmediate\",\n        \"setInterval\",\n        \"setTimeout\",\n    ].forEach(function(name) {\n        var value = global[name];\n        props[name] = {\n            get: function() {\n                return value;\n            },\n        };\n    });\n    builtins.forEach(function(name) {\n        try {\n            delete global[name];\n        } catch (e) {}\n    });\n    Object.defineProperties(global, props);\n    // for Node.js v8+\n    global.__proto__ = Object.defineProperty(Object.create(global.__proto__), \"toString\", {\n        value: function() {\n            return \"[object global]\";\n        },\n    });\n\n    function self() {\n        return this;\n    }\n\n    function safe_log(arg, cache) {\n        if (arg) switch (typeof arg) {\n          case \"function\":\n            return arg.toString();\n          case \"object\":\n            if (arg === global) return \"[object global]\";\n            if (/Error$/.test(arg.name)) return arg.toString();\n            if (typeof arg.then == \"function\") return \"[object Promise]\";\n            if (arg.constructor) arg.constructor.toString();\n            var index = cache.original.indexOf(arg);\n            if (index >= 0) return cache.replaced[index];\n            if (--cache.level < 0) return \"[object Object]\";\n            var value = {};\n            cache.original.push(arg);\n            cache.replaced.push(value);\n            for (var key in arg) {\n                var desc = Object.getOwnPropertyDescriptor(arg, key);\n                if (desc && (desc.get || desc.set)) {\n                    Object.defineProperty(value, key, desc);\n                } else {\n                    value[key] = safe_log(arg[key], cache);\n                }\n            }\n            return value;\n        }\n        return arg;\n    }\n}\n\nfunction run_code_vm(code, toplevel, timeout) {\n    timeout = timeout || 5000;\n    var stdout = \"\";\n    var original_write = process.stdout.write;\n    process.stdout.write = function(chunk) {\n        stdout += chunk;\n    };\n    try {\n        var ctx = vm.createContext({ console: console });\n        // for Node.js v6\n        vm.runInContext(setup_code, ctx);\n        vm.runInContext(toplevel ? \"(function(){\\n\" + code + \"\\n})();\" : code, ctx, { timeout: timeout });\n        // for Node.js v4\n        return strip_color_codes(stdout.replace(/\\b(Array \\[|Object {)/g, function(match) {\n            return match.slice(-1);\n        }));\n    } catch (ex) {\n        return ex;\n    } finally {\n        process.stdout.write = original_write;\n    }\n}\n\nfunction run_code_exec(code, toplevel, timeout) {\n    if (toplevel) {\n        code = setup_code + \"(function(){\\n\" + code + \"\\n})();\";\n    } else {\n        code = code.replace(/^(([\"'])[^\"']*\\2(;|$))?/, function(directive) {\n            return directive + setup_code;\n        });\n    }\n    var result = spawnSync(process.argv[0], [ '--max-old-space-size=2048' ], {\n        encoding: \"utf8\",\n        input: code,\n        maxBuffer: 1073741824,\n        stdio: \"pipe\",\n        timeout: timeout || 5000,\n    });\n    if (result.status === 0) return result.stdout;\n    var msg = (\"\" + result.stderr).replace(/\\r\\n/g, \"\\n\");\n    if (result.error && result.error.code == \"ETIMEDOUT\" || /FATAL ERROR:/.test(msg)) {\n        return new Error(\"Script execution timed out.\");\n    }\n    if (result.error) return result.error;\n    var match = /\\n([^:\\s]*Error)(?:: ([\\s\\S]+?))?\\n(    at [\\s\\S]+)\\n$/.exec(msg);\n    var marker = \"\\n\\n-----===== UNCAUGHT EXCEPTION =====-----\\n\\n\";\n    var start = msg.indexOf(marker) + marker.length;\n    var end = msg.indexOf(marker, start);\n    var details;\n    if (end >= 0) {\n        details = msg.slice(start, end).replace(/<([1-9][0-9]*) empty items?>/g, function(match, count) {\n            return new Array(+count).join();\n        });\n        try {\n            details = vm.runInNewContext(\"(\" + details + \")\");\n        } catch (e) {}\n    } else if (!match) {\n        return new Error(\"Script execution aborted.\");\n    }\n    if (!match) return details;\n    var ex = new global[match[1]](match[2]);\n    ex.stack = ex.stack.slice(0, ex.stack.indexOf(\"    at \")) + match[3];\n    if (typeof details == \"object\") {\n        for (var name in details) ex[name] = details[name];\n    } else if (end >= 0) {\n        ex.details = details;\n    }\n    return ex;\n}\n"
  },
  {
    "path": "test/ufuzz/actions.js",
    "content": "var get = require(\"https\").get;\nvar parse = require(\"url\").parse;\n\nvar base, token, run_number;\nvar expires = Date.now() + (6 * 60 - 10) * 60 * 1000;\nexports.init = function(url, auth, num) {\n    base = url;\n    token = auth;\n    run_number = num;\n};\nexports.should_stop = function(callback) {\n    if (Date.now() > expires) return callback();\n    read(base + \"/actions/runs?per_page=100\", function(reply) {\n        var runs = verify(reply, \"workflow_runs\").filter(function(workflow) {\n            return workflow.status != \"completed\";\n        }).sort(function(a, b) {\n            return b.run_number - a.run_number;\n        });\n        var found = false, remaining = 20;\n        (function next() {\n            var workflow;\n            do {\n                workflow = runs.pop();\n                if (!workflow) return;\n                if (!is_cron(workflow)) break;\n                if (workflow.run_number == run_number) found = true;\n            } while (!found);\n            read(workflow.jobs_url, function(reply) {\n                verify(reply, \"jobs\").forEach(function(job) {\n                    if (job.status != \"completed\") remaining--;\n                });\n                if (remaining >= 0) {\n                    next();\n                } else {\n                    callback();\n                }\n            });\n        })();\n    });\n};\n\nfunction is_cron(workflow) {\n    return /^(schedule|workflow_dispatch|workflow_run)$/.test(workflow.event);\n}\n\nfunction read(url, callback) {\n    var done = function(reply) {\n        done = function() {};\n        callback(reply);\n    };\n    var options = parse(url);\n    options.headers = {\n        \"Authorization\": \"Token \" + token,\n        \"User-Agent\": \"UglifyJS\",\n    };\n    get(options, function(response) {\n        var chunks = [];\n        response.setEncoding(\"utf8\");\n        response.on(\"data\", function(chunk) {\n            chunks.push(chunk);\n        }).on(\"end\", function() {\n            var reply;\n            try {\n                reply = JSON.parse(chunks.join(\"\"));\n            } catch (e) {}\n            done(reply);\n        }).on(\"error\", function() {\n            done();\n        });\n    }).on(\"error\", function() {\n        done();\n    });\n}\n\nfunction verify(reply, field) {\n    if (!reply) return [];\n    var values = reply[field];\n    if (!Array.isArray(values)) return [];\n    return values.filter(function(value) {\n        return value;\n    });\n}\n"
  },
  {
    "path": "test/ufuzz/index.js",
    "content": "// derived from https://github.com/qfox/uglyfuzzer by Peter van der Zee\n\"use strict\";\n\n// check both CLI and file modes of nodejs (!). See #1695 for details. and the various settings of uglify.\n// bin/uglifyjs s.js -c && bin/uglifyjs s.js -c passes=3 && bin/uglifyjs s.js -c passes=3 -m\n// cat s.js | node && node s.js && bin/uglifyjs s.js -c | node && bin/uglifyjs s.js -c passes=3 | node && bin/uglifyjs s.js -c passes=3 -m | node\n\nrequire(\"../../tools/tty\");\n\nvar UglifyJS = require(\"../..\");\nvar randomBytes = require(\"crypto\").randomBytes;\nvar sandbox = require(\"../sandbox\");\nvar reduce_test = require(\"../reduce\");\n\nvar MAX_GENERATED_TOPLEVELS_PER_RUN = 1;\nvar MAX_GENERATION_RECURSION_DEPTH = 12;\nvar INTERVAL_COUNT = 100;\n\nvar STMT_ARG_TO_ID = Object.create(null);\nvar STMTS_TO_USE = [];\nfunction STMT_(name) {\n    return STMT_ARG_TO_ID[name] = STMTS_TO_USE.push(STMTS_TO_USE.length) - 1;\n}\n\nvar STMT_BLOCK = STMT_(\"block\");\nvar STMT_IF_ELSE = STMT_(\"ifelse\");\nvar STMT_DO_WHILE = STMT_(\"dowhile\");\nvar STMT_WHILE = STMT_(\"while\");\nvar STMT_FOR_LOOP = STMT_(\"forloop\");\nvar STMT_FOR_ENUM = STMT_(\"forenum\");\nvar STMT_SEMI = STMT_(\"semi\");\nvar STMT_EXPR = STMT_(\"expr\");\nvar STMT_SWITCH = STMT_(\"switch\");\nvar STMT_VAR = STMT_(\"var\");\nvar STMT_RETURN_ETC = STMT_(\"stop\");\nvar STMT_FUNC_EXPR = STMT_(\"funcexpr\");\nvar STMT_TRY = STMT_(\"try\");\nvar STMT_C = STMT_(\"c\");\n\nvar STMT_FIRST_LEVEL_OVERRIDE = -1;\nvar STMT_SECOND_LEVEL_OVERRIDE = -1;\nvar STMT_COUNT_FROM_GLOBAL = true; // count statement depth from nearest function scope or just global scope?\n\nvar num_iterations = +process.argv[2] || 1/0;\nvar verbose = false; // log every generated test\nvar verbose_interval = false; // log every 100 generated tests\nvar use_strict = false;\nvar catch_redef = require.main === module;\nvar generate_directive = require.main === module;\nfor (var i = 2; i < process.argv.length; ++i) {\n    switch (process.argv[i]) {\n      case \"-v\":\n        verbose = true;\n        break;\n      case \"-V\":\n        verbose_interval = true;\n        break;\n      case \"-t\":\n        MAX_GENERATED_TOPLEVELS_PER_RUN = +process.argv[++i];\n        if (!MAX_GENERATED_TOPLEVELS_PER_RUN) throw new Error(\"Must generate at least one toplevel per run\");\n        break;\n      case \"-r\":\n        MAX_GENERATION_RECURSION_DEPTH = +process.argv[++i];\n        if (!MAX_GENERATION_RECURSION_DEPTH) throw new Error(\"Recursion depth must be at least 1\");\n        break;\n      case \"-s1\":\n        var name = process.argv[++i];\n        STMT_FIRST_LEVEL_OVERRIDE = STMT_ARG_TO_ID[name];\n        if (!(STMT_FIRST_LEVEL_OVERRIDE >= 0)) throw new Error(\"Unknown statement name; use -? to get a list\");\n        break;\n      case \"-s2\":\n        var name = process.argv[++i];\n        STMT_SECOND_LEVEL_OVERRIDE = STMT_ARG_TO_ID[name];\n        if (!(STMT_SECOND_LEVEL_OVERRIDE >= 0)) throw new Error(\"Unknown statement name; use -? to get a list\");\n        break;\n      case \"--no-catch-redef\":\n        catch_redef = false;\n        break;\n      case \"--no-directive\":\n        generate_directive = false;\n        break;\n      case \"--use-strict\":\n        use_strict = true;\n        break;\n      case \"--stmt-depth-from-func\":\n        STMT_COUNT_FROM_GLOBAL = false;\n        break;\n      case \"--only-stmt\":\n        STMTS_TO_USE = process.argv[++i].split(\",\").map(function(name) {\n          return STMT_ARG_TO_ID[name];\n        });\n        break;\n      case \"--without-stmt\":\n        // meh. it runs once it's fine.\n        process.argv[++i].split(\",\").forEach(function(name) {\n            var omit = STMT_ARG_TO_ID[name];\n            STMTS_TO_USE = STMTS_TO_USE.filter(function(id) {\n              return id !== omit;\n            });\n        });\n        break;\n      case \"--help\":\n      case \"-h\":\n      case \"-?\":\n        println(\"** UglifyJS fuzzer help **\");\n        println(\"Valid options (optional):\");\n        println(\"<number>: generate this many cases (if used must be first arg)\");\n        println(\"-v: print every generated test case\");\n        println(\"-V: print every 100th generated test case\");\n        println(\"-t <int>: generate this many toplevels per run (more take longer)\");\n        println(\"-r <int>: maximum recursion depth for generator (higher takes longer)\");\n        println(\"-s1 <statement name>: force the first level statement to be this one (see list below)\");\n        println(\"-s2 <statement name>: force the second level statement to be this one (see list below)\");\n        println(\"--no-catch-redef: do not redefine catch variables\");\n        println(\"--no-directive: do not generate directives\");\n        println('--use-strict: generate \"use strict\"');\n        println(\"--stmt-depth-from-func: reset statement depth counter at each function, counts from global otherwise\");\n        println(\"--only-stmt <statement names>: a comma delimited white list of statements that may be generated\");\n        println(\"--without-stmt <statement names>: a comma delimited black list of statements never to generate\");\n        println(\"List of accepted statement names: \" + Object.keys(STMT_ARG_TO_ID));\n        println(\"** UglifyJS fuzzer exiting **\");\n        return 0;\n      default:\n        // first arg may be a number.\n        if (i > 2 || !parseInt(process.argv[i], 10)) throw new Error(\"Unknown argument[\" + process.argv[i] + \"]; see -h for help\");\n    }\n}\n\nvar SUPPORT = function(matrix) {\n    for (var name in matrix) {\n        matrix[name] = !sandbox.is_error(sandbox.run_code(matrix[name]));\n    }\n    return matrix;\n}({\n    arrow: \"a => 0;\",\n    async: \"async function f(){}\",\n    async_generator: \"async function* f(){}\",\n    bigint: \"42n\",\n    catch_omit_var: \"try {} catch {}\",\n    class: \"class C { f() {} }\",\n    class_field: \"class C { p = 0; }\",\n    class_private: \"class C { #f() {} }\",\n    class_static_init: \"class C { static {} }\",\n    computed_key: \"({[0]: 0});\",\n    const_block: \"var a; { const a = 0; }\",\n    default_value: \"[ a = 0 ] = [];\",\n    destructuring: \"[] = [];\",\n    exponentiation: \"0 ** 0\",\n    for_await_of: \"async function f(a) { for await (a of []); }\",\n    for_of: \"for (var a of []);\",\n    generator: \"function* f(){}\",\n    let: \"let a;\",\n    logical_assignment: \"[].p ??= 0;\",\n    new_target: \"function f() { new.target; }\",\n    nullish: \"0 ?? 0\",\n    optional_chaining: \"0?.p\",\n    rest: \"var [...a] = [];\",\n    rest_object: \"var {...a} = {};\",\n    spread: \"[...[]];\",\n    spread_object: \"({...0});\",\n    template: \"``\",\n    trailing_comma: \"function f(a,) {}\",\n});\nif (SUPPORT.exponentiation && sandbox.run_code(\"console.log(10 ** 100 === Math.pow(10, 100));\") !== \"true\\n\") {\n    SUPPORT.exponentiation = false;\n}\n\nvar VALUES = [\n    '\"a\"',\n    '\"b\"',\n    '\"c\"',\n    '\"\"',\n    \"true\",\n    \"false\",\n    \" /[a2][^e]+$/ \",\n    \"(-1)\",\n    \"(-2)\",\n    \"(-3)\",\n    \"(-4)\",\n    \"(-5)\",\n    \"0\",\n    \"1\",\n    \"2\",\n    \"3\",\n    \"4\",\n    \"5\",\n    \"22\",\n    \"(-0)\", // 0/-0 !== 0\n    \"23..toString()\",\n    \"24 .toString()\",\n    \"25. \",\n    \"0x26.toString()\",\n    \"NaN\",\n    \"null\",\n    \"Infinity\",\n    \"undefined\",\n    \"[]\",\n    \"[,0][1]\", // an array with elisions... but this is always false\n    \"([,0].length === 2)\", // an array with elisions... this is always true\n    \"({})\", // wrapped the object causes too many syntax errors in statements\n    '\"foo\"',\n    '\"bar\"',\n    '\"undefined\"',\n    '\"object\"',\n    '\"number\"',\n    '\"function\"',\n    \"this\",\n];\nVALUES = VALUES.concat(VALUES);\nVALUES = VALUES.concat(VALUES);\nVALUES = VALUES.concat(VALUES);\nif (SUPPORT.bigint) VALUES = VALUES.concat([\n    \"(!0o644n)\",\n    \"([3n][0] > 2)\",\n    \"(-42n).toString()\",\n    \"Number(0XDEADn << 16n | 0xbeefn)\",\n]);\nVALUES = VALUES.concat(VALUES);\nVALUES = VALUES.concat(VALUES);\nVALUES = VALUES.concat(VALUES);\nVALUES = VALUES.concat(VALUES);\nVALUES.push(\"import.meta\");\n\nvar BINARY_OPS = [\n    \" + \", // spaces needed to disambiguate with ++ cases (could otherwise cause syntax errors)\n    \" - \",\n    \"/\",\n    \"*\",\n    \"&\",\n    \"|\",\n    \"^\",\n    \"<\",\n    \"<=\",\n    \">\",\n    \">=\",\n    \"==\",\n    \"===\",\n    \"!=\",\n    \"!==\",\n    \"<<\",\n    \">>\",\n    \">>>\",\n    \"%\",\n    \"&&\",\n    \"||\",\n    \"^\",\n    \",\",\n];\nBINARY_OPS = BINARY_OPS.concat(BINARY_OPS);\nif (SUPPORT.nullish) BINARY_OPS.push(\"??\");\nBINARY_OPS = BINARY_OPS.concat(BINARY_OPS);\nBINARY_OPS = BINARY_OPS.concat(BINARY_OPS);\nif (SUPPORT.exponentiation) BINARY_OPS.push(\"**\");\nBINARY_OPS = BINARY_OPS.concat(BINARY_OPS);\nBINARY_OPS = BINARY_OPS.concat(BINARY_OPS);\nBINARY_OPS.push(\" in \", \" instanceof \");\n\nvar ASSIGNMENTS = [ \"=\" ];\nASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);\nASSIGNMENTS.push(\"+=\");\nASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);\nASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);\nASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);\nASSIGNMENTS = ASSIGNMENTS.concat([\n    \"-=\",\n    \"*=\",\n    \"/=\",\n    \"%=\",\n    \"&=\",\n    \"|=\",\n    \"^=\",\n    \"<<=\",\n    \">>=\",\n    \">>>=\",\n]);\nASSIGNMENTS = ASSIGNMENTS.concat(ASSIGNMENTS);\nif (SUPPORT.exponentiation) ASSIGNMENTS.push(\"**=\");\nif (SUPPORT.logical_assignment) ASSIGNMENTS = ASSIGNMENTS.concat([\n    \"&&=\",\n    \"||=\",\n    \"??=\",\n]);\n\nvar UNARY_SAFE = [\n    \"+\",\n    \"-\",\n    \"~\",\n    \"!\",\n    \"void \",\n    \"delete \",\n];\nvar UNARY_POSTFIX = [\n    \"++\",\n    \"--\",\n];\nvar UNARY_PREFIX = UNARY_POSTFIX.concat(UNARY_SAFE);\n\nvar NO_COMMA = true;\nvar COMMA_OK = false;\nvar MAYBE = true;\nvar MANDATORY = false;\nvar CAN_THROW = true;\nvar CANNOT_THROW = false;\nvar CAN_BREAK = true;\nvar CANNOT_BREAK = false;\nvar CAN_CONTINUE = true;\nvar CANNOT_CONTINUE = false;\nvar CAN_RETURN = false;\nvar CANNOT_RETURN = true;\nvar NO_DEFUN = false;\nvar DEFUN_OK = true;\nvar DONT_STORE = true;\nvar NO_CONST = true;\nvar NO_DUPLICATE = true;\nvar NO_LAMBDA = true;\nvar NO_TEMPLATE = true;\n\nvar VAR_NAMES = [\n    \"a\",\n    \"a\",\n    \"a\",\n    \"a\",\n    \"b\",\n    \"b\",\n    \"b\",\n    \"b\",\n    \"c\", // prevent redeclaring this, avoid assigning to this\n    \"foo\",\n    \"foo\",\n    \"bar\",\n    \"bar\",\n    \"undefined\",\n    \"NaN\",\n    \"Infinity\",\n    \"arguments\",\n    \"async\",\n    \"await\",\n    \"let\",\n    \"yield\",\n];\nvar INITIAL_NAMES_LEN = VAR_NAMES.length;\n\nvar TYPEOF_OUTCOMES = [\n    \"function\",\n    \"undefined\",\n    \"string\",\n    \"number\",\n    \"object\",\n    \"boolean\",\n    \"special\",\n    \"unknown\",\n    \"symbol\",\n    \"crap\",\n];\n\nvar avoid_vars = [];\nvar block_vars = [ \"let\" ];\nvar lambda_vars = [];\nvar unique_vars = [];\nvar classes = [];\nvar allow_this = true;\nvar async = false;\nvar has_await = false;\nvar export_default = false;\nvar generator = false;\nvar loops = 0;\nvar funcs = 0;\nvar clazz = 0;\nvar imports = 0;\nvar in_class = 0;\nvar called = Object.create(null);\nvar labels = 10000;\n\nfunction rng(limit) {\n    var r = randomBytes(2).readUInt16LE(0) / 65536;\n    return Math.floor(limit * r);\n}\n\nfunction get_num(max) {\n    if (rng(max + 1) == 0) return 0;\n    var i = 1;\n    while (i < max && rng(2)) i++;\n    return i;\n}\n\nfunction strictMode() {\n    return use_strict && rng(4) == 0 ? '\"use strict\";' : \"\";\n}\n\nfunction appendExport(stmtDepth, allowDefault) {\n    if (SUPPORT.destructuring && stmtDepth == 1 && rng(20) == 0) {\n        if (allowDefault && !export_default && rng(5) == 0) {\n            export_default = true;\n            return \"export default \";\n        }\n        return \"export \";\n    }\n    return \"\";\n}\n\nfunction mayDefer(code) {\n    if (SUPPORT.arrow && rng(200) == 0) {\n        has_await = true;\n        return \"void setImmediate(() => (\" + code + \"))\";\n    }\n    return code;\n}\n\nfunction createTopLevelCode() {\n    VAR_NAMES.length = INITIAL_NAMES_LEN; // prune any previous names still in the list\n    block_vars.length = 1;\n    lambda_vars.length = 0;\n    unique_vars.length = 0;\n    classes.length = 0;\n    allow_this = true;\n    async = SUPPORT.async && rng(200) == 0;\n    has_await = false;\n    export_default = false;\n    generator = false;\n    loops = 0;\n    funcs = 0;\n    clazz = 0;\n    imports = 0;\n    in_class = async;\n    called = Object.create(null);\n    var s = [\n        strictMode(),\n        appendExport(1) + \"var _calls_ = 10, a = 100, b = 10, c = 0;\",\n    ];\n    createBlockVariables(MAX_GENERATION_RECURSION_DEPTH, 0, CANNOT_THROW, function(defns) {\n        s.push(defns());\n        if (rng(2)) {\n            s.push(createStatements(3, MAX_GENERATION_RECURSION_DEPTH, CANNOT_THROW, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, 0));\n        } else {\n            s.push(createFunctions(MAX_GENERATED_TOPLEVELS_PER_RUN, MAX_GENERATION_RECURSION_DEPTH, DEFUN_OK, CANNOT_THROW, 0));\n        }\n    });\n    // preceding `null` makes for a cleaner output (empty string still shows up etc)\n    var log = \"console.log(null, a, b, c, Infinity, NaN, undefined)\";\n    if (SUPPORT.arrow && has_await && rng(20) == 0) log = \"setImmediate(() => \" + log + \")\";\n    s.push(log + \";\");\n    return s.join(\"\\n\");\n}\n\nfunction createFunctions(n, recurmax, allowDefun, canThrow, stmtDepth) {\n    if (--recurmax < 0) { return \";\"; }\n    var s = \"\";\n    for (var i = get_num(n - 1) + 1; --i >= 0;) {\n        s += createFunction(recurmax, allowDefun, canThrow, stmtDepth) + \"\\n\";\n    }\n    return s;\n}\n\nfunction addTrailingComma(list) {\n    return SUPPORT.trailing_comma && list && rng(20) == 0 ? list + \",\" : list;\n}\n\nfunction createParams(was_async, was_generator, noDuplicate) {\n    var save_async = async;\n    if (!async) async = was_async;\n    var save_generator = generator;\n    if (!generator) generator = was_generator;\n    var len = unique_vars.length;\n    var params = [];\n    for (var i = get_num(3); --i >= 0;) {\n        var name = createVarName(MANDATORY);\n        if (noDuplicate || in_class) unique_vars.push(name);\n        params.push(name);\n    }\n    unique_vars.length = len;\n    generator = save_generator;\n    async = save_async;\n    return addTrailingComma(params.join(\", \"));\n}\n\nfunction createArgs(recurmax, stmtDepth, canThrow, noTemplate) {\n    recurmax--;\n    if (SUPPORT.template && !noTemplate && rng(20) == 0) return createTemplateLiteral(recurmax, stmtDepth, canThrow);\n    var args = [];\n    for (var i = get_num(3); --i >= 0;) switch (SUPPORT.spread ? rng(50) : 3) {\n      case 0:\n      case 1:\n        var name = getVarName();\n        if (canThrow && rng(20) == 0) {\n            args.push(\"...\" + name);\n        } else {\n            args.push('...(\"\" + ' + name + \")\");\n        }\n        break;\n      case 2:\n        args.push(\"...\" + createArrayLiteral(recurmax, stmtDepth, canThrow));\n        break;\n      default:\n        args.push(rng(2) ? createValue() : createExpression(recurmax, NO_COMMA, stmtDepth, canThrow));\n        break;\n    }\n    return \"(\" + addTrailingComma(args.join(\", \")) + \")\";\n}\n\nfunction createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, was_async, was_generator) {\n    var avoid = [];\n    var len = unique_vars.length;\n    var pairs = createPairs(recurmax, !nameLenBefore);\n    pairs.has_rest = nameLenBefore && convertToRest(pairs.names);\n    unique_vars.length = len;\n    return pairs;\n\n    function mapShuffled(values, fn) {\n        var declare_only = [];\n        var side_effects = [];\n        values.forEach(function(value, index) {\n            value = fn(value, index);\n            if (/]:|=/.test(value) ? canThrow && rng(20) == 0 : rng(5)) {\n                declare_only.splice(rng(declare_only.length + 1), 0, value);\n            } else if (canThrow && rng(20) == 0) {\n                side_effects.splice(rng(side_effects.length + 1), 0, value);\n            } else {\n                side_effects.push(value);\n            }\n        });\n        return declare_only.concat(side_effects);\n    }\n\n    function convertToRest(names) {\n        var last = names.length - 1;\n        if (last >= 0 && SUPPORT.rest && rng(20) == 0) {\n            var name = names[last];\n            if (name && name.indexOf(\"=\") < 0) {\n                if (/^[[{]/.test(name)) name = \"[ \" + name + \" ]\";\n                names[last] = \"...\" + name;\n                return true;\n            }\n        }\n    }\n\n    function fill(nameFn, valueFn) {\n        var save_async = async;\n        if (was_async != null) {\n            async = false;\n            if (save_async || was_async) addAvoidVar(\"await\");\n        }\n        var save_generator = generator;\n        if (was_generator != null) {\n            generator = false;\n            if (save_generator || was_generator) addAvoidVar(\"yield\");\n        }\n        avoid.forEach(addAvoidVar);\n        var save_vars = nameLenBefore && VAR_NAMES.splice(nameLenBefore);\n        if (nameFn) nameFn();\n        if (was_generator != null) {\n            generator = was_generator;\n            if (save_generator || was_generator) removeAvoidVar(\"yield\");\n        }\n        if (was_async != null) {\n            async = was_async;\n            if (save_async || was_async) removeAvoidVar(\"await\");\n        }\n        if (valueFn) valueFn();\n        if (save_vars) [].push.apply(VAR_NAMES, save_vars);\n        avoid.forEach(removeAvoidVar);\n        generator = save_generator;\n        async = save_async;\n    }\n\n    function createAssignmentValue(recurmax) {\n        return nameLenBefore && rng(2) ? createValue() : createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);\n    }\n\n    function createDefaultValue(recurmax, noDefault) {\n        return !noDefault && SUPPORT.default_value && rng(20) == 0 ? \" = \" +  createAssignmentValue(recurmax) : \"\";\n    }\n\n    function createKey(recurmax, keys) {\n        var key;\n        do {\n            key = createObjectKey(recurmax, stmtDepth, canThrow);\n        } while (keys.indexOf(key) >= 0);\n        return key;\n    }\n\n    function createName() {\n        unique_vars.push(\"a\", \"b\", \"c\", \"undefined\", \"NaN\", \"Infinity\");\n        var save_async = async;\n        if (!async) async = was_async;\n        var save_generator = generator;\n        if (!generator) generator = was_generator;\n        var name = createVarName(MANDATORY);\n        generator = save_generator;\n        async = save_async;\n        unique_vars.length -= 6;\n        avoid.push(name);\n        unique_vars.push(name);\n        return name;\n    }\n\n    function createPairs(recurmax, noDefault) {\n        var names = [], values = [];\n        var m = rng(4), n = rng(4);\n        if (!nameLenBefore) m = Math.max(m, n, 1);\n        for (var i = Math.max(m, n); --i >= 0;) {\n            if (i < m && i < n) {\n                createDestructured(recurmax, noDefault, names, values);\n            } else if (i < m) {\n                var name = createName();\n                fill(function() {\n                    names.unshift(name + createDefaultValue(recurmax, noDefault));\n                });\n            } else {\n                fill(null, function() {\n                    values.unshift(createAssignmentValue(recurmax));\n                });\n            }\n        }\n        return {\n            names: names,\n            values: values,\n        };\n    }\n\n    function createDestructured(recurmax, noDefault, names, values) {\n        switch (rng(20)) {\n          case 0:\n            if (--recurmax < 0) {\n                names.unshift(\"[]\");\n                values.unshift('\"\"');\n            } else {\n                var pairs = createPairs(recurmax);\n                var default_value;\n                fill(function() {\n                    default_value = createDefaultValue(recurmax, noDefault);\n                }, function() {\n                    while (!rng(10)) {\n                        var index = rng(pairs.names.length + 1);\n                        pairs.names.splice(index, 0, \"\");\n                        if (index < pairs.values.length) {\n                            pairs.values.splice(index, 0, rng(2) ? createAssignmentValue(recurmax) : \"\");\n                        } else switch (rng(5)) {\n                          case 0:\n                            pairs.values[index] = createAssignmentValue(recurmax);\n                          case 1:\n                            pairs.values.length = index + 1;\n                        }\n                    }\n                    convertToRest(pairs.names);\n                    names.unshift(\"[ \" + pairs.names.join(\", \") + \" ]\" + default_value);\n                    values.unshift(\"[ \" + pairs.values.join(\", \") + \" ]\");\n                });\n            }\n            break;\n          case 1:\n            if (--recurmax < 0) {\n                names.unshift(\"{}\");\n                values.unshift('\"\"');\n            } else {\n                var pairs = createPairs(recurmax);\n                var keys = [];\n                pairs.names.forEach(function(name, index) {\n                    if (/^[[{]/.test(name)) {\n                        var key;\n                        do {\n                            key = KEYS[rng(KEYS.length)];\n                        } while (keys.indexOf(key) >= 0);\n                        keys[index] = key;\n                    }\n                });\n                fill(function() {\n                    var last = pairs.names.length - 1, rest;\n                    if (last >= 0 && !(last in keys) && SUPPORT.rest_object && rng(20) == 0) {\n                        rest = pairs.names.pop();\n                        if (!/=/.test(rest)) rest = \"...\" + rest;\n                    }\n                    var s = mapShuffled(pairs.names, function(name, index) {\n                        if (index in keys) return keys[index] + \": \" + name;\n                        return rng(10) == 0 ? name : createKey(recurmax, keys) + \": \" + name;\n                    });\n                    if (rest) {\n                        s.push(rest);\n                        s = s.join(\", \");\n                    } else {\n                        s = addTrailingComma(s.join(\", \"));\n                    }\n                    names.unshift(\"{ \" + s + \" }\" + createDefaultValue(recurmax, noDefault));\n                }, function() {\n                    values.unshift(\"{ \" + addTrailingComma(mapShuffled(pairs.values, function(value, index) {\n                        var key = index in keys ? keys[index] : createKey(recurmax, keys);\n                        return key + \": \" + value;\n                    }).join(\", \")) + \" }\");\n                });\n            }\n            break;\n          default:\n            var name = createName();\n            fill(function() {\n                names.unshift(name + createDefaultValue(recurmax, noDefault));\n            }, function() {\n                values.unshift(createAssignmentValue(recurmax));\n            });\n            break;\n        }\n    }\n}\n\nfunction filterDirective(s) {\n    if (!generate_directive && !s[1] && /\\(\"/.test(s[2])) s[2] = \";\" + s[2];\n    return s;\n}\n\nfunction createBlockVariables(recurmax, stmtDepth, canThrow, fn) {\n    ++stmtDepth;\n    var block_len = block_vars.length;\n    var class_len = classes.length;\n    var nameLenBefore = VAR_NAMES.length;\n    var consts = [];\n    var lets = [];\n    unique_vars.push(\"a\", \"b\", \"c\", \"undefined\", \"NaN\", \"Infinity\");\n    while (!rng(block_vars.length > block_len ? 10 : 100)) {\n        var name = createVarName(MANDATORY);\n        if (SUPPORT.let && rng(2)) {\n            lets.push(name);\n        } else {\n            consts.push(name);\n        }\n        block_vars.push(name);\n    }\n    unique_vars.length -= 6;\n    fn(function() {\n        consts.forEach(addAvoidVar);\n        lets.forEach(addAvoidVar);\n        var s = [];\n        if (SUPPORT.class) while (rng(200) == 0) {\n            var name = \"C\" + clazz++;\n            classes.push(name);\n            s.push(appendExport(stmtDepth, true) + createClassLiteral(recurmax, stmtDepth, canThrow, name));\n        }\n        if (rng(2)) {\n            s.push(createDefinitions(\"const\", consts), createDefinitions(\"let\", lets));\n        } else {\n            s.push(createDefinitions(\"let\", lets), createDefinitions(\"const\", consts));\n        }\n        s.push(\"\");\n        return s.join(\"\\n\");\n    });\n    VAR_NAMES.length = nameLenBefore;\n    classes.length = class_len;\n    block_vars.length = block_len;\n\n    function createDefinitions(type, names) {\n        if (!names.length) return \"\";\n        var s = appendExport(stmtDepth) + type + \" \";\n        switch (SUPPORT.destructuring ? rng(10) : 2) {\n          case 0:\n            while (!rng(10)) names.splice(rng(names.length + 1), 0, \"\");\n            s += \"[ \" + names.join(\", \") + \" ] = [ \" + names.map(function() {\n                return rng(10) ? createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) : \"\";\n            }).join(\", \") + \" ];\";\n            break;\n          case 1:\n            var keys = [];\n            s += \"{ \" + names.map(function(name, i) {\n                var key = createObjectKey(recurmax, stmtDepth, canThrow);\n                if (!/\\[/.test(key)) keys[i] = key;\n                return key + \": \" + name;\n            }).join(\", \") + \"} = { \" + names.map(function(name, i) {\n                var key = i in keys ? keys[i] : createObjectKey(recurmax, stmtDepth, canThrow);\n                return key + \": \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);\n            }).join(\", \") + \"};\";\n            break;\n          default:\n            s += names.map(function(name) {\n                if (type == \"let\" && !rng(10)) {\n                    removeAvoidVar(name);\n                    return name;\n                }\n                var value = createExpression(recurmax, NO_COMMA, stmtDepth, canThrow);\n                removeAvoidVar(name);\n                return name + \" = \" + value;\n            }).join(\", \") + \";\";\n            names.length = 0;\n            break;\n        }\n        names.forEach(removeAvoidVar);\n        return s;\n    }\n}\n\nfunction mayCreateBlockVariables(recurmax, stmtDepth, canThrow, fn) {\n    if (SUPPORT.const_block) {\n        createBlockVariables(recurmax, stmtDepth, canThrow, fn);\n    } else {\n        fn(function() {\n            return \"\";\n        });\n    }\n}\n\nfunction makeFunction(name) {\n    lambda_vars.push(name);\n    if (generator) {\n        name = \"function* \" + name;\n    } else {\n        name = \"function \" + name;\n    }\n    if (async) name = \"async \" + name;\n    return name;\n}\n\nfunction invokeGenerator(was_generator) {\n    if (generator && !was_generator) switch (rng(4)) {\n      case 0:\n        return \".next()\";\n      case 1:\n        return \".next().done\";\n      case 2:\n        return \".next().value\";\n    }\n    return \"\";\n}\n\nfunction createFunction(recurmax, allowDefun, canThrow, stmtDepth) {\n    if (--recurmax < 0) { return \";\"; }\n    if (!STMT_COUNT_FROM_GLOBAL) stmtDepth = 0;\n    ++stmtDepth;\n    var s = [];\n    var name, args;\n    var nameLenBefore = VAR_NAMES.length;\n    var lambda_len = lambda_vars.length;\n    var save_async = async;\n    var save_generator = generator;\n    async = SUPPORT.async && rng(200) == 0;\n    generator = SUPPORT.generator && rng(50) == 0;\n    if (async && generator && !SUPPORT.async_generator) {\n        if (rng(2)) {\n            async = false;\n        } else {\n            generator = false;\n        }\n    }\n    createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {\n        if (allowDefun || rng(5) > 0) {\n            name = \"f\" + funcs++;\n        } else {\n            unique_vars.push(\"a\", \"b\", \"c\");\n            name = createVarName(MANDATORY, !allowDefun);\n            unique_vars.length -= 3;\n        }\n        var params;\n        if (SUPPORT.destructuring && (!allowDefun || !(name in called)) && rng(2)) {\n            called[name] = false;\n            var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async, save_generator);\n            params = pairs.names.join(\", \");\n            if (!pairs.has_rest) params = addTrailingComma(params);\n            args = \"(\" + addTrailingComma(pairs.values.join(\", \")) + \")\";\n        } else {\n            params = createParams(save_async, save_generator);\n        }\n        s.push(makeFunction(name) + \"(\" + params + \"){\", strictMode());\n        s.push(defns());\n        if (rng(5) === 0) {\n            // functions with functions. lower the recursion to prevent a mess.\n            s.push(createFunctions(5, Math.ceil(recurmax * 0.7), DEFUN_OK, canThrow, stmtDepth));\n        } else {\n            // functions with statements\n            s.push(_createStatements(3, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));\n        }\n        s.push(\"}\", \"\");\n        s = filterDirective(s).join(\"\\n\");\n    });\n    var call_next = invokeGenerator(save_generator);\n    generator = save_generator;\n    async = save_async;\n    lambda_vars.length = lambda_len;\n    VAR_NAMES.length = nameLenBefore;\n\n    if (allowDefun) s = appendExport(stmtDepth, true) + s;\n    if (!allowDefun) {\n        // avoid \"function statements\" (decl inside statements)\n        s = appendExport(stmtDepth) + \"var \" + createVarName(MANDATORY) + \" = \" + s;\n        s += args || createArgs(recurmax, stmtDepth, canThrow);\n        s += call_next;\n    } else if (!(name in called) || args || rng(3)) {\n        s += appendExport(stmtDepth) + \"var \" + createVarName(MANDATORY) + \" = \" + name;\n        s += args || createArgs(recurmax, stmtDepth, canThrow);\n        s += call_next;\n    }\n\n    return s + \";\";\n}\n\nfunction _createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {\n    if (--recurmax < 0) return \";\";\n    var s = \"\";\n    for (var i = get_num(n); --i >= 0;) {\n        s += createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + \"\\n\";\n    }\n    return s;\n}\n\nfunction createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {\n    var s = \"\";\n    mayCreateBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {\n        s += defns() + \"\\n\";\n        s += _createStatements(n, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);\n    });\n    return s;\n}\n\nfunction enableLoopControl(flag, defaultValue) {\n    return Array.isArray(flag) && flag.indexOf(\"\") < 0 ? flag.concat(\"\") : flag || defaultValue;\n}\n\nfunction createLabel(canBreak, canContinue) {\n    var label;\n    if (rng(10) < 3) {\n        label = ++labels;\n        if (Array.isArray(canBreak)) {\n            canBreak = canBreak.slice();\n        } else {\n            canBreak = canBreak ? [ \"\" ] : [];\n        }\n        canBreak.push(label);\n        if (Array.isArray(canContinue)) {\n            canContinue = canContinue.slice();\n        } else {\n            canContinue = canContinue ? [ \"\" ] : [];\n        }\n        canContinue.push(label);\n    }\n    return {\n        break: canBreak,\n        continue: canContinue,\n        target: label ? \"L\" + label + \": \" : \"\"\n    };\n}\n\nfunction getLabel(label) {\n    if (!Array.isArray(label)) return \"\";\n    label = label[rng(label.length)];\n    return label && \" L\" + label;\n}\n\nfunction declareVarName(name, no_var) {\n    if (!SUPPORT.let || !no_var && rng(10)) return \"var \";\n    block_vars.push(name);\n    return rng(2) ? \"let \" : \"const \";\n}\n\nfunction createImportAlias() {\n    if (rng(10)) return \"alias\" + imports++;\n    unique_vars.push(\"a\", \"b\", \"c\", \"undefined\", \"NaN\", \"Infinity\");\n    var name = createVarName(MANDATORY);\n    block_vars.push(name);\n    unique_vars.length -= 6;\n    return name;\n}\n\nfunction createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth, target) {\n    ++stmtDepth;\n    var loop = ++loops;\n    if (--recurmax < 0) {\n        return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \";\";\n    }\n\n    // allow to forcefully generate certain structures at first or second recursion level\n    if (target === undefined) {\n        if (stmtDepth === 1 && STMT_FIRST_LEVEL_OVERRIDE >= 0) target = STMT_FIRST_LEVEL_OVERRIDE;\n        else if (stmtDepth === 2 && STMT_SECOND_LEVEL_OVERRIDE >= 0) target = STMT_SECOND_LEVEL_OVERRIDE;\n        else target = STMTS_TO_USE[rng(STMTS_TO_USE.length)];\n    }\n\n    switch (target) {\n      case STMT_BLOCK:\n        var label = createLabel(canBreak);\n        return label.target + \"{\" + createStatements(5, recurmax, canThrow, label.break, canContinue, cannotReturn, stmtDepth) + \"}\";\n      case STMT_IF_ELSE:\n        return \"if (\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \")\" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + (rng(2) ? \" else \" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) : \"\");\n      case STMT_DO_WHILE:\n        var label = createLabel(canBreak, canContinue);\n        canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);\n        canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);\n        return \"{var brake\" + loop + \" = 5; \" + label.target + \"do {\" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + \"} while (\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" && --brake\" + loop + \" > 0);}\";\n      case STMT_WHILE:\n        var label = createLabel(canBreak, canContinue);\n        canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);\n        canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);\n        return \"{var brake\" + loop + \" = 5; \" + label.target + \"while (\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" && --brake\" + loop + \" > 0)\" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + \"}\";\n      case STMT_FOR_LOOP:\n        var label = createLabel(canBreak, canContinue);\n        canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);\n        canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);\n        return label.target + \"for (var brake\" + loop + \" = 5; \" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" && brake\" + loop + \" > 0; --brake\" + loop + \")\" + createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);\n      case STMT_FOR_ENUM:\n        var block_len = block_vars.length;\n        var nameLenBefore = VAR_NAMES.length;\n        var label = createLabel(canBreak, canContinue);\n        canBreak = label.break || enableLoopControl(canBreak, CAN_BREAK);\n        canContinue = label.continue || enableLoopControl(canContinue, CAN_CONTINUE);\n        var of = SUPPORT.for_of && rng(20) == 0;\n        var key;\n        if (rng(10)) {\n            key = \"key\" + loop;\n        } else if (bug_for_of_async && of) {\n            addAvoidVar(\"async\");\n            key = getVarName(NO_CONST);\n            removeAvoidVar(\"async\");\n        } else {\n            key = getVarName(NO_CONST);\n        }\n        var init = \"\";\n        if (!/^key/.test(key)) {\n            if (!(of && bug_for_of_var) && rng(10) == 0) init = \"var \";\n        } else {\n            init = declareVarName(key, of && bug_for_of_var);\n        }\n        if (!SUPPORT.destructuring || of && !(canThrow && rng(20) == 0) || rng(10)) {\n            init += key;\n        } else if (rng(5)) {\n            init += \"[ \" + key + \" ]\";\n        } else {\n            init += \"{ length: \" + key + \" }\";\n        }\n        var s = \"var expr\" + loop + \" = \";\n        if (of) {\n            var await = SUPPORT.for_await_of && async && rng(20) == 0;\n            if (SUPPORT.generator && rng(20) == 0) {\n                var gen = getVarName();\n                if (canThrow && rng(20) == 0) {\n                    s += gen + \"; \";\n                } else {\n                    s += gen + \" && typeof \" + gen + \"[Symbol.\";\n                    s += await ? \"asyncIterator\" : \"iterator\";\n                    s += '] == \"function\" ? ' + gen + \" : \" + createArrayLiteral(recurmax, stmtDepth, canThrow) + \"; \";\n                }\n            } else if (rng(5)) {\n                s += createArrayLiteral(recurmax, stmtDepth, canThrow) + \"; \";\n            } else if (canThrow && rng(20) == 0) {\n                s += createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"; \";\n            } else {\n                s += '\"\" + (' + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"); \";\n            }\n            s += label.target + \" for \";\n            if (await) {\n                s += \"await \";\n                has_await = true;\n            }\n            s += \"(\" + init + \" of expr\" + loop + \") {\";\n        } else {\n            s += createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"; \";\n            s += label.target + \" for (\" + init + \" in expr\" + loop + \") {\";\n        }\n        if (/^key/.test(key)) VAR_NAMES.push(key);\n        if (rng(3)) {\n            s += \"c = 1 + c; \";\n            unique_vars.push(\"a\", \"b\", \"c\", \"undefined\", \"NaN\", \"Infinity\");\n            var name;\n            do {\n                name = createVarName(MANDATORY);\n            } while (name == key);\n            unique_vars.length -= 6;\n            s += declareVarName(name) + name + \" = expr\" + loop + \"[\" + key + \"]; \";\n        }\n        s += createStatement(recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + \"}\";\n        VAR_NAMES.length = nameLenBefore;\n        block_vars.length = block_len;\n        return \"{\" + s + \"}\";\n      case STMT_SEMI:\n        return use_strict && rng(20) === 0 ? '\"use strict\";' : \";\";\n      case STMT_EXPR:\n          if (SUPPORT.destructuring && stmtDepth == 1 && !export_default && rng(20) == 0) {\n              export_default = true;\n              return \"export default \" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \";\";\n          }\n        return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \";\";\n      case STMT_SWITCH:\n        // note: case args are actual expressions\n        // note: default does not _need_ to be last\n        return \"switch (\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \") { \" + createSwitchParts(recurmax, 4, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) + \"}\";\n      case STMT_VAR:\n        if (SUPPORT.destructuring && stmtDepth == 1 && rng(5) == 0) {\n            var s = rng(2) ? \" \" + createImportAlias() : \"\";\n            if (rng(10)) {\n                if (s) s += \",\";\n                if (rng(2)) {\n                    s += \" * as \" + createImportAlias();\n                } else {\n                    var names = [];\n                    for (var i = get_num(3); --i >= 0;) {\n                        var name = createImportAlias();\n                        names.push(rng(2) ? getDotKey() + \" as \" + name : name);\n                    }\n                    s += \" { \" + names.join(\", \") + \" }\";\n                }\n            }\n            if (s) s += \" from\";\n            return \"import\" + s + ' \"path/to/module.js\";';\n        } else if (SUPPORT.destructuring && rng(20) == 0) {\n            var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow);\n            return appendExport(stmtDepth) + \"var \" + pairs.names.map(function(name, index) {\n                return index in pairs.values ? name + \" = \" + pairs.values[index] : name;\n            }).join(\", \") + \";\";\n        } else switch (rng(3)) {\n          case 0:\n            unique_vars.push(\"c\");\n            var name = createVarName(MANDATORY);\n            unique_vars.pop();\n            return appendExport(stmtDepth) + \"var \" + name + \";\";\n          case 1:\n            // initializer can only have one expression\n            unique_vars.push(\"c\");\n            var name = createVarName(MANDATORY);\n            unique_vars.pop();\n            return appendExport(stmtDepth) + \"var \" + name + \" = \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \";\";\n          default:\n            // initializer can only have one expression\n            unique_vars.push(\"c\");\n            var n1 = createVarName(MANDATORY);\n            var n2 = createVarName(MANDATORY);\n            unique_vars.pop();\n            return appendExport(stmtDepth) + \"var \" + n1 + \" = \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \", \" + n2 + \" = \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \";\";\n        }\n      case STMT_RETURN_ETC:\n        switch (rng(8)) {\n          case 0:\n          case 1:\n          case 2:\n          case 3:\n            if (canBreak && rng(5) === 0) return \"break\" + getLabel(canBreak) + \";\";\n            if (canContinue && rng(5) === 0) return \"continue\" + getLabel(canContinue) + \";\";\n            if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \";\";\n            if (rng(3) == 0) return \"/*3*/return;\";\n            return \"return \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \";\";\n          case 4:\n            // this is actually more like a parser test, but perhaps it hits some dead code elimination traps\n            // must wrap in curlies to prevent orphaned `else` statement\n            // note: you can't `throw` without an expression so don't put a `throw` option in this case\n            if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \";\";\n            return \"{ /*2*/ return\\n\" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \"}\";\n          default:\n            // must wrap in curlies to prevent orphaned `else` statement\n            if (canThrow && rng(5) === 0) return \"{ throw \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \"}\";\n            if (cannotReturn) return createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \";\";\n            return \"{ return \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \"}\";\n        }\n      case STMT_FUNC_EXPR:\n        // \"In non-strict mode code, functions can only be declared at top level, inside a block, or ...\"\n        // (don't make func decls in `if`; it's only a parser thing because you can't call them without a block)\n        return \"{\" + createFunction(recurmax, NO_DEFUN, canThrow, stmtDepth) + \"}\";\n      case STMT_TRY:\n        // catch var could cause some problems\n        // note: the \"blocks\" are syntactically mandatory for try/catch/finally\n        var n = rng(3); // 0=only catch, 1=only finally, 2=catch+finally\n        var s = \"try {\" + createStatement(recurmax, n === 1 ? CANNOT_THROW : CAN_THROW, canBreak, canContinue, cannotReturn, stmtDepth) + \" }\";\n        if (n !== 1) {\n            // the catch var should only be accessible in the catch clause...\n            // we have to do go through some trouble here to prevent leaking it\n            mayCreateBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {\n                var block_len = block_vars.length;\n                var nameLenBefore = VAR_NAMES.length;\n                var unique_len = unique_vars.length;\n                if (SUPPORT.catch_omit_var && !rng(20)) {\n                    s += \" catch { \";\n                } else if (canThrow && SUPPORT.destructuring && !rng(20)) {\n                    unique_vars.push(\"a\", \"b\", \"c\", \"undefined\", \"NaN\", \"Infinity\");\n                    var name = createVarName(MANDATORY);\n                    block_vars.push(name);\n                    var message = createVarName(MANDATORY);\n                    block_vars.push(message);\n                    unique_vars.length -= 6;\n                    if (SUPPORT.computed_key && rng(10) == 0) {\n                        s += \" catch ({  message: \" + message + \", \";\n                        addAvoidVar(name);\n                        s += \"[\" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \"]: \" + name;\n                        removeAvoidVar(name);\n                        s += \" }) { \";\n                    } else {\n                        s += \" catch ({ name: \" + name + \", message: \" + message + \" }) { \";\n                    }\n                } else {\n                    var name = createVarName(MANDATORY);\n                    if (!catch_redef) unique_vars.push(name);\n                    s += \" catch (\" + name + \") { \";\n                }\n                var catches = VAR_NAMES.length - nameLenBefore;\n                s += defns() + \"\\n\";\n                s += _createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth);\n                s += \" }\";\n                // remove catch variables\n                block_vars.length = block_len;\n                if (catches > 0) VAR_NAMES.splice(nameLenBefore, catches);\n                unique_vars.length = unique_len;\n            });\n        }\n        if (n !== 0) s += [\n            \" finally { \",\n            createStatements(5, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),\n            \" }\",\n        ].join(\"\");\n        return s;\n      case STMT_C:\n        return \"c = c + 1;\";\n      default:\n        throw \"no\";\n    }\n}\n\nfunction createSwitchParts(recurmax, n, canThrow, canBreak, canContinue, cannotReturn, stmtDepth) {\n    var hadDefault = false;\n    var s = [ \"\" ];\n    canBreak = enableLoopControl(canBreak, CAN_BREAK);\n    while (n-- > 0) {\n        //hadDefault = n > 0; // disables weird `default` clause positioning (use when handling destabilizes)\n        if (hadDefault || rng(5) > 0) {\n            s.push(\n                \"case \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \":\",\n                _createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),\n                rng(10) > 0 ? \" break;\" : \"/* fall-through */\",\n                \"\"\n            );\n        } else {\n            hadDefault = true;\n            s.push(\n                \"default:\",\n                _createStatements(3, recurmax, canThrow, canBreak, canContinue, cannotReturn, stmtDepth),\n                \"\"\n            );\n        }\n    }\n    return s.join(\"\\n\");\n}\n\nfunction createExpression(recurmax, noComma, stmtDepth, canThrow) {\n    if (--recurmax < 0) {\n        return \"(c = 1 + c, \" + createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + \")\"; // note: should return a simple non-recursing expression value!\n    }\n    // since `a` and `b` are our canaries we want them more frequently than other expressions (1/3rd chance of a canary)\n    switch (rng(6)) {\n      case 0:\n        return \"(a++ + (\" + _createExpression(recurmax, noComma, stmtDepth, canThrow) + \"))\";\n      case 1:\n        return \"((--b) + (\" + _createExpression(recurmax, noComma, stmtDepth, canThrow) + \"))\";\n      case 2:\n        return \"((c = c + 1) + (\" + _createExpression(recurmax, noComma, stmtDepth, canThrow) + \"))\"; // c only gets incremented\n      default:\n        var expr = \"(\" + _createExpression(recurmax, noComma, stmtDepth, canThrow) + \")\";\n        if (async && rng(50) == 0) {\n            has_await = true;\n            return \"(await\" + expr + \")\";\n        }\n        if (generator && rng(50) == 0) return \"(yield\" + (canThrow && rng(20) == 0 ? \"*\" : \"\") + expr + \")\";\n        return expr;\n    }\n}\n\nfunction _createExpression(recurmax, noComma, stmtDepth, canThrow) {\n    var p = 0;\n    switch (rng(_createExpression.N)) {\n      case p++:\n        if (generator && rng(50) == 0) return \"yield\";\n      case p++:\n        return createUnaryPrefix() + (rng(2) ? \"a\" : \"b\");\n      case p++:\n      case p++:\n        return (rng(2) ? \"a\" : \"b\") + createUnaryPostfix();\n      case p++:\n      case p++:\n        // parens needed because assignments aren't valid unless they're the left-most op(s) in an expression\n        return \"b \" + createAssignment() + \" a\";\n      case p++:\n      case p++:\n        return rng(2) + \" === 1 ? a : b\";\n      case p++:\n        if (SUPPORT.template && rng(20) == 0) {\n            var tmpl = createTemplateLiteral(recurmax, stmtDepth, canThrow);\n            if (rng(10) == 0) tmpl = \"String.raw\" + tmpl;\n            return tmpl;\n        }\n      case p++:\n        return createValue();\n      case p++:\n        if (SUPPORT.destructuring && rng(20) == 0) {\n            var name = \"alias\" + rng(imports + 2);\n            return canThrow && rng(20) == 0 ? name : \"typeof \" + name + ' != \"undefined\" && ' + name;\n        }\n      case p++:\n        return getVarName();\n      case p++:\n        switch (SUPPORT.destructuring ? rng(20) : 2) {\n          case 0:\n            return [\n                \"[ \",\n                new Array(rng(3)).join(),\n                getVarName(NO_CONST, NO_LAMBDA),\n                new Array(rng(3)).join(),\n                \" ] = \",\n                createArrayLiteral(recurmax, stmtDepth, canThrow),\n            ].join(\"\");\n          case 1:\n            return [\n                \"{ \",\n                rng(2) ? \"\" : createObjectKey(recurmax, stmtDepth, canThrow) + \": \",\n                getVarName(NO_CONST, NO_LAMBDA),\n                \" } = \",\n                createExpression(recurmax, COMMA_OK, stmtDepth, canThrow),\n                \" || {}\",\n            ].join(\"\");\n          default:\n            return getVarName(NO_CONST, NO_LAMBDA) + createAssignment() + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);\n        }\n      case p++:\n        return createExpression(recurmax, COMMA_OK, stmtDepth, canThrow);\n      case p++:\n        return createExpression(recurmax, noComma, stmtDepth, canThrow) + \" ? \" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \" : \" + createExpression(recurmax, noComma, stmtDepth, canThrow);\n      case p++:\n      case p++:\n        var nameLenBefore = VAR_NAMES.length;\n        var lambda_len = lambda_vars.length;\n        var save_async = async;\n        var save_generator = generator;\n        async = SUPPORT.async && rng(200) == 0;\n        generator = SUPPORT.generator && rng(50) == 0;\n        if (async && generator && !SUPPORT.async_generator) {\n            if (rng(2)) {\n                async = false;\n            } else {\n                generator = false;\n            }\n        }\n        unique_vars.push(\"a\", \"b\", \"c\");\n        var name = createVarName(MAYBE); // note: this name is only accessible from _within_ the function. and immutable at that.\n        unique_vars.length -= 3;\n        var s = [];\n        switch (rng(5)) {\n          case 0:\n            if (SUPPORT.arrow && !name && !generator && rng(2)) {\n                var args, suffix;\n                (rng(2) ? createBlockVariables : function() {\n                    arguments[3]();\n                })(recurmax, stmtDepth, canThrow, function(defns) {\n                    var params;\n                    if (SUPPORT.destructuring && rng(2)) {\n                        var pairs = createAssignmentPairs(recurmax, stmtDepth, canThrow, nameLenBefore, save_async, save_generator);\n                        params = pairs.names.join(\", \");\n                        if (!pairs.has_rest) params = addTrailingComma(params);\n                        args = \"(\" + addTrailingComma(pairs.values.join(\", \")) + \")\";\n                    } else {\n                        params = createParams(save_async, save_generator, NO_DUPLICATE);\n                    }\n                    params = (async ? \"async (\" : \"(\") + params + \") => \";\n                    if (defns) {\n                        s.push(\n                            \"(\" + params + \"{\",\n                            strictMode(),\n                            defns(),\n                            _createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth)\n                        );\n                        suffix = \"})\";\n                    } else {\n                        s.push(\"(\" + params);\n                        switch (rng(10)) {\n                          case 0:\n                            if (!in_class) {\n                                s.push('(typeof arguments != \"undefined\" && arguments && arguments[' + rng(3) + \"])\");\n                                break;\n                            }\n                          case 1:\n                            s.push(\"(this && this.\" + getDotKey() + \")\");\n                            break;\n                          default:\n                            s.push(createExpression(recurmax, NO_COMMA, stmtDepth, canThrow));\n                            break;\n                        }\n                        suffix = \")\";\n                    }\n                });\n                generator = save_generator;\n                async = save_async;\n                lambda_vars.length = lambda_len;\n                VAR_NAMES.length = nameLenBefore;\n                if (!args && rng(2)) args = createArgs(recurmax, stmtDepth, canThrow);\n                if (args) suffix += args;\n                s.push(suffix);\n            } else {\n                s.push(\n                    \"(\" + makeFunction(name) + \"(){\",\n                    strictMode(),\n                    createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),\n                    rng(2) ? \"})\" : \"})()\" + invokeGenerator(save_generator)\n                );\n            }\n            break;\n          case 1:\n            s.push(\n                \"+\" + makeFunction(name) + \"(){\",\n                strictMode(),\n                createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),\n                \"}()\" + invokeGenerator(save_generator)\n            );\n            break;\n          case 2:\n            s.push(\n                \"!\" + makeFunction(name) + \"(){\",\n                strictMode(),\n                createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),\n                \"}()\" + invokeGenerator(save_generator)\n            );\n            break;\n          case 3:\n            s.push(\n                \"void \" + makeFunction(name) + \"(){\",\n                strictMode(),\n                createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),\n                \"}()\" + invokeGenerator(save_generator)\n            );\n            break;\n          default:\n            async = false;\n            generator = false;\n            var instantiate = rng(4) ? \"new \" : \"\";\n            createBlockVariables(recurmax, stmtDepth, canThrow, function(defns) {\n                s.push(\n                    instantiate + makeFunction(name) + \"(\" + createParams(save_async, save_generator) + \"){\",\n                    strictMode()\n                );\n                var add_new_target = SUPPORT.new_target && VALUES.indexOf(\"new.target\") < 0;\n                if (add_new_target) VALUES.push(\"new.target\");\n                s.push(defns());\n                if (instantiate) for (var i = get_num(3); --i >= 0;) {\n                    s.push((in_class ? \"if (this) \" : \"\") + createThisAssignment(recurmax, stmtDepth, canThrow));\n                }\n                s.push(_createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth));\n                if (add_new_target) VALUES.splice(VALUES.indexOf(\"new.target\"), 1);\n            });\n            generator = save_generator;\n            async = save_async;\n            lambda_vars.length = lambda_len;\n            VAR_NAMES.length = nameLenBefore;\n            s.push(rng(2) ? \"}\" : \"}\" + createArgs(recurmax, stmtDepth, canThrow, instantiate));\n            break;\n        }\n        generator = save_generator;\n        async = save_async;\n        lambda_vars.length = lambda_len;\n        VAR_NAMES.length = nameLenBefore;\n        return filterDirective(s).join(\"\\n\");\n      case p++:\n      case p++:\n        return createTypeofExpr(recurmax, stmtDepth, canThrow);\n      case p++:\n      case p++:\n        // more like a parser test but perhaps comment nodes mess up the analysis?\n        // note: parens not needed for post-fix (since that's the default when ambiguous)\n        // for prefix ops we need parens to prevent accidental syntax errors.\n        switch (rng(6)) {\n          case 0:\n            return \"a/* ignore */++\";\n          case 1:\n            return \"b/* ignore */--\";\n          case 2:\n            return \"++/* ignore */a\";\n          case 3:\n            return \"--/* ignore */b\";\n          case 4:\n            // only groups that wrap a single variable return a \"Reference\", so this is still valid.\n            // may just be a parser edge case that is invisible to uglify...\n            return \"--(b)\";\n          case 5:\n            // classic 0.3-0.1 case; 1-0.1-0.1-0.1 is not 0.7 :)\n            return \"b + 1 - 0.1 - 0.1 - 0.1\";\n          default:\n            return \"--/* ignore */b\";\n        }\n      case p++:\n      case p++:\n        return createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow);\n      case p++:\n      case p++:\n        return createUnarySafePrefix() + \"(\" + createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + \")\";\n      case p++:\n        return \" (\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" || a || 3).toString() \";\n      case p++:\n        return \" /[abc4]/.test((\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" || b || 5).toString()) \";\n      case p++:\n        return \" /[abc4]/g.exec((\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" || b || 5).toString()) \";\n      case p++:\n        return \" (\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" || \" + rng(10) + \").toString()[\" +\n            createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"] \";\n      case p++:\n        return createArrayLiteral(recurmax, stmtDepth, canThrow);\n      case p++:\n        return createObjectLiteral(recurmax, stmtDepth, canThrow);\n      case p++:\n        return createArrayLiteral(recurmax, stmtDepth, canThrow) + \"[\" +\n            createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"]\";\n      case p++:\n        return createObjectLiteral(recurmax, stmtDepth, canThrow) + \"[\" +\n            createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"]\";\n      case p++:\n        return createArrayLiteral(recurmax, stmtDepth, canThrow) + \".\" + getDotKey();\n      case p++:\n        return createObjectLiteral(recurmax, stmtDepth, canThrow) + \".\" + getDotKey();\n      case p++:\n        return createValue() + \" in \" + createArrayLiteral(recurmax, stmtDepth, canThrow);\n      case p++:\n        return createValue() + \" in \" + createObjectLiteral(recurmax, stmtDepth, canThrow);\n      case p++:\n        var name = getVarName();\n        var prop = \"[\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"]\";\n        if (SUPPORT.optional_chaining && rng(50) == 0) return name + \"?.\" + prop;\n        if (canThrow && rng(20) == 0) return name + prop;\n        return name + \" && \" + name + prop;\n      case p++:\n        var name = getVarName();\n        var prop = getDotKey();\n        if (SUPPORT.optional_chaining && rng(50) == 0) return name + \"?.\" + prop;\n        if (canThrow && rng(20) == 0) return name + \".\" + prop;\n        return name + \" && \" + name + \".\" + prop;\n      case p++:\n      case p++:\n        var name = getVarName();\n        var fn = name + \".\" + getDotKey();\n        var s = \"typeof \" + fn + ' == \"function\" && --_calls_ >= 0 && ';\n        s += rng(5) ? fn : \"(\" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \", \" + fn + \")\";\n        s += createArgs(recurmax, stmtDepth, canThrow);\n        return mayDefer(canThrow && rng(20) == 0 ? s : name + \" && \" + s);\n      case p++:\n        if (SUPPORT.class) {\n            if (classes.length && rng(20) == 0) {\n                return \"--_calls_ >= 0 && new \" + classes[rng(classes.length)] + createArgs(recurmax, stmtDepth, canThrow, NO_TEMPLATE);\n            }\n            if (rng(200) == 0) {\n                var s = \"--_calls_ >= 0 && new \";\n                var nameLenBefore = VAR_NAMES.length;\n                var class_len = classes.length;\n                var name;\n                if (canThrow && rng(20) == 0) {\n                    in_class++;\n                    name = createVarName(MAYBE);\n                    in_class--;\n                } else if (rng(2)) {\n                    name = \"C\" + clazz++;\n                    classes.push(name);\n                }\n                s += createClassLiteral(recurmax, stmtDepth, canThrow, name);\n                classes.length = class_len;\n                VAR_NAMES.length = nameLenBefore;\n                s += createArgs(recurmax, stmtDepth, canThrow, NO_TEMPLATE);\n                return s;\n            }\n        }\n      case p++:\n      case p++:\n      case p++:\n        var name;\n        do {\n            name = rng(3) == 0 ? getVarName() : \"f\" + rng(funcs + 2);\n        } while (name in called && !called[name]);\n        called[name] = true;\n        var args = createArgs(recurmax, stmtDepth, canThrow);\n        var call = \"typeof \" + name + ' == \"function\" && --_calls_ >= 0 && ' + name + args;\n        if (canThrow) {\n            if (SUPPORT.optional_chaining && args[0] != \"`\" && rng(50) == 0) {\n                call = \"--_calls_ >= 0 && \" + name + \"?.\" + args;\n            } else if (rng(20) == 0) {\n                call = \"--_calls_ >= 0 && \" + name + args;\n            }\n        }\n        return mayDefer(call);\n    }\n    _createExpression.N = p;\n    return _createExpression(recurmax, noComma, stmtDepth, canThrow);\n}\n\nfunction createArrayLiteral(recurmax, stmtDepth, canThrow) {\n    recurmax--;\n    var arr = [];\n    for (var i = get_num(5); --i >= 0;) switch (SUPPORT.spread ? rng(50) : 3 + rng(47)) {\n      case 0:\n      case 1:\n        var name = getVarName();\n        if (canThrow && rng(20) == 0) {\n            arr.push(\"...\" + name);\n        } else {\n            arr.push('...(\"\" + ' + name + \")\");\n        }\n        break;\n      case 2:\n        arr.push(\"...\" + createArrayLiteral(recurmax, stmtDepth, canThrow));\n        break;\n      case 3:\n      case 4:\n        // in rare cases produce an array hole element\n        arr.push(\"\");\n        break;\n      default:\n        arr.push(createExpression(recurmax, COMMA_OK, stmtDepth, canThrow));\n        break;\n    }\n    return \"[\" + arr.join(\", \") + \"]\";\n}\n\nfunction createTemplateLiteral(recurmax, stmtDepth, canThrow) {\n    recurmax--;\n    var s = [];\n    addText();\n    for (var i = get_num(5); --i >= 0;) {\n        s.push(\"${\", createExpression(recurmax, COMMA_OK, stmtDepth, canThrow), \"}\");\n        addText();\n    }\n    return \"`\" + s.join(rng(5) ? \"\" : \"\\n\") + \"`\";\n\n    function addText() {\n        while (rng(5) == 0) s.push([\n            \" \",\n            \"$\",\n            \"}\",\n            \"\\\\`\",\n            \"\\\\\\\\\",\n            \"tmpl\",\n        ][rng(6)]);\n    }\n}\n\nvar SAFE_KEYS = [\n    \"a\",\n    \"b\",\n    \"c\",\n    \"foo\",\n    \"NaN\",\n    \"null\",\n    \"Infinity\",\n    \"undefined\",\n    \"async\",\n    \"done\",\n    \"get\",\n    \"in\",\n    \"length\",\n    \"next\",\n    \"set\",\n    \"static\",\n    \"then\",\n    \"value\",\n    \"var\",\n];\nvar KEYS = [\n    \"''\",\n    '\"\\t\"',\n    '\"-2\"',\n    \"0\",\n    \"1.5\",\n    \"3\",\n].concat(SAFE_KEYS);\nSAFE_KEYS = SAFE_KEYS.concat(SAFE_KEYS);\nSAFE_KEYS = SAFE_KEYS.concat(SAFE_KEYS);\nSAFE_KEYS = SAFE_KEYS.concat(SAFE_KEYS);\nSAFE_KEYS.push(\"__proto__\");\n\nfunction getDotKey(assign) {\n    var key;\n    do {\n        key = SAFE_KEYS[rng(SAFE_KEYS.length)];\n    } while (assign && key == \"length\");\n    return key;\n}\n\nfunction createObjectKey(recurmax, stmtDepth, canThrow) {\n    if (SUPPORT.computed_key && rng(10) == 0) {\n        return \"[\" + createExpression(recurmax, NO_COMMA, stmtDepth, canThrow) + \"]\";\n    }\n    return KEYS[rng(KEYS.length)];\n}\n\nfunction createSuperAssignment(recurmax, stmtDepth, canThrow) {\n    var s = rng(2) ? \"super.\" + getDotKey() : \"super[\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"]\";\n    return getVarName(NO_CONST, NO_LAMBDA) + createAssignment() + s + \";\";\n}\n\nfunction createThisAssignment(recurmax, stmtDepth, canThrow) {\n    var s = rng(2) ? \"this.\" + getDotKey(true) : \"this[\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \"]\";\n    return s + createAssignment() + _createBinaryExpr(recurmax, COMMA_OK, stmtDepth, canThrow) + \";\";\n}\n\nfunction createObjectFunction(recurmax, stmtDepth, canThrow, internal, isClazz) {\n    var nameLenBefore = VAR_NAMES.length;\n    var save_async = async;\n    var save_generator = generator;\n    var s;\n    var name;\n    if (internal) {\n        name = internal;\n    } else if (isClazz) {\n        var clazzName = classes.pop();\n        name = createObjectKey(recurmax, stmtDepth, canThrow);\n        classes.push(clazzName);\n    } else {\n        name = createObjectKey(recurmax, stmtDepth, canThrow);\n    }\n    var fn;\n    switch (internal ? 2 : rng(SUPPORT.computed_key ? 3 : 2)) {\n      case 0:\n        async = false;\n        generator = false;\n        fn = function(defns) {\n            s = [\n                \"get \" + name + \"(){\",\n                strictMode(),\n                defns(),\n                _createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),\n                createStatement(recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth, STMT_RETURN_ETC),\n                \"}\",\n            ];\n        };\n        break;\n      case 1:\n        var prop;\n        do {\n            prop = getDotKey();\n        } while (name == prop);\n        async = false;\n        generator = false;\n        fn = function(defns) {\n            s = [\n                \"set \" + name + \"(\" + createVarName(MANDATORY) + \"){\",\n                strictMode(),\n                defns(),\n                _createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth),\n                \"this.\" + prop + createAssignment() + _createBinaryExpr(recurmax, COMMA_OK, stmtDepth, canThrow) + \";\",\n                \"}\",\n            ];\n        };\n        break;\n      default:\n        if (/^(constructor|super)$/.test(internal)) {\n            async = false;\n            generator = false;\n            name = \"constructor\";\n        } else {\n            async = SUPPORT.async && rng(200) == 0;\n            generator = SUPPORT.generator && rng(50) == 0;\n            if (async && generator && !SUPPORT.async_generator) {\n                if (rng(2)) {\n                    async = false;\n                } else {\n                    generator = false;\n                }\n            }\n        }\n        fn = function(defns) {\n            if (generator) name = \"*\" + name;\n            if (async) name = \"async \"+ name;\n            var save_allow = allow_this;\n            if (internal == \"super\") allow_this = false;\n            s = [\n                name + \"(\" + createParams(save_async, save_generator, NO_DUPLICATE) + \"){\",\n                strictMode(),\n                defns(),\n            ];\n            s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth));\n            if (internal == \"super\") s.push(\"super\" + createArgs(recurmax, stmtDepth, canThrow, NO_TEMPLATE) + \";\");\n            allow_this = save_allow;\n            if (/^(constructor|super)$/.test(internal) || rng(10) == 0) for (var i = get_num(3); --i >= 0;) {\n                s.push(rng(2) ? createSuperAssignment(recurmax, stmtDepth, canThrow) : createThisAssignment(recurmax, stmtDepth, canThrow));\n            }\n            s.push(_createStatements(2, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CAN_RETURN, stmtDepth), \"}\");\n        };\n        break;\n    }\n    createBlockVariables(recurmax, stmtDepth, canThrow, fn);\n    generator = save_generator;\n    async = save_async;\n    VAR_NAMES.length = nameLenBefore;\n    return filterDirective(s).join(\"\\n\");\n}\n\nfunction createObjectLiteral(recurmax, stmtDepth, canThrow) {\n    recurmax--;\n    var obj = [ \"({\" ];\n    var offset = SUPPORT.spread_object ? 0 : SUPPORT.computed_key ? 2 : 4;\n    var has_proto = false;\n    for (var i = get_num(5); --i >= 0;) switch (offset + rng(50 - offset)) {\n      case 0:\n        obj.push(\"...\" + getVarName() + \",\");\n        break;\n      case 1:\n        obj.push(\"...\" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \",\");\n        break;\n      case 2:\n      case 3:\n        obj.push(getVarName() + \",\");\n        break;\n      case 4:\n        obj.push(createObjectFunction(recurmax, stmtDepth, canThrow) + \",\");\n        break;\n      default:\n        if (has_proto || rng(200)) {\n            obj.push(createObjectKey(recurmax, stmtDepth, canThrow) + \": \" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \",\");\n        } else {\n            obj.push(\"__proto__: \" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \" || {},\");\n            has_proto = true;\n        }\n        break;\n    }\n    obj.push(\"})\");\n    return obj.join(\"\\n\");\n}\n\nfunction createClassLiteral(recurmax, stmtDepth, canThrow, name) {\n    recurmax--;\n    var save_async = async;\n    var save_generator = generator;\n    in_class++;\n    var s = \"class\", constructor = \"constructor\";\n    var isClazz = /^C/.test(name);\n    if (name) s += \" \" + name;\n    if (rng(10) == 0) {\n        constructor = \"super\";\n        s += \" extends \";\n        var p = getVarName();\n        if (canThrow && rng(20) == 0) {\n            s += p;\n        } else {\n            s += \"(typeof \" + p + ' == \"function\" && typeof ' + p + '.prototype == \"object\" && ' + p + \".constructor === Function ? \" + p + \" : function() {})\";\n        }\n    }\n    s += \" {\\n\";\n    var declared = [];\n    for (var i = get_num(5); --i >= 0;) {\n        var fixed = false;\n        if (rng(5) == 0) {\n            fixed = true;\n            s += \"static \";\n        }\n        var internal = null;\n        if (SUPPORT.class_private && rng(10) == 0) {\n            do {\n                internal = \"#\" + getDotKey();\n            } while (declared.indexOf(internal) >= 0);\n            declared.push(internal);\n        }\n        if (SUPPORT.class_field && rng(2)) {\n            if (internal) {\n                s += internal;\n            } else if (fixed && bug_class_static_nontrivial) {\n                s += getDotKey();\n            } else {\n                s += createObjectKey(recurmax, stmtDepth, canThrow);\n            }\n            if (rng(5)) {\n                async = false;\n                generator = false;\n                s += \" = \" + createExpression(recurmax, NO_COMMA, stmtDepth, fixed ? canThrow : CANNOT_THROW);\n                generator = save_generator;\n                async = save_async;\n            }\n            s += \";\\n\";\n        } else if (SUPPORT.class_static_init && fixed && !internal && rng(10) == 0) {\n            async = false;\n            generator = false;\n            s += [\n                \"{ \",\n                createStatements(5, recurmax, canThrow, CANNOT_BREAK, CANNOT_CONTINUE, CANNOT_RETURN, stmtDepth),\n                \" }\\n\",\n            ].join(\"\");\n            generator = save_generator;\n            async = save_async;\n        } else {\n            if (!fixed && !internal && constructor && rng(10) == 0) {\n                internal = constructor;\n                constructor = null;\n            }\n            s += createObjectFunction(recurmax, stmtDepth, canThrow, internal, isClazz) + \"\\n\";\n        }\n    }\n    in_class--;\n    generator = save_generator;\n    async = save_async;\n    return s + \"}\";\n}\n\nfunction createNestedBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {\n    recurmax = 3; // note that this generates 2^recurmax expression parts... make sure to cap it\n    return _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow);\n}\nfunction _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {\n    return \"(\" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow)\n        + createBinaryOp(noComma, canThrow) + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + \")\";\n}\nfunction _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) {\n    // intentionally generate more hardcore ops\n    if (--recurmax < 0) return createValue();\n    var assignee, expr;\n    switch (rng(30)) {\n      case 0:\n        return \"(c = c + 1, \" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + \")\";\n      case 1:\n        return \"(\" + createUnarySafePrefix() + \"(\" + _createSimpleBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + \"))\";\n      case 2:\n        assignee = getVarName(NO_CONST, NO_LAMBDA);\n        return \"(\" + assignee + createAssignment() + _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow) + \")\";\n      case 3:\n        assignee = getVarName();\n        switch (SUPPORT.destructuring ? rng(20) : 2) {\n          case 0:\n            expr = [\n                \"([ \",\n                assignee,\n                \"[\", createExpression(recurmax, COMMA_OK, stmtDepth, canThrow), \"]\",\n                \" ] = [ \",\n                _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow),\n                \" ])\",\n            ].join(\"\");\n            break;\n          case 1:\n            var key1 = createObjectKey(recurmax, stmtDepth, canThrow);\n            var key2 = /^\\[/.test(key1) ? createObjectKey(recurmax, stmtDepth, canThrow) : key1;\n            expr = [\n                \"({ \",\n                key1, \": \", assignee,\n                \"[\", createExpression(recurmax, COMMA_OK, stmtDepth, canThrow), \"]\",\n                \" } = { \",\n                key2, \": \", _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow),\n                \" })\",\n            ].join(\"\");\n            break;\n          default:\n            expr = [\n                \"(\",\n                assignee,\n                \"[\", createExpression(recurmax, COMMA_OK, stmtDepth, canThrow), \"]\",\n                createAssignment(),\n                _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow),\n                \")\",\n            ].join(\"\");\n            break;\n        }\n        if (in_class) return \"(Object.isExtensible(\" + assignee + \") && \" + expr + \")\";\n        return canThrow && rng(20) == 0 ? expr : \"(\" + assignee + \" && \" + expr + \")\";\n      case 4:\n        assignee = getVarName();\n        switch (SUPPORT.destructuring ? rng(20) : 2) {\n          case 0:\n            expr = [\n                \"([ \",\n                assignee,\n                \".\", getDotKey(true),\n                \" ] = [ \",\n                _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow),\n                \" ])\",\n            ].join(\"\");\n            break;\n          case 1:\n            var key1 = createObjectKey(recurmax, stmtDepth, canThrow);\n            var key2 = /^\\[/.test(key1) ? createObjectKey(recurmax, stmtDepth, canThrow) : key1;\n            expr = [\n                \"({ \",\n                key1, \": \", assignee,\n                \".\", getDotKey(true),\n                \" } = { \",\n                key2, \": \", _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow),\n                \" })\",\n            ].join(\"\");\n            break;\n          default:\n            expr = [\n                \"(\",\n                assignee,\n                \".\", getDotKey(true),\n                createAssignment(),\n                _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow),\n                \")\",\n            ].join(\"\");\n            break;\n        }\n        if (in_class) return \"(Object.isExtensible(\" + assignee + \") && \" + expr + \")\";\n        return canThrow && rng(20) == 0 ? expr : \"(\" + assignee + \" && \" + expr + \")\";\n      default:\n        return _createBinaryExpr(recurmax, noComma, stmtDepth, canThrow);\n    }\n}\n\nfunction createTypeofExpr(recurmax, stmtDepth, canThrow) {\n    switch (rng(8)) {\n      case 0:\n        return \"(typeof \" + createVar() + ' === \"' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '\")';\n      case 1:\n        return \"(typeof \" + createVar() + ' !== \"' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '\")';\n      case 2:\n        return \"(typeof \" + createVar() + ' == \"' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '\")';\n      case 3:\n        return \"(typeof \" + createVar() + ' != \"' + TYPEOF_OUTCOMES[rng(TYPEOF_OUTCOMES.length)] + '\")';\n      case 4:\n        return \"(typeof \" + createVar() + \")\";\n      default:\n        return \"(typeof \" + createExpression(recurmax, COMMA_OK, stmtDepth, canThrow) + \")\";\n    }\n\n    function createVar() {\n        var save_async = async;\n        var save_generator = generator;\n        if (!async && avoid_vars.indexOf(\"await\") >= 0) async = true;\n        if (!generator && avoid_vars.indexOf(\"yield\") >= 0) generator = true;\n        var name = createVarName(MANDATORY, DONT_STORE);\n        generator = save_generator;\n        async = save_async;\n        return name;\n    }\n}\n\nfunction createValue() {\n    var v;\n    do {\n        v = VALUES[rng(VALUES.length)];\n    } while (v == \"new.target\" && rng(200) || !allow_this && v == \"this\");\n    return v;\n}\n\nfunction createBinaryOp(noComma, canThrow) {\n    var op;\n    do {\n        op = BINARY_OPS[rng(BINARY_OPS.length)];\n    } while (noComma && op == \",\" || !canThrow && /^ in/.test(op));\n    return op;\n}\n\nfunction createAssignment() {\n    return ASSIGNMENTS[rng(ASSIGNMENTS.length)];\n}\n\nfunction createUnarySafePrefix() {\n    var prefix;\n    do {\n        prefix = UNARY_SAFE[rng(UNARY_SAFE.length)];\n    } while (prefix == \"delete \" && in_class);\n    return prefix;\n}\n\nfunction createUnaryPrefix() {\n    var prefix;\n    do {\n        prefix = UNARY_PREFIX[rng(UNARY_PREFIX.length)];\n    } while (prefix == \"delete \" && in_class);\n    return prefix;\n}\n\nfunction createUnaryPostfix() {\n    return UNARY_POSTFIX[rng(UNARY_POSTFIX.length)];\n}\n\nfunction addAvoidVar(name) {\n    avoid_vars.push(name);\n}\n\nfunction removeAvoidVar(name) {\n    var index = avoid_vars.lastIndexOf(name);\n    if (index >= 0) avoid_vars.splice(index, 1);\n}\n\nfunction isBannedKeyword(name) {\n    switch (name) {\n      case \"arguments\":\n      case \"let\":\n        return in_class;\n      case \"await\":\n        return async || in_class && bug_class_static_await;\n      case \"yield\":\n        return generator || in_class;\n    }\n}\n\nfunction getVarName(noConst, noLambda) {\n    // try to get a generated name reachable from current scope. default to just `a`\n    var name, tries = 10;\n    do {\n        if (--tries < 0) return \"a\";\n        name = VAR_NAMES[INITIAL_NAMES_LEN + rng(VAR_NAMES.length - INITIAL_NAMES_LEN)];\n    } while (!name\n        || avoid_vars.indexOf(name) >= 0\n        || noConst && (block_vars.indexOf(name) >= 0\n            || in_class && [\n                \"Infinity\",\n                \"NaN\",\n                \"undefined\",\n            ].indexOf(name) >= 0)\n        || noLambda && lambda_vars.indexOf(name) >= 0\n        || isBannedKeyword(name));\n    return name;\n}\n\nfunction createVarName(maybe, dontStore) {\n    if (!maybe || rng(2)) {\n        var suffix = rng(3);\n        var name, tries = 10;\n        do {\n            name = VAR_NAMES[rng(VAR_NAMES.length)];\n            if (--tries < 0) suffix++;\n            if (suffix) name += \"_\" + suffix;\n        } while (unique_vars.indexOf(name) >= 0\n            || block_vars.indexOf(name) >= 0\n            || isBannedKeyword(name));\n        if (!dontStore) VAR_NAMES.push(name);\n        return name;\n    }\n    return \"\";\n}\n\nif (require.main !== module) {\n    exports.createTopLevelCode = function() {\n        var code = createTopLevelCode();\n        exports.module = async && has_await;\n        return code;\n    };\n    exports.num_iterations = num_iterations;\n    exports.verbose = verbose;\n    return;\n}\n\nfunction run_code(code, toplevel, timeout) {\n    return sandbox.run_code(sandbox.patch_module_statements(code, async && has_await), toplevel, timeout);\n}\n\nfunction writeln(stream, msg) {\n    if (typeof msg != \"undefined\") {\n        stream.write(typeof msg == \"string\" ? msg : msg.stack || \"\" + msg);\n    }\n    stream.write(\"\\n\");\n}\n\nfunction println(msg) {\n    writeln(process.stdout, msg);\n}\n\nfunction errorln(msg) {\n    writeln(process.stderr, msg);\n}\n\nfunction try_beautify(code, toplevel, result, printfn, options) {\n    var o = JSON.parse(beautify_options);\n    o.module = !!(async && has_await);\n    var beautified = UglifyJS.minify(code, o);\n    if (beautified.error) {\n        printfn(\"// !!! beautify failed !!!\");\n        printfn(beautified.error);\n        beautified = null;\n    } else if (!sandbox.same_stdout(run_code(beautified.code, toplevel), result)) {\n        beautified = null;\n    } else if (options) {\n        var uglified = UglifyJS.minify(beautified.code, JSON.parse(options));\n        var expected, actual;\n        if (sandbox.is_error(uglify_code) || uglified.error) {\n            expected = uglify_code;\n            actual = uglified.error;\n        } else {\n            expected = uglify_result;\n            actual = run_code(uglified.code, toplevel);\n        }\n        if (!sandbox.same_stdout(expected, actual)) {\n            beautified = null;\n        }\n    }\n    if (beautified) {\n        printfn(\"// (beautified)\");\n        printfn(beautified.code);\n    } else {\n        printfn(\"//\");\n        printfn(code);\n    }\n}\n\nvar default_options = UglifyJS.default_options();\n\nfunction log_suspects(minify_options, component) {\n    var options = component in minify_options ? minify_options[component] : true;\n    if (!options) return;\n    if (typeof options != \"object\") options = {};\n    var defs = default_options[component];\n    var toplevel = sandbox.has_toplevel(minify_options);\n    var suspects = Object.keys(defs).filter(function(name) {\n        var flip = component == \"compress\" && name == \"keep_fargs\"\n            || component == \"output\" && name == \"semicolons\";\n        if (flip !== (name in options ? options : defs)[name]) {\n            var m = JSON.parse(JSON.stringify(minify_options));\n            var o = JSON.parse(JSON.stringify(options));\n            o[name] = flip;\n            m[component] = o;\n            m.validate = true;\n            var result = UglifyJS.minify(original_code, m);\n            if (sandbox.is_error(uglify_code)) {\n                return !sandbox.same_stdout(uglify_code, result.error);\n            } else if (result.error) {\n                errorln(\"Error testing options.\" + component + \".\" + name);\n                errorln(result.error);\n            } else {\n                var r = run_code(result.code, toplevel);\n                return !sandbox.same_stdout(uglify_result, r);\n            }\n        }\n    });\n    if (suspects.length > 0) {\n        errorln(\"Suspicious \" + component + \" options:\");\n        suspects.forEach(function(name) {\n            errorln(\"  \" + name);\n        });\n        errorln();\n    }\n}\n\nfunction log_suspects_global(options, toplevel) {\n    var suspects = Object.keys(default_options).filter(function(component) {\n      return typeof default_options[component] != \"object\";\n    }).filter(function(component) {\n        var m = JSON.parse(options);\n        m[component] = false;\n        m.validate = true;\n        var result = UglifyJS.minify(original_code, m);\n        if (sandbox.is_error(uglify_code)) {\n            return !sandbox.same_stdout(uglify_code, result.error);\n        } else if (result.error) {\n            errorln(\"Error testing options.\" + component);\n            errorln(result.error);\n        } else {\n            var r = run_code(result.code, toplevel);\n            return !sandbox.same_stdout(uglify_result, r);\n        }\n    });\n    if (suspects.length > 0) {\n        errorln(\"Suspicious options:\");\n        suspects.forEach(function(name) {\n            errorln(\"  \" + name);\n        });\n        errorln();\n    }\n}\n\nfunction log(options) {\n    var toplevel = sandbox.has_toplevel(JSON.parse(options));\n    if (!ok) errorln(\"\\n\\n\\n\\n\\n\\n!!!!!!!!!!\\n\\n\\n\");\n    errorln(\"//=============================================================\");\n    if (!ok) errorln(\"// !!!!!! Failed... round \" + round);\n    errorln(\"// original code\");\n    try_beautify(original_code, toplevel, original_result, errorln, options);\n    errorln();\n    errorln();\n    errorln(\"//-------------------------------------------------------------\");\n    if (sandbox.is_error(uglify_code)) {\n        errorln(\"// !!! uglify failed !!!\");\n        errorln(uglify_code);\n        if (original_erred) {\n            errorln();\n            errorln();\n            errorln(\"original stacktrace:\");\n            errorln(original_result);\n        }\n    } else {\n        errorln(\"// uglified code\");\n        try_beautify(uglify_code, toplevel, uglify_result, errorln);\n        errorln();\n        errorln();\n        errorln(\"original result:\");\n        errorln(original_result);\n        errorln(\"uglified result:\");\n        errorln(uglify_result);\n    }\n    errorln(\"//-------------------------------------------------------------\");\n    if (!ok) {\n        var reduce_options = JSON.parse(options);\n        reduce_options.validate = true;\n        var reduced = reduce_test(original_code, reduce_options, {\n            max_timeout: max_timeout,\n            verbose: false,\n        }).code;\n        if (reduced) {\n            errorln();\n            errorln(\"// reduced test case (output will differ)\");\n            errorln();\n            errorln(reduced);\n            errorln();\n            errorln(\"//-------------------------------------------------------------\");\n        }\n    }\n    errorln(\"minify(options):\");\n    errorln(JSON.stringify(JSON.parse(options), null, 2));\n    errorln();\n    if (!ok) {\n        Object.keys(default_options).filter(function(component) {\n          var defs = default_options[component];\n          return defs && typeof defs == \"object\";\n        }).forEach(log_suspects.bind(null, JSON.parse(options)));\n        log_suspects_global(options, toplevel);\n        errorln(\"!!!!!! Failed... round \" + round);\n    }\n}\n\nfunction sort_globals(code) {\n    var injected = \"throw Object.keys(this).sort(\" + function(global) {\n        return function(m, n) {\n            return (typeof global[n] == \"function\") - (typeof global[m] == \"function\")\n                || (m < n ? -1 : m > n ? 1 : 0);\n        };\n    } + \"(this));\";\n    var save_async = async;\n    if (async && has_await) {\n        async = false;\n        injected = [\n            '\"use strict\";',\n            injected,\n            \"(async function(){\",\n            code,\n            \"})();\"\n        ].join(\"\\n\");\n    } else {\n        injected += \"\\n\" + code;\n    }\n    var globals = run_code(injected);\n    async = save_async;\n    if (!Array.isArray(globals)) {\n        errorln();\n        errorln();\n        errorln(\"//-------------------------------------------------------------\");\n        errorln(\"// !!! sort_globals() failed !!!\");\n        errorln(\"// expected Array, got:\");\n        if (!sandbox.is_error(globals)) try {\n            globals = JSON.stringify(globals);\n        } catch (e) {}\n        errorln(globals);\n        errorln(\"//\");\n        errorln(code);\n        errorln();\n        return code;\n    }\n    return globals.length ? \"var \" + globals.map(function(name) {\n        return name + \"=\" + name;\n    }).join() + \";\" + code : code;\n}\n\nfunction fuzzy_match(original, uglified) {\n    var m = [], n = [];\n    if (collect(original, m) !== collect(uglified, n)) return false;\n    for (var i = 0; i < m.length; i++) {\n        var a = m[i];\n        var b = n[i];\n        if (Math.abs((b - a) / a) > 1e-10) return false;\n    }\n    return true;\n\n    function collect(input, nums) {\n        return input.replace(/-?([1-9][0-9]*(\\.[0-9]+)?|0\\.[0-9]+)(e-?[1-9][0-9]*)?/gi, function(num) {\n            return \"<|\" + nums.push(+num) + \"|>\";\n        });\n    }\n}\n\nfunction patch_proto() {\n    [ Array, Boolean, Error, Function, Number, Object, RegExp, String ].forEach(function(type) {\n        [ \"toString\", \"valueOf\" ].forEach(function(prop) {\n            type.prototype[prop] = function(fn) {\n                return function() {\n                    try {\n                        return fn.apply(this, arguments);\n                    } catch (e) {}\n                };\n            }(type.prototype[prop]);\n        });\n    });\n}\n\nfunction is_error_timeout(ex) {\n    return /timed out/.test(ex.message);\n}\n\nfunction is_error_in(ex) {\n    return ex.name == \"TypeError\" && /'in'/.test(ex.message);\n}\n\nfunction is_error_tdz(ex) {\n    return ex.name == \"ReferenceError\";\n}\n\nfunction is_error_spread(ex) {\n    return ex.name == \"TypeError\" && /Found non-callable @@iterator| is not iterable| not a function|Symbol\\(Symbol\\.iterator\\)/.test(ex.message);\n}\n\nfunction is_error_recursion(ex) {\n    return ex.name == \"RangeError\" && /Invalid string length|Maximum call stack size exceeded/.test(ex.message);\n}\n\nfunction is_error_set_property(ex) {\n    return ex.name == \"TypeError\" && /^Cannot set propert[\\s\\S]+? of (null|undefined)/.test(ex.message);\n}\n\nfunction is_error_redeclaration(ex) {\n    return ex.name == \"SyntaxError\" && /already been declared|redeclaration/.test(ex.message);\n}\n\nfunction is_error_destructuring(ex) {\n    return ex.name == \"TypeError\" && /^Cannot (destructure|read propert)/.test(ex.message);\n}\n\nfunction is_error_class_constructor(ex) {\n    return ex.name == \"TypeError\" && /\\bconstructors?\\b/.test(ex.message) && /\\bnew\\b/.test(ex.message);\n}\n\nfunction is_error_getter_only_property(ex) {\n    return ex.name == \"TypeError\" && [ \"getter\", \"only\", \"property\" ].every(function(keyword) {\n        return ex.message.indexOf(keyword) >= 0;\n    });\n}\n\nfunction patch_try_catch(orig, toplevel) {\n    var patched = Object.create(null);\n    var patches = [];\n    var stack = [ {\n        code: orig,\n        index: 0,\n        offset: 0,\n        tries: [],\n    } ];\n    var tail_throw = '\\nif (typeof UFUZZ_ERROR == \"object\") throw UFUZZ_ERROR;\\n';\n    var re = /(?:(?:^|[\\s{}):;])try|}\\s*catch\\s*\\(([^()[{]+)\\)|}\\s*finally)\\s*(?={)/g;\n    while (stack.length) {\n        var code = stack[0].code;\n        var offset = stack[0].offset;\n        var tries = stack[0].tries;\n        var match;\n        re.lastIndex = stack.shift().index;\n        while (match = re.exec(code)) {\n            var index = match.index + match[0].length + 1;\n            if (/(?:^|[\\s{}):;])try\\s*$/.test(match[0])) {\n                tries.unshift({ try: index - offset });\n                continue;\n            }\n            var insert;\n            if (/}\\s*finally\\s*$/.test(match[0])) {\n                tries.shift();\n                insert = tail_throw;\n            } else {\n                while (tries.length && tries[0].catch) tries.shift();\n                tries[0].catch = index - offset;\n                insert = [\n                    \"if (!\" + match[1] + \".ufuzz_var) {\",\n                        match[1] + '.ufuzz_var = \"' + match[1] + '\";',\n                        match[1] + \".ufuzz_try = \" + tries[0].try + \";\",\n                        match[1] + \".ufuzz_catch = \" + tries[0].catch + \";\",\n                        \"UFUZZ_ERROR = \" + match[1] + \";\",\n                    \"}\",\n                    \"throw \" + match[1] + \";\",\n                ].join(\"\\n\");\n            }\n            var new_code = code.slice(0, index) + insert + code.slice(index) + tail_throw + \"var UFUZZ_ERROR;\";\n            var result = run_code(new_code, toplevel);\n            if (!sandbox.is_error(result)) {\n                if (!stack.filled && match[1]) stack.push({\n                    code: code,\n                    index: index && index - 1,\n                    offset: offset,\n                    tries: JSON.parse(JSON.stringify(tries)),\n                });\n                offset += insert.length;\n                code = new_code;\n            } else if (is_error_in(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"invalid `in`\");');\n            } else if (is_error_tdz(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"TDZ\");');\n            } else if (is_error_spread(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"spread not iterable\");');\n            } else if (is_error_recursion(result)) {\n                patch(result.ufuzz_try, 'throw new Error(\"skipping infinite recursion\");');\n            } else if (is_error_set_property(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"cannot set property\");');\n            } else if (is_error_destructuring(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"cannot destructure\");');\n            } else if (is_error_class_constructor(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"missing new for class\");');\n            } else if (is_error_getter_only_property(result)) {\n                patch(result.ufuzz_catch, result.ufuzz_var + ' = new Error(\"setting getter-only property\");');\n            }\n        }\n        stack.filled = true;\n    }\n    if (patches.length) return patches.reduce(function(code, patch) {\n        var index = patch[0];\n        return code.slice(0, index) + patch[1] + code.slice(index);\n    }, orig);\n\n    function patch(index, code) {\n        if (patched[index]) return;\n        patched[index] = true;\n        patches.unshift([ index, code ]);\n    }\n}\n\nvar beautify_options = {\n    compress: false,\n    mangle: false,\n    output: {\n        beautify: true,\n        braces: true,\n    },\n};\nvar minify_options = require(\"./options.json\");\nif (sandbox.is_error(sandbox.run_code(\"A:if (0) B:; else B:;\"))) {\n    minify_options.forEach(function(o) {\n        if (!(\"mangle\" in o)) o.mangle = {};\n        if (o.mangle) o.mangle.v8 = true;\n    });\n}\nvar bug_async_arrow_rest = function() {};\nif (SUPPORT.arrow && SUPPORT.async && SUPPORT.rest && sandbox.is_error(sandbox.run_code(\"async (a = f(...[], b)) => 0;\"))) {\n    bug_async_arrow_rest = function(ex) {\n        return ex.name == \"SyntaxError\" && ex.message == \"Rest parameter must be last formal parameter\";\n    };\n}\nvar bug_class_static_await = SUPPORT.async && SUPPORT.class_field && sandbox.is_error(sandbox.run_code(\"var await; class A { static p = await; }\"));\nvar bug_class_static_nontrivial = SUPPORT.class_field && sandbox.is_error(sandbox.run_code(\"class A { static 42; static get 42() {} }\"));\nvar bug_for_of_async = SUPPORT.for_await_of && sandbox.is_error(sandbox.run_code(\"var async; for (async of []);\"));\nvar bug_for_of_var = SUPPORT.for_of && SUPPORT.let && sandbox.is_error(sandbox.run_code(\"try {} catch (e) { for (var e of []); }\"));\nvar bug_proto_stream = function(ex) {\n    return ex.name == \"TypeError\" && ex.message == \"callback is not a function\";\n}\nif (SUPPORT.destructuring && sandbox.is_error(sandbox.run_code(\"console.log([ 1 ], {} = 2);\"))) {\n    beautify_options.output.v8 = true;\n    minify_options.forEach(function(o) {\n        if (!(\"output\" in o)) o.output = {};\n        o.output.v8 = true;\n    });\n}\nbeautify_options = JSON.stringify(beautify_options);\nminify_options = minify_options.map(JSON.stringify);\nvar original_code, original_result, original_erred;\nvar uglify_code, uglify_result, ok;\nvar max_timeout = 10000;\nfor (var round = 1; round <= num_iterations; round++) {\n    process.stdout.write(round + \" of \" + num_iterations + \"\\r\");\n\n    original_code = createTopLevelCode();\n    var orig_result = [ run_code(original_code), run_code(original_code, true) ];\n    if (orig_result.some(function(result, toplevel) {\n        if (!sandbox.is_error(result)) return;\n        println();\n        println();\n        println(\"//=============================================================\");\n        println(\"// original code\" + (toplevel ? \" (toplevel)\" : \"\"));\n        try_beautify(original_code, toplevel, result, println);\n        println();\n        println();\n        println(\"original result:\");\n        println(result);\n        println();\n        if (is_error_timeout(result)) orig_result[toplevel] = result = run_code(original_code, toplevel, max_timeout);\n        // skip over test cases which take too long to run\n        if (is_error_timeout(result)) return true;\n        // ignore v8 parser bug\n        if (bug_async_arrow_rest(result)) return true;\n        // ignore Node.js `__proto__` quirks\n        if (bug_proto_stream(result)) return true;\n        // ignore runtime platform bugs\n        if (result.message == \"Script execution aborted.\") return true;\n    })) {\n        num_iterations++;\n        continue;\n    }\n    minify_options.forEach(function(options) {\n        var o = JSON.parse(options);\n        if (async && has_await) {\n            o.module = true;\n            options = JSON.stringify(o);\n        }\n        var toplevel = sandbox.has_toplevel(o);\n        o.validate = true;\n        uglify_code = UglifyJS.minify(original_code, o);\n        original_result = orig_result[toplevel ? 1 : 0];\n        original_erred = sandbox.is_error(original_result);\n        if (!uglify_code.error) {\n            uglify_code = uglify_code.code;\n            uglify_result = run_code(uglify_code, toplevel);\n            ok = sandbox.same_stdout(original_result, uglify_result);\n            var uglify_erred = sandbox.is_error(uglify_result);\n            // ignore v8 parser bug\n            if (!ok && uglify_erred && bug_async_arrow_rest(uglify_result)) ok = true;\n            // ignore Node.js `__proto__` quirks\n            if (!ok && uglify_erred && bug_proto_stream(uglify_result)) ok = true;\n            // ignore runtime platform bugs\n            if (!ok && uglify_erred && uglify_result.message == \"Script execution aborted.\") ok = true;\n            // ignore spurious time-outs\n            if (!ok && uglify_erred && is_error_timeout(uglify_result)) {\n                var waited_result = run_code(uglify_code, toplevel, max_timeout);\n                ok = sandbox.same_stdout(original_result, waited_result);\n            }\n            // ignore declaration order of global variables\n            if (!ok && !toplevel) {\n                if (!(original_erred && original_result.name == \"SyntaxError\") && !(uglify_erred && uglify_result.name == \"SyntaxError\")) {\n                    ok = sandbox.same_stdout(run_code(sort_globals(original_code)), run_code(sort_globals(uglify_code)));\n                }\n            }\n            // ignore numerical imprecision caused by `unsafe_math`\n            if (!ok && o.compress && o.compress.unsafe_math) {\n                if (typeof original_result == \"string\" && typeof uglify_result == \"string\") {\n                    ok = fuzzy_match(original_result, uglify_result);\n                } else if (original_erred && uglify_erred) {\n                    ok = original_result.name == uglify_result.name && fuzzy_match(original_result.message, uglify_result.message);\n                }\n                if (!ok) {\n                    var fuzzy_result = run_code(original_code.replace(/( - 0\\.1){3}/g, \" - 0.3\"), toplevel);\n                    ok = sandbox.same_stdout(fuzzy_result, uglify_result);\n                }\n            }\n            if (!ok && original_erred && uglify_erred && (\n                // ignore difference in error message caused by `in`\n                is_error_in(original_result) && is_error_in(uglify_result)\n                // ignore difference in error message caused by Temporal Dead Zone\n                || is_error_tdz(original_result) && is_error_tdz(uglify_result)\n                // ignore difference in error message caused by spread syntax\n                || is_error_spread(original_result) && is_error_spread(uglify_result)\n                // ignore difference in error message caused by destructuring assignment\n                || is_error_set_property(original_result) && is_error_set_property(uglify_result)\n                // ignore difference in error message caused by `import` symbol redeclaration\n                || /\\bimport\\b/.test(original_code) && is_error_redeclaration(original_result) && is_error_redeclaration(uglify_result)\n                // ignore difference in error message caused by destructuring\n                || is_error_destructuring(original_result) && is_error_destructuring(uglify_result)\n                // ignore difference in error message caused by call on class\n                || is_error_class_constructor(original_result) && is_error_class_constructor(uglify_result)\n                // ignore difference in error message caused by setting getter-only property\n                || is_error_getter_only_property(original_result) && is_error_getter_only_property(uglify_result)\n            )) ok = true;\n            // ignore difference due to `__proto__` assignment\n            if (!ok && /\\b__proto__\\b/.test(original_code)) {\n                var original_proto = run_code(\"(\" + patch_proto + \")();\\n\" + original_code, toplevel);\n                var uglify_proto = run_code(\"(\" + patch_proto + \")();\\n\" + uglify_code, toplevel);\n                ok = sandbox.same_stdout(original_proto, uglify_proto);\n            }\n            // ignore difference in depth of termination caused by infinite recursion\n            if (!ok && original_erred && is_error_recursion(original_result)) {\n                if (!uglify_erred || is_error_recursion(uglify_result)) ok = true;\n            }\n            // ignore errors above when caught by try-catch\n            if (!ok) {\n                var orig_skipped = patch_try_catch(original_code, toplevel);\n                var uglify_skipped = patch_try_catch(uglify_code, toplevel);\n                if (orig_skipped && uglify_skipped) {\n                    ok = sandbox.same_stdout(run_code(orig_skipped, toplevel), run_code(uglify_skipped, toplevel));\n                }\n            }\n        } else {\n            uglify_code = uglify_code.error;\n            ok = original_erred && uglify_code.name == original_result.name;\n        }\n        if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);\n        if (!ok && isFinite(num_iterations)) {\n            println();\n            process.exit(1);\n        }\n    });\n}\nprintln();\n"
  },
  {
    "path": "test/ufuzz/job.js",
    "content": "var actions = require(\"./actions\");\nvar child_process = require(\"child_process\");\n\nvar args = [\n    \"--max-old-space-size=2048\",\n    \"test/ufuzz\",\n];\nvar iterations;\nswitch (process.argv.length) {\n  case 3:\n    iterations = +process.argv[2];\n    args.push(iterations);\n    break;\n  case 5:\n    actions.init(process.argv[2], process.argv[3], +process.argv[4]);\n    break;\n  default:\n    throw new Error(\"invalid parameters\");\n}\nvar tasks = [ run(), run() ];\nif (iterations) return;\nvar alive = setInterval(function() {\n    actions.should_stop(function() {\n        clearInterval(alive);\n        tasks.forEach(function(kill) {\n            kill();\n        });\n    });\n}, 8 * 60 * 1000);\n\nfunction run() {\n    var child, stdout, stderr, log;\n    spawn();\n    return function() {\n        clearInterval(log);\n        child.removeListener(\"exit\", respawn);\n        child.kill();\n    };\n\n    function spawn() {\n        child = child_process.spawn(\"node\", args, {\n            stdio: [ \"ignore\", \"pipe\", \"pipe\" ]\n        }).on(\"exit\", respawn);\n        stdout = \"\";\n        child.stdout.on(\"data\", function(data) {\n            stdout += data;\n        });\n        stderr = \"\";\n        child.stderr.on(\"data\", trap).pipe(process.stdout);\n        log = setInterval(function() {\n            stdout = stdout.replace(/[^\\r\\n]+\\r(?=[^\\r\\n]+\\r)/g, \"\");\n            var end = stdout.lastIndexOf(\"\\r\");\n            if (end < 0) return;\n            console.log(stdout.slice(0, end));\n            stdout = stdout.slice(end + 1);\n        }, 5 * 60 * 1000);\n    }\n\n    function respawn() {\n        console.log(stdout.replace(/[^\\r\\n]*\\r/g, \"\"));\n        clearInterval(log);\n        if (!iterations) {\n            spawn();\n        } else if (process.exitCode) {\n            tasks.forEach(function(kill) {\n                kill();\n            });\n        }\n    }\n\n    function trap(data) {\n        stderr += data;\n        if (~stderr.indexOf(\"!!!!!! Failed... round \")) {\n            process.exitCode = 1;\n            child.stderr.removeListener(\"data\", trap);\n        }\n    }\n}\n"
  },
  {
    "path": "test/ufuzz/options.json",
    "content": "[\n    {\n        \"compress\": false,\n        \"mangle\": false,\n        \"module\": false,\n        \"output\": {\n            \"beautify\": true,\n            \"braces\": true\n        },\n        \"rename\": true\n    },\n    {\n        \"compress\": false,\n        \"module\": false\n    },\n    {\n        \"mangle\": false,\n        \"module\": false\n    },\n    {\n        \"module\": false\n    },\n    {\n        \"ie\": true,\n        \"module\": false,\n        \"output\": {\n            \"semicolons\": false\n        },\n        \"toplevel\": true\n    },\n    {\n        \"compress\": {\n            \"hoist_vars\": true,\n            \"keep_infinity\": true,\n            \"passes\": 1e6,\n            \"unsafe\": true\n        },\n        \"keep_fargs\": true,\n        \"keep_fnames\": true,\n        \"module\": false,\n        \"toplevel\": true\n    },\n    {\n        \"compress\": {\n            \"passes\": 1e6,\n            \"sequences\": 1e6,\n            \"unsafe\": true,\n            \"unsafe_Function\": true,\n            \"unsafe_math\": true,\n            \"unsafe_proto\": true,\n            \"unsafe_regexp\": true\n        },\n        \"module\": false\n    }\n]\n"
  },
  {
    "path": "tools/domprops.html",
    "content": "<!doctype html>\n<html>\n<body>\n    <script>\n        !function(G) {\n            var domprops = [];\n            var objs = [ G ];\n            var tagNames = [\n                \"a\",\n                \"abbr\",\n                \"acronym\",\n                \"address\",\n                \"applet\",\n                \"area\",\n                \"article\",\n                \"aside\",\n                \"audio\",\n                \"b\",\n                \"base\",\n                \"basefont\",\n                \"bdi\",\n                \"bdo\",\n                \"bgsound\",\n                \"big\",\n                \"blink\",\n                \"blockquote\",\n                \"body\",\n                \"br\",\n                \"button\",\n                \"canvas\",\n                \"caption\",\n                \"center\",\n                \"checked\",\n                \"cite\",\n                \"code\",\n                \"col\",\n                \"colgroup\",\n                \"command\",\n                \"comment\",\n                \"compact\",\n                \"content\",\n                \"data\",\n                \"datalist\",\n                \"dd\",\n                \"declare\",\n                \"defer\",\n                \"del\",\n                \"details\",\n                \"dfn\",\n                \"dialog\",\n                \"dir\",\n                \"disabled\",\n                \"div\",\n                \"dl\",\n                \"dt\",\n                \"element\",\n                \"em\",\n                \"embed\",\n                \"fieldset\",\n                \"figcaption\",\n                \"figure\",\n                \"font\",\n                \"footer\",\n                \"form\",\n                \"frame\",\n                \"frameset\",\n                \"h1\",\n                \"h2\",\n                \"h3\",\n                \"h4\",\n                \"h5\",\n                \"h6\",\n                \"head\",\n                \"header\",\n                \"hgroup\",\n                \"hr\",\n                \"html\",\n                \"i\",\n                \"iframe\",\n                \"image\",\n                \"img\",\n                \"input\",\n                \"ins\",\n                \"isindex\",\n                \"ismap\",\n                \"kbd\",\n                \"keygen\",\n                \"label\",\n                \"legend\",\n                \"li\",\n                \"link\",\n                \"listing\",\n                \"main\",\n                \"map\",\n                \"mark\",\n                \"marquee\",\n                \"math\",\n                \"menu\",\n                \"menuitem\",\n                \"meta\",\n                \"meter\",\n                \"multicol\",\n                \"multiple\",\n                \"nav\",\n                \"nextid\",\n                \"nobr\",\n                \"noembed\",\n                \"noframes\",\n                \"nohref\",\n                \"noresize\",\n                \"noscript\",\n                \"noshade\",\n                \"nowrap\",\n                \"object\",\n                \"ol\",\n                \"optgroup\",\n                \"option\",\n                \"output\",\n                \"p\",\n                \"param\",\n                \"picture\",\n                \"plaintext\",\n                \"pre\",\n                \"progress\",\n                \"q\",\n                \"rb\",\n                \"readonly\",\n                \"rp\",\n                \"rt\",\n                \"rtc\",\n                \"ruby\",\n                \"s\",\n                \"samp\",\n                \"script\",\n                \"section\",\n                \"select\",\n                \"selected\",\n                \"shadow\",\n                \"slot\",\n                \"small\",\n                \"source\",\n                \"spacer\",\n                \"span\",\n                \"strike\",\n                \"strong\",\n                \"style\",\n                \"sub\",\n                \"summary\",\n                \"sup\",\n                \"svg\",\n                \"table\",\n                \"tbody\",\n                \"td\",\n                \"template\",\n                \"textarea\",\n                \"tfoot\",\n                \"th\",\n                \"thead\",\n                \"time\",\n                \"title\",\n                \"tr\",\n                \"track\",\n                \"tt\",\n                \"u\",\n                \"ul\",\n                \"var\",\n                \"video\",\n                \"wbr\",\n                \"xmp\",\n                \"XXX\",\n            ];\n            for (var n = 0; n < tagNames.length; n++) {\n                add(document.createElement(tagNames[n]));\n            }\n            var nsNames = {\n                \"http://www.w3.org/1998/Math/MathML\": [\n                    \"annotation\",\n                    \"annotation-xml\",\n                    \"maction\",\n                    \"maligngroup\",\n                    \"malignmark\",\n                    \"math\",\n                    \"menclose\",\n                    \"merror\",\n                    \"mfenced\",\n                    \"mfrac\",\n                    \"mglyph\",\n                    \"mi\",\n                    \"mlabeledtr\",\n                    \"mlongdiv\",\n                    \"mmultiscripts\",\n                    \"mn\",\n                    \"mo\",\n                    \"mover\",\n                    \"mpadded\",\n                    \"mphantom\",\n                    \"mprescripts\",\n                    \"mroot\",\n                    \"mrow\",\n                    \"ms\",\n                    \"mscarries\",\n                    \"mscarry\",\n                    \"msgroup\",\n                    \"msline\",\n                    \"mspace\",\n                    \"msqrt\",\n                    \"msrow\",\n                    \"mstack\",\n                    \"mstyle\",\n                    \"msub\",\n                    \"msubsup\",\n                    \"msup\",\n                    \"mtable\",\n                    \"mtd\",\n                    \"mtext\",\n                    \"mtr\",\n                    \"munder\",\n                    \"munderover\",\n                    \"none\",\n                    \"semantics\",\n                ],\n                \"http://www.w3.org/2000/svg\": [\n                    \"a\",\n                    \"altGlyph\",\n                    \"altGlyphDef\",\n                    \"altGlyphItem\",\n                    \"animate\",\n                    \"animateColor\",\n                    \"animateMotion\",\n                    \"animateTransform\",\n                    \"circle\",\n                    \"clipPath\",\n                    \"color-profile\",\n                    \"cursor\",\n                    \"defs\",\n                    \"desc\",\n                    \"discard\",\n                    \"ellipse\",\n                    \"feBlend\",\n                    \"feColorMatrix\",\n                    \"feComponentTransfer\",\n                    \"feComposite\",\n                    \"feConvolveMatrix\",\n                    \"feDiffuseLighting\",\n                    \"feDisplacementMap\",\n                    \"feDistantLight\",\n                    \"feDropShadow\",\n                    \"feFlood\",\n                    \"feFuncA\",\n                    \"feFuncB\",\n                    \"feFuncG\",\n                    \"feFuncR\",\n                    \"feGaussianBlur\",\n                    \"feImage\",\n                    \"feMerge\",\n                    \"feMergeNode\",\n                    \"feMorphology\",\n                    \"feOffset\",\n                    \"fePointLight\",\n                    \"feSpecularLighting\",\n                    \"feSpotLight\",\n                    \"feTile\",\n                    \"feTurbulence\",\n                    \"filter\",\n                    \"font\",\n                    \"font-face\",\n                    \"font-face-format\",\n                    \"font-face-name\",\n                    \"font-face-src\",\n                    \"font-face-uri\",\n                    \"foreignObject\",\n                    \"g\",\n                    \"glyph\",\n                    \"glyphRef\",\n                    \"hatch\",\n                    \"hatchpath\",\n                    \"hkern\",\n                    \"image\",\n                    \"line\",\n                    \"linearGradient\",\n                    \"marker\",\n                    \"mask\",\n                    \"mesh\",\n                    \"meshgradient\",\n                    \"meshpatch\",\n                    \"meshrow\",\n                    \"metadata\",\n                    \"missing-glyph\",\n                    \"mpath\",\n                    \"path\",\n                    \"pattern\",\n                    \"polygon\",\n                    \"polyline\",\n                    \"radialGradient\",\n                    \"rect\",\n                    \"script\",\n                    \"set\",\n                    \"solidcolor\",\n                    \"stop\",\n                    \"style\",\n                    \"svg\",\n                    \"switch\",\n                    \"symbol\",\n                    \"text\",\n                    \"textPath\",\n                    \"title\",\n                    \"tref\",\n                    \"tspan\",\n                    \"unknown\",\n                    \"use\",\n                    \"view\",\n                    \"vkern\",\n                ],\n            };\n            if (document.createElementNS) for (var ns in nsNames) {\n                for (var n = 0; n < nsNames[ns].length; n++) {\n                    add(document.createElementNS(ns, nsNames[ns][n]));\n                }\n            }\n            var skips = [\n                G.alert,\n                G.back,\n                G.blur,\n                G.captureEvents,\n                G.clearImmediate,\n                G.clearInterval,\n                G.clearTimeout,\n                G.close,\n                G.confirm,\n                G.console,\n                G.dump,\n                G.fetch,\n                G.find,\n                G.focus,\n                G.forward,\n                G.getAttention,\n                G.history,\n                G.home,\n                G.location,\n                G.moveBy,\n                G.moveTo,\n                G.navigator,\n                G.open,\n                G.openDialog,\n                G.print,\n                G.process,\n                G.prompt,\n                G.resizeBy,\n                G.resizeTo,\n                G.setImmediate,\n                G.setInterval,\n                G.setTimeout,\n                G.showModalDialog,\n                G.sizeToContent,\n                G.stop,\n            ];\n            var types = [];\n            var interfaces = [\n                \"beforeunloadevent\",\n                \"compositionevent\",\n                \"customevent\",\n                \"devicemotionevent\",\n                \"deviceorientationevent\",\n                \"dragevent\",\n                \"event\",\n                \"events\",\n                \"focusevent\",\n                \"hashchangeevent\",\n                \"htmlevents\",\n                \"keyboardevent\",\n                \"messageevent\",\n                \"mouseevent\",\n                \"mouseevents\",\n                \"storageevent\",\n                \"svgevents\",\n                \"textevent\",\n                \"touchevent\",\n                \"uievent\",\n                \"uievents\",\n            ];\n            var i = 0, full = false;\n            var addEvent = document.createEvent ? function(type) {\n                if (~indexOf(types, type)) return;\n                types.push(type);\n                for (var j = 0; j < interfaces.length; j++) try {\n                    var event = document.createEvent(interfaces[j]);\n                    event.initEvent(type, true, true);\n                    add(event);\n                } catch (e) {}\n            } : function() {};\n            var scanProperties = Object.getOwnPropertyNames ? function(o, fn) {\n                var names = Object.getOwnPropertyNames(o);\n                names.forEach(fn);\n                for (var k in o) if (!~indexOf(names, k)) fn(k);\n            } : function(o, fn) {\n                for (var k in o) fn(k);\n            };\n            setTimeout(function next() {\n                for (var j = 10; --j >= 0 && i < objs.length; i++) {\n                    var o = objs[i];\n                    var skip = ~indexOf(skips, o);\n                    try {\n                        scanProperties(o, function(k) {\n                            if (!~indexOf(domprops, k)) domprops.push(k);\n                            if (/^on/.test(k)) addEvent(k.slice(2));\n                            if (!full) try {\n                                add(o[k]);\n                            } catch (e) {}\n                        });\n                    } catch (e) {}\n                    if (skip || full) continue;\n                    try {\n                        add(o.__proto__);\n                    } catch (e) {}\n                    try {\n                        add(o.prototype);\n                    } catch (e) {}\n                    try {\n                        add(new o());\n                    } catch (e) {}\n                    try {\n                        add(o());\n                    } catch (e) {}\n                }\n                if (!full && objs.length > 20000) {\n                    alert(objs.length);\n                    full = true;\n                }\n                if (i < objs.length) {\n                    setTimeout(next, 0);\n                } else {\n                    document.write('<pre>[\\n    \"' + domprops.sort().join('\",\\n    \"').replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\") + '\"\\n]</pre>');\n                }\n            }, 0);\n\n            function add(o) {\n                if (o) switch (typeof o) {\n                case \"function\":\n                case \"object\":\n                    if (!~indexOf(objs, o)) objs.push(o);\n                }\n            }\n\n            function indexOf(list, value) {\n                var j = list.length;\n                while (--j >= 0) {\n                    if (list[j] === value) break;\n                }\n                return j;\n            }\n        }(function() {\n            return this;\n        }());\n    </script>\n</body>\n</html>\n"
  },
  {
    "path": "tools/domprops.json",
    "content": "[\n    \"$&\",\n    \"$'\",\n    \"$*\",\n    \"$+\",\n    \"$1\",\n    \"$2\",\n    \"$3\",\n    \"$4\",\n    \"$5\",\n    \"$6\",\n    \"$7\",\n    \"$8\",\n    \"$9\",\n    \"$_\",\n    \"$`\",\n    \"$input\",\n    \"-moz-animation\",\n    \"-moz-animation-delay\",\n    \"-moz-animation-direction\",\n    \"-moz-animation-duration\",\n    \"-moz-animation-fill-mode\",\n    \"-moz-animation-iteration-count\",\n    \"-moz-animation-name\",\n    \"-moz-animation-play-state\",\n    \"-moz-animation-timing-function\",\n    \"-moz-appearance\",\n    \"-moz-backface-visibility\",\n    \"-moz-binding\",\n    \"-moz-border-end\",\n    \"-moz-border-end-color\",\n    \"-moz-border-end-style\",\n    \"-moz-border-end-width\",\n    \"-moz-border-image\",\n    \"-moz-border-start\",\n    \"-moz-border-start-color\",\n    \"-moz-border-start-style\",\n    \"-moz-border-start-width\",\n    \"-moz-box-align\",\n    \"-moz-box-direction\",\n    \"-moz-box-flex\",\n    \"-moz-box-ordinal-group\",\n    \"-moz-box-orient\",\n    \"-moz-box-pack\",\n    \"-moz-box-sizing\",\n    \"-moz-column-count\",\n    \"-moz-column-fill\",\n    \"-moz-column-gap\",\n    \"-moz-column-rule\",\n    \"-moz-column-rule-color\",\n    \"-moz-column-rule-style\",\n    \"-moz-column-rule-width\",\n    \"-moz-column-width\",\n    \"-moz-columns\",\n    \"-moz-float-edge\",\n    \"-moz-font-feature-settings\",\n    \"-moz-font-language-override\",\n    \"-moz-force-broken-image-icon\",\n    \"-moz-hyphens\",\n    \"-moz-image-region\",\n    \"-moz-margin-end\",\n    \"-moz-margin-start\",\n    \"-moz-orient\",\n    \"-moz-outline-radius\",\n    \"-moz-outline-radius-bottomleft\",\n    \"-moz-outline-radius-bottomright\",\n    \"-moz-outline-radius-topleft\",\n    \"-moz-outline-radius-topright\",\n    \"-moz-padding-end\",\n    \"-moz-padding-start\",\n    \"-moz-perspective\",\n    \"-moz-perspective-origin\",\n    \"-moz-stack-sizing\",\n    \"-moz-tab-size\",\n    \"-moz-text-size-adjust\",\n    \"-moz-transform\",\n    \"-moz-transform-origin\",\n    \"-moz-transform-style\",\n    \"-moz-transition\",\n    \"-moz-transition-delay\",\n    \"-moz-transition-duration\",\n    \"-moz-transition-property\",\n    \"-moz-transition-timing-function\",\n    \"-moz-user-focus\",\n    \"-moz-user-input\",\n    \"-moz-user-modify\",\n    \"-moz-user-select\",\n    \"-moz-window-dragging\",\n    \"-webkit-align-content\",\n    \"-webkit-align-items\",\n    \"-webkit-align-self\",\n    \"-webkit-animation\",\n    \"-webkit-animation-delay\",\n    \"-webkit-animation-direction\",\n    \"-webkit-animation-duration\",\n    \"-webkit-animation-fill-mode\",\n    \"-webkit-animation-iteration-count\",\n    \"-webkit-animation-name\",\n    \"-webkit-animation-play-state\",\n    \"-webkit-animation-timing-function\",\n    \"-webkit-appearance\",\n    \"-webkit-backface-visibility\",\n    \"-webkit-background-clip\",\n    \"-webkit-background-origin\",\n    \"-webkit-background-size\",\n    \"-webkit-border-bottom-left-radius\",\n    \"-webkit-border-bottom-right-radius\",\n    \"-webkit-border-image\",\n    \"-webkit-border-radius\",\n    \"-webkit-border-top-left-radius\",\n    \"-webkit-border-top-right-radius\",\n    \"-webkit-box-align\",\n    \"-webkit-box-direction\",\n    \"-webkit-box-flex\",\n    \"-webkit-box-ordinal-group\",\n    \"-webkit-box-orient\",\n    \"-webkit-box-pack\",\n    \"-webkit-box-shadow\",\n    \"-webkit-box-sizing\",\n    \"-webkit-filter\",\n    \"-webkit-flex\",\n    \"-webkit-flex-basis\",\n    \"-webkit-flex-direction\",\n    \"-webkit-flex-flow\",\n    \"-webkit-flex-grow\",\n    \"-webkit-flex-shrink\",\n    \"-webkit-flex-wrap\",\n    \"-webkit-justify-content\",\n    \"-webkit-line-clamp\",\n    \"-webkit-mask\",\n    \"-webkit-mask-clip\",\n    \"-webkit-mask-composite\",\n    \"-webkit-mask-image\",\n    \"-webkit-mask-origin\",\n    \"-webkit-mask-position\",\n    \"-webkit-mask-position-x\",\n    \"-webkit-mask-position-y\",\n    \"-webkit-mask-repeat\",\n    \"-webkit-mask-size\",\n    \"-webkit-order\",\n    \"-webkit-perspective\",\n    \"-webkit-perspective-origin\",\n    \"-webkit-text-fill-color\",\n    \"-webkit-text-size-adjust\",\n    \"-webkit-text-stroke\",\n    \"-webkit-text-stroke-color\",\n    \"-webkit-text-stroke-width\",\n    \"-webkit-transform\",\n    \"-webkit-transform-origin\",\n    \"-webkit-transform-style\",\n    \"-webkit-transition\",\n    \"-webkit-transition-delay\",\n    \"-webkit-transition-duration\",\n    \"-webkit-transition-property\",\n    \"-webkit-transition-timing-function\",\n    \"-webkit-user-select\",\n    \"0\",\n    \"1\",\n    \"10\",\n    \"11\",\n    \"12\",\n    \"13\",\n    \"14\",\n    \"15\",\n    \"16\",\n    \"17\",\n    \"18\",\n    \"19\",\n    \"2\",\n    \"20\",\n    \"21\",\n    \"22\",\n    \"23\",\n    \"24\",\n    \"25\",\n    \"26\",\n    \"27\",\n    \"28\",\n    \"29\",\n    \"3\",\n    \"30\",\n    \"31\",\n    \"32\",\n    \"33\",\n    \"34\",\n    \"35\",\n    \"36\",\n    \"37\",\n    \"38\",\n    \"39\",\n    \"4\",\n    \"40\",\n    \"41\",\n    \"42\",\n    \"43\",\n    \"44\",\n    \"45\",\n    \"46\",\n    \"47\",\n    \"48\",\n    \"49\",\n    \"5\",\n    \"50\",\n    \"51\",\n    \"6\",\n    \"7\",\n    \"8\",\n    \"9\",\n    \"@@iterator\",\n    \"ABORT_ERR\",\n    \"ACTIVE\",\n    \"ACTIVE_ATTRIBUTES\",\n    \"ACTIVE_TEXTURE\",\n    \"ACTIVE_UNIFORMS\",\n    \"ACTIVE_UNIFORM_BLOCKS\",\n    \"ADDITION\",\n    \"ALIASED_LINE_WIDTH_RANGE\",\n    \"ALIASED_POINT_SIZE_RANGE\",\n    \"ALLOW_KEYBOARD_INPUT\",\n    \"ALLPASS\",\n    \"ALPHA\",\n    \"ALPHA_BITS\",\n    \"ALREADY_SIGNALED\",\n    \"ALT_MASK\",\n    \"ALWAYS\",\n    \"ANDROID\",\n    \"ANGLE_instanced_arrays\",\n    \"ANY_SAMPLES_PASSED\",\n    \"ANY_SAMPLES_PASSED_CONSERVATIVE\",\n    \"ANY_TYPE\",\n    \"ANY_UNORDERED_NODE_TYPE\",\n    \"APP_UPDATE\",\n    \"ARM\",\n    \"ARRAY_BUFFER\",\n    \"ARRAY_BUFFER_BINDING\",\n    \"ATTACHED_SHADERS\",\n    \"ATTRIBUTE_NODE\",\n    \"AT_TARGET\",\n    \"AbortController\",\n    \"AbortSignal\",\n    \"AbsoluteOrientationSensor\",\n    \"AbstractRange\",\n    \"Accelerometer\",\n    \"ActiveXObject\",\n    \"AddSearchProvider\",\n    \"AesGcmEncryptResult\",\n    \"AggregateError\",\n    \"AnalyserNode\",\n    \"Animation\",\n    \"AnimationEffect\",\n    \"AnimationEvent\",\n    \"AnimationPlaybackEvent\",\n    \"AnimationTimeline\",\n    \"AnonXMLHttpRequest\",\n    \"AppBannerPromptResult\",\n    \"ApplicationCache\",\n    \"ApplicationCacheErrorEvent\",\n    \"Array\",\n    \"ArrayBuffer\",\n    \"Atomics\",\n    \"Attr\",\n    \"Audio\",\n    \"AudioBuffer\",\n    \"AudioBufferSourceNode\",\n    \"AudioContext\",\n    \"AudioDestinationNode\",\n    \"AudioListener\",\n    \"AudioNode\",\n    \"AudioParam\",\n    \"AudioParamMap\",\n    \"AudioProcessingEvent\",\n    \"AudioScheduledSourceNode\",\n    \"AudioStreamTrack\",\n    \"AudioTrack\",\n    \"AudioTrackList\",\n    \"AudioWorklet\",\n    \"AudioWorkletNode\",\n    \"AuthenticatorAssertionResponse\",\n    \"AuthenticatorAttestationResponse\",\n    \"AuthenticatorResponse\",\n    \"AutocompleteErrorEvent\",\n    \"BACK\",\n    \"BAD_BOUNDARYPOINTS_ERR\",\n    \"BAD_REQUEST\",\n    \"BANDPASS\",\n    \"BLEND\",\n    \"BLEND_COLOR\",\n    \"BLEND_DST_ALPHA\",\n    \"BLEND_DST_RGB\",\n    \"BLEND_EQUATION\",\n    \"BLEND_EQUATION_ALPHA\",\n    \"BLEND_EQUATION_RGB\",\n    \"BLEND_SRC_ALPHA\",\n    \"BLEND_SRC_RGB\",\n    \"BLUE_BITS\",\n    \"BLUR\",\n    \"BOOL\",\n    \"BOOLEAN_TYPE\",\n    \"BOOL_VEC2\",\n    \"BOOL_VEC3\",\n    \"BOOL_VEC4\",\n    \"BOTH\",\n    \"BROWSER_DEFAULT_WEBGL\",\n    \"BUBBLING_PHASE\",\n    \"BUFFER_SIZE\",\n    \"BUFFER_USAGE\",\n    \"BYTE\",\n    \"BYTES_PER_ELEMENT\",\n    \"BackgroundFetchManager\",\n    \"BackgroundFetchRecord\",\n    \"BackgroundFetchRegistration\",\n    \"BarProp\",\n    \"BarcodeDetector\",\n    \"BaseAudioContext\",\n    \"BaseHref\",\n    \"BatteryManager\",\n    \"BeforeInstallPromptEvent\",\n    \"BeforeLoadEvent\",\n    \"BeforeUnloadEvent\",\n    \"BigInt\",\n    \"BigInt64Array\",\n    \"BigUint64Array\",\n    \"BiquadFilterNode\",\n    \"Blob\",\n    \"BlobEvent\",\n    \"Bluetooth\",\n    \"BluetoothCharacteristicProperties\",\n    \"BluetoothDevice\",\n    \"BluetoothRemoteGATTCharacteristic\",\n    \"BluetoothRemoteGATTDescriptor\",\n    \"BluetoothRemoteGATTServer\",\n    \"BluetoothRemoteGATTService\",\n    \"BluetoothUUID\",\n    \"BookmarkCollection\",\n    \"Boolean\",\n    \"BroadcastChannel\",\n    \"ByteLengthQueuingStrategy\",\n    \"CANNOT_RUN\",\n    \"CAPTURING_PHASE\",\n    \"CCW\",\n    \"CDATASection\",\n    \"CDATA_SECTION_NODE\",\n    \"CHANGE\",\n    \"CHARSET_RULE\",\n    \"CHECKING\",\n    \"CHROME_UPDATE\",\n    \"CLAMP_TO_EDGE\",\n    \"CLICK\",\n    \"CLOSED\",\n    \"CLOSING\",\n    \"COLOR\",\n    \"COLOR_ATTACHMENT0\",\n    \"COLOR_ATTACHMENT1\",\n    \"COLOR_ATTACHMENT10\",\n    \"COLOR_ATTACHMENT11\",\n    \"COLOR_ATTACHMENT12\",\n    \"COLOR_ATTACHMENT13\",\n    \"COLOR_ATTACHMENT14\",\n    \"COLOR_ATTACHMENT15\",\n    \"COLOR_ATTACHMENT2\",\n    \"COLOR_ATTACHMENT3\",\n    \"COLOR_ATTACHMENT4\",\n    \"COLOR_ATTACHMENT5\",\n    \"COLOR_ATTACHMENT6\",\n    \"COLOR_ATTACHMENT7\",\n    \"COLOR_ATTACHMENT8\",\n    \"COLOR_ATTACHMENT9\",\n    \"COLOR_BUFFER_BIT\",\n    \"COLOR_CLEAR_VALUE\",\n    \"COLOR_WRITEMASK\",\n    \"COMMENT_NODE\",\n    \"COMPARE_REF_TO_TEXTURE\",\n    \"COMPILE_STATUS\",\n    \"COMPRESSED_RGBA_S3TC_DXT1_EXT\",\n    \"COMPRESSED_RGBA_S3TC_DXT3_EXT\",\n    \"COMPRESSED_RGBA_S3TC_DXT5_EXT\",\n    \"COMPRESSED_RGB_S3TC_DXT1_EXT\",\n    \"COMPRESSED_TEXTURE_FORMATS\",\n    \"CONDITION_SATISFIED\",\n    \"CONFIGURATION_UNSUPPORTED\",\n    \"CONNECTING\",\n    \"CONSTANT_ALPHA\",\n    \"CONSTANT_COLOR\",\n    \"CONSTRAINT_ERR\",\n    \"CONTENT\",\n    \"CONTEXT_LOST_WEBGL\",\n    \"CONTROL_MASK\",\n    \"COPY_READ_BUFFER\",\n    \"COPY_READ_BUFFER_BINDING\",\n    \"COPY_WRITE_BUFFER\",\n    \"COPY_WRITE_BUFFER_BINDING\",\n    \"COUNTER_STYLE_RULE\",\n    \"CROS\",\n    \"CSS\",\n    \"CSS2Properties\",\n    \"CSSAnimation\",\n    \"CSSCharsetRule\",\n    \"CSSConditionRule\",\n    \"CSSCounterStyleRule\",\n    \"CSSFontFaceRule\",\n    \"CSSFontFeatureValuesRule\",\n    \"CSSGroupingRule\",\n    \"CSSImageValue\",\n    \"CSSImportRule\",\n    \"CSSKeyframeRule\",\n    \"CSSKeyframesRule\",\n    \"CSSKeywordValue\",\n    \"CSSMathInvert\",\n    \"CSSMathMax\",\n    \"CSSMathMin\",\n    \"CSSMathNegate\",\n    \"CSSMathProduct\",\n    \"CSSMathSum\",\n    \"CSSMathValue\",\n    \"CSSMatrixComponent\",\n    \"CSSMediaRule\",\n    \"CSSMozDocumentRule\",\n    \"CSSNameSpaceRule\",\n    \"CSSNamespaceRule\",\n    \"CSSNumericArray\",\n    \"CSSNumericValue\",\n    \"CSSPageRule\",\n    \"CSSPerspective\",\n    \"CSSPositionValue\",\n    \"CSSPrimitiveValue\",\n    \"CSSRotate\",\n    \"CSSRule\",\n    \"CSSRuleList\",\n    \"CSSScale\",\n    \"CSSSkew\",\n    \"CSSSkewX\",\n    \"CSSSkewY\",\n    \"CSSStyleDeclaration\",\n    \"CSSStyleRule\",\n    \"CSSStyleSheet\",\n    \"CSSStyleValue\",\n    \"CSSSupportsRule\",\n    \"CSSTransformComponent\",\n    \"CSSTransformValue\",\n    \"CSSTransition\",\n    \"CSSTranslate\",\n    \"CSSUnitValue\",\n    \"CSSUnknownRule\",\n    \"CSSUnparsedValue\",\n    \"CSSValue\",\n    \"CSSValueList\",\n    \"CSSVariableReferenceValue\",\n    \"CSSVariablesDeclaration\",\n    \"CSSVariablesRule\",\n    \"CSSViewportRule\",\n    \"CSS_ATTR\",\n    \"CSS_CM\",\n    \"CSS_COUNTER\",\n    \"CSS_CUSTOM\",\n    \"CSS_DEG\",\n    \"CSS_DIMENSION\",\n    \"CSS_EMS\",\n    \"CSS_EXS\",\n    \"CSS_FILTER_BLUR\",\n    \"CSS_FILTER_BRIGHTNESS\",\n    \"CSS_FILTER_CONTRAST\",\n    \"CSS_FILTER_CUSTOM\",\n    \"CSS_FILTER_DROP_SHADOW\",\n    \"CSS_FILTER_GRAYSCALE\",\n    \"CSS_FILTER_HUE_ROTATE\",\n    \"CSS_FILTER_INVERT\",\n    \"CSS_FILTER_OPACITY\",\n    \"CSS_FILTER_REFERENCE\",\n    \"CSS_FILTER_SATURATE\",\n    \"CSS_FILTER_SEPIA\",\n    \"CSS_GRAD\",\n    \"CSS_HZ\",\n    \"CSS_IDENT\",\n    \"CSS_IN\",\n    \"CSS_INHERIT\",\n    \"CSS_KHZ\",\n    \"CSS_MATRIX\",\n    \"CSS_MATRIX3D\",\n    \"CSS_MM\",\n    \"CSS_MS\",\n    \"CSS_NUMBER\",\n    \"CSS_PC\",\n    \"CSS_PERCENTAGE\",\n    \"CSS_PERSPECTIVE\",\n    \"CSS_PRIMITIVE_VALUE\",\n    \"CSS_PT\",\n    \"CSS_PX\",\n    \"CSS_RAD\",\n    \"CSS_RECT\",\n    \"CSS_RGBCOLOR\",\n    \"CSS_ROTATE\",\n    \"CSS_ROTATE3D\",\n    \"CSS_ROTATEX\",\n    \"CSS_ROTATEY\",\n    \"CSS_ROTATEZ\",\n    \"CSS_S\",\n    \"CSS_SCALE\",\n    \"CSS_SCALE3D\",\n    \"CSS_SCALEX\",\n    \"CSS_SCALEY\",\n    \"CSS_SCALEZ\",\n    \"CSS_SKEW\",\n    \"CSS_SKEWX\",\n    \"CSS_SKEWY\",\n    \"CSS_STRING\",\n    \"CSS_TRANSLATE\",\n    \"CSS_TRANSLATE3D\",\n    \"CSS_TRANSLATEX\",\n    \"CSS_TRANSLATEY\",\n    \"CSS_TRANSLATEZ\",\n    \"CSS_UNKNOWN\",\n    \"CSS_URI\",\n    \"CSS_VALUE_LIST\",\n    \"CSS_VH\",\n    \"CSS_VMAX\",\n    \"CSS_VMIN\",\n    \"CSS_VW\",\n    \"CULL_FACE\",\n    \"CULL_FACE_MODE\",\n    \"CURRENT_PROGRAM\",\n    \"CURRENT_QUERY\",\n    \"CURRENT_VERTEX_ATTRIB\",\n    \"CUSTOM\",\n    \"CW\",\n    \"Cache\",\n    \"CacheStorage\",\n    \"CanvasCaptureMediaStream\",\n    \"CanvasCaptureMediaStreamTrack\",\n    \"CanvasGradient\",\n    \"CanvasPattern\",\n    \"CanvasPixelArray\",\n    \"CanvasRenderingContext2D\",\n    \"CaretPosition\",\n    \"ChannelMergerNode\",\n    \"ChannelSplitterNode\",\n    \"CharacterData\",\n    \"Chrome PDF Plugin\",\n    \"Chrome PDF Viewer\",\n    \"ClientRect\",\n    \"ClientRectList\",\n    \"Clipboard\",\n    \"ClipboardEvent\",\n    \"ClipboardItem\",\n    \"CloseEvent\",\n    \"Collator\",\n    \"CollectGarbage\",\n    \"CommandEvent\",\n    \"Comment\",\n    \"CompileError\",\n    \"CompositionEvent\",\n    \"CompressionStream\",\n    \"Console\",\n    \"ConstantSourceNode\",\n    \"ControlRangeCollection\",\n    \"Controllers\",\n    \"ConvolverNode\",\n    \"Coordinates\",\n    \"CountQueuingStrategy\",\n    \"Counter\",\n    \"Credential\",\n    \"CredentialsContainer\",\n    \"Crypto\",\n    \"CryptoKey\",\n    \"CryptoOperation\",\n    \"CustomElementRegistry\",\n    \"CustomEvent\",\n    \"DATABASE_ERR\",\n    \"DATA_CLONE_ERR\",\n    \"DATA_ERR\",\n    \"DBLCLICK\",\n    \"DECR\",\n    \"DECR_WRAP\",\n    \"DELETE_STATUS\",\n    \"DEPTH\",\n    \"DEPTH24_STENCIL8\",\n    \"DEPTH32F_STENCIL8\",\n    \"DEPTH_ATTACHMENT\",\n    \"DEPTH_BITS\",\n    \"DEPTH_BUFFER_BIT\",\n    \"DEPTH_CLEAR_VALUE\",\n    \"DEPTH_COMPONENT\",\n    \"DEPTH_COMPONENT16\",\n    \"DEPTH_COMPONENT24\",\n    \"DEPTH_COMPONENT32F\",\n    \"DEPTH_FUNC\",\n    \"DEPTH_RANGE\",\n    \"DEPTH_STENCIL\",\n    \"DEPTH_STENCIL_ATTACHMENT\",\n    \"DEPTH_TEST\",\n    \"DEPTH_WRITEMASK\",\n    \"DEVICE_INELIGIBLE\",\n    \"DIRECTION_DOWN\",\n    \"DIRECTION_LEFT\",\n    \"DIRECTION_RIGHT\",\n    \"DIRECTION_UP\",\n    \"DISABLED\",\n    \"DISPATCH_REQUEST_ERR\",\n    \"DITHER\",\n    \"DOCUMENT_FRAGMENT_NODE\",\n    \"DOCUMENT_NODE\",\n    \"DOCUMENT_POSITION_CONTAINED_BY\",\n    \"DOCUMENT_POSITION_CONTAINS\",\n    \"DOCUMENT_POSITION_DISCONNECTED\",\n    \"DOCUMENT_POSITION_FOLLOWING\",\n    \"DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC\",\n    \"DOCUMENT_POSITION_PRECEDING\",\n    \"DOCUMENT_TYPE_NODE\",\n    \"DOMCursor\",\n    \"DOMError\",\n    \"DOMException\",\n    \"DOMImplementation\",\n    \"DOMImplementationLS\",\n    \"DOMMatrix\",\n    \"DOMMatrixReadOnly\",\n    \"DOMParser\",\n    \"DOMPoint\",\n    \"DOMPointReadOnly\",\n    \"DOMQuad\",\n    \"DOMRect\",\n    \"DOMRectList\",\n    \"DOMRectReadOnly\",\n    \"DOMRequest\",\n    \"DOMSTRING_SIZE_ERR\",\n    \"DOMSettableTokenList\",\n    \"DOMStringList\",\n    \"DOMStringMap\",\n    \"DOMTokenList\",\n    \"DOMTransactionEvent\",\n    \"DOM_DELTA_LINE\",\n    \"DOM_DELTA_PAGE\",\n    \"DOM_DELTA_PIXEL\",\n    \"DOM_INPUT_METHOD_DROP\",\n    \"DOM_INPUT_METHOD_HANDWRITING\",\n    \"DOM_INPUT_METHOD_IME\",\n    \"DOM_INPUT_METHOD_KEYBOARD\",\n    \"DOM_INPUT_METHOD_MULTIMODAL\",\n    \"DOM_INPUT_METHOD_OPTION\",\n    \"DOM_INPUT_METHOD_PASTE\",\n    \"DOM_INPUT_METHOD_SCRIPT\",\n    \"DOM_INPUT_METHOD_UNKNOWN\",\n    \"DOM_INPUT_METHOD_VOICE\",\n    \"DOM_KEY_LOCATION_JOYSTICK\",\n    \"DOM_KEY_LOCATION_LEFT\",\n    \"DOM_KEY_LOCATION_MOBILE\",\n    \"DOM_KEY_LOCATION_NUMPAD\",\n    \"DOM_KEY_LOCATION_RIGHT\",\n    \"DOM_KEY_LOCATION_STANDARD\",\n    \"DOM_VK_0\",\n    \"DOM_VK_1\",\n    \"DOM_VK_2\",\n    \"DOM_VK_3\",\n    \"DOM_VK_4\",\n    \"DOM_VK_5\",\n    \"DOM_VK_6\",\n    \"DOM_VK_7\",\n    \"DOM_VK_8\",\n    \"DOM_VK_9\",\n    \"DOM_VK_A\",\n    \"DOM_VK_ACCEPT\",\n    \"DOM_VK_ADD\",\n    \"DOM_VK_ALT\",\n    \"DOM_VK_ALTGR\",\n    \"DOM_VK_AMPERSAND\",\n    \"DOM_VK_ASTERISK\",\n    \"DOM_VK_AT\",\n    \"DOM_VK_ATTN\",\n    \"DOM_VK_B\",\n    \"DOM_VK_BACKSPACE\",\n    \"DOM_VK_BACK_QUOTE\",\n    \"DOM_VK_BACK_SLASH\",\n    \"DOM_VK_BACK_SPACE\",\n    \"DOM_VK_C\",\n    \"DOM_VK_CANCEL\",\n    \"DOM_VK_CAPS_LOCK\",\n    \"DOM_VK_CIRCUMFLEX\",\n    \"DOM_VK_CLEAR\",\n    \"DOM_VK_CLOSE_BRACKET\",\n    \"DOM_VK_CLOSE_CURLY_BRACKET\",\n    \"DOM_VK_CLOSE_PAREN\",\n    \"DOM_VK_COLON\",\n    \"DOM_VK_COMMA\",\n    \"DOM_VK_CONTEXT_MENU\",\n    \"DOM_VK_CONTROL\",\n    \"DOM_VK_CONVERT\",\n    \"DOM_VK_CRSEL\",\n    \"DOM_VK_CTRL\",\n    \"DOM_VK_D\",\n    \"DOM_VK_DECIMAL\",\n    \"DOM_VK_DELETE\",\n    \"DOM_VK_DIVIDE\",\n    \"DOM_VK_DOLLAR\",\n    \"DOM_VK_DOUBLE_QUOTE\",\n    \"DOM_VK_DOWN\",\n    \"DOM_VK_E\",\n    \"DOM_VK_EISU\",\n    \"DOM_VK_END\",\n    \"DOM_VK_ENTER\",\n    \"DOM_VK_EQUALS\",\n    \"DOM_VK_EREOF\",\n    \"DOM_VK_ESCAPE\",\n    \"DOM_VK_EXCLAMATION\",\n    \"DOM_VK_EXECUTE\",\n    \"DOM_VK_EXSEL\",\n    \"DOM_VK_F\",\n    \"DOM_VK_F1\",\n    \"DOM_VK_F10\",\n    \"DOM_VK_F11\",\n    \"DOM_VK_F12\",\n    \"DOM_VK_F13\",\n    \"DOM_VK_F14\",\n    \"DOM_VK_F15\",\n    \"DOM_VK_F16\",\n    \"DOM_VK_F17\",\n    \"DOM_VK_F18\",\n    \"DOM_VK_F19\",\n    \"DOM_VK_F2\",\n    \"DOM_VK_F20\",\n    \"DOM_VK_F21\",\n    \"DOM_VK_F22\",\n    \"DOM_VK_F23\",\n    \"DOM_VK_F24\",\n    \"DOM_VK_F25\",\n    \"DOM_VK_F26\",\n    \"DOM_VK_F27\",\n    \"DOM_VK_F28\",\n    \"DOM_VK_F29\",\n    \"DOM_VK_F3\",\n    \"DOM_VK_F30\",\n    \"DOM_VK_F31\",\n    \"DOM_VK_F32\",\n    \"DOM_VK_F33\",\n    \"DOM_VK_F34\",\n    \"DOM_VK_F35\",\n    \"DOM_VK_F36\",\n    \"DOM_VK_F4\",\n    \"DOM_VK_F5\",\n    \"DOM_VK_F6\",\n    \"DOM_VK_F7\",\n    \"DOM_VK_F8\",\n    \"DOM_VK_F9\",\n    \"DOM_VK_FINAL\",\n    \"DOM_VK_FRONT\",\n    \"DOM_VK_G\",\n    \"DOM_VK_GREATER_THAN\",\n    \"DOM_VK_H\",\n    \"DOM_VK_HANGUL\",\n    \"DOM_VK_HANJA\",\n    \"DOM_VK_HASH\",\n    \"DOM_VK_HELP\",\n    \"DOM_VK_HK_TOGGLE\",\n    \"DOM_VK_HOME\",\n    \"DOM_VK_HYPHEN_MINUS\",\n    \"DOM_VK_I\",\n    \"DOM_VK_INSERT\",\n    \"DOM_VK_J\",\n    \"DOM_VK_JUNJA\",\n    \"DOM_VK_K\",\n    \"DOM_VK_KANA\",\n    \"DOM_VK_KANJI\",\n    \"DOM_VK_L\",\n    \"DOM_VK_LEFT\",\n    \"DOM_VK_LEFT_TAB\",\n    \"DOM_VK_LESS_THAN\",\n    \"DOM_VK_M\",\n    \"DOM_VK_META\",\n    \"DOM_VK_MODECHANGE\",\n    \"DOM_VK_MULTIPLY\",\n    \"DOM_VK_N\",\n    \"DOM_VK_NONCONVERT\",\n    \"DOM_VK_NUMPAD0\",\n    \"DOM_VK_NUMPAD1\",\n    \"DOM_VK_NUMPAD2\",\n    \"DOM_VK_NUMPAD3\",\n    \"DOM_VK_NUMPAD4\",\n    \"DOM_VK_NUMPAD5\",\n    \"DOM_VK_NUMPAD6\",\n    \"DOM_VK_NUMPAD7\",\n    \"DOM_VK_NUMPAD8\",\n    \"DOM_VK_NUMPAD9\",\n    \"DOM_VK_NUM_LOCK\",\n    \"DOM_VK_O\",\n    \"DOM_VK_OEM_1\",\n    \"DOM_VK_OEM_102\",\n    \"DOM_VK_OEM_2\",\n    \"DOM_VK_OEM_3\",\n    \"DOM_VK_OEM_4\",\n    \"DOM_VK_OEM_5\",\n    \"DOM_VK_OEM_6\",\n    \"DOM_VK_OEM_7\",\n    \"DOM_VK_OEM_8\",\n    \"DOM_VK_OEM_COMMA\",\n    \"DOM_VK_OEM_MINUS\",\n    \"DOM_VK_OEM_PERIOD\",\n    \"DOM_VK_OEM_PLUS\",\n    \"DOM_VK_OPEN_BRACKET\",\n    \"DOM_VK_OPEN_CURLY_BRACKET\",\n    \"DOM_VK_OPEN_PAREN\",\n    \"DOM_VK_P\",\n    \"DOM_VK_PA1\",\n    \"DOM_VK_PAGEDOWN\",\n    \"DOM_VK_PAGEUP\",\n    \"DOM_VK_PAGE_DOWN\",\n    \"DOM_VK_PAGE_UP\",\n    \"DOM_VK_PAUSE\",\n    \"DOM_VK_PERCENT\",\n    \"DOM_VK_PERIOD\",\n    \"DOM_VK_PIPE\",\n    \"DOM_VK_PLAY\",\n    \"DOM_VK_PLUS\",\n    \"DOM_VK_PRINT\",\n    \"DOM_VK_PRINTSCREEN\",\n    \"DOM_VK_PROCESSKEY\",\n    \"DOM_VK_PROPERITES\",\n    \"DOM_VK_Q\",\n    \"DOM_VK_QUESTION_MARK\",\n    \"DOM_VK_QUOTE\",\n    \"DOM_VK_R\",\n    \"DOM_VK_REDO\",\n    \"DOM_VK_RETURN\",\n    \"DOM_VK_RIGHT\",\n    \"DOM_VK_S\",\n    \"DOM_VK_SCROLL_LOCK\",\n    \"DOM_VK_SELECT\",\n    \"DOM_VK_SEMICOLON\",\n    \"DOM_VK_SEPARATOR\",\n    \"DOM_VK_SHIFT\",\n    \"DOM_VK_SLASH\",\n    \"DOM_VK_SLEEP\",\n    \"DOM_VK_SPACE\",\n    \"DOM_VK_SUBTRACT\",\n    \"DOM_VK_T\",\n    \"DOM_VK_TAB\",\n    \"DOM_VK_TILDE\",\n    \"DOM_VK_U\",\n    \"DOM_VK_UNDERSCORE\",\n    \"DOM_VK_UNDO\",\n    \"DOM_VK_UNICODE\",\n    \"DOM_VK_UP\",\n    \"DOM_VK_V\",\n    \"DOM_VK_VOLUME_DOWN\",\n    \"DOM_VK_VOLUME_MUTE\",\n    \"DOM_VK_VOLUME_UP\",\n    \"DOM_VK_W\",\n    \"DOM_VK_WIN\",\n    \"DOM_VK_WINDOW\",\n    \"DOM_VK_WIN_ICO_00\",\n    \"DOM_VK_WIN_ICO_CLEAR\",\n    \"DOM_VK_WIN_ICO_HELP\",\n    \"DOM_VK_WIN_OEM_ATTN\",\n    \"DOM_VK_WIN_OEM_AUTO\",\n    \"DOM_VK_WIN_OEM_BACKTAB\",\n    \"DOM_VK_WIN_OEM_CLEAR\",\n    \"DOM_VK_WIN_OEM_COPY\",\n    \"DOM_VK_WIN_OEM_CUSEL\",\n    \"DOM_VK_WIN_OEM_ENLW\",\n    \"DOM_VK_WIN_OEM_FINISH\",\n    \"DOM_VK_WIN_OEM_FJ_JISHO\",\n    \"DOM_VK_WIN_OEM_FJ_LOYA\",\n    \"DOM_VK_WIN_OEM_FJ_MASSHOU\",\n    \"DOM_VK_WIN_OEM_FJ_ROYA\",\n    \"DOM_VK_WIN_OEM_FJ_TOUROKU\",\n    \"DOM_VK_WIN_OEM_JUMP\",\n    \"DOM_VK_WIN_OEM_PA1\",\n    \"DOM_VK_WIN_OEM_PA2\",\n    \"DOM_VK_WIN_OEM_PA3\",\n    \"DOM_VK_WIN_OEM_RESET\",\n    \"DOM_VK_WIN_OEM_WSCTRL\",\n    \"DOM_VK_X\",\n    \"DOM_VK_XF86XK_ADD_FAVORITE\",\n    \"DOM_VK_XF86XK_APPLICATION_LEFT\",\n    \"DOM_VK_XF86XK_APPLICATION_RIGHT\",\n    \"DOM_VK_XF86XK_AUDIO_CYCLE_TRACK\",\n    \"DOM_VK_XF86XK_AUDIO_FORWARD\",\n    \"DOM_VK_XF86XK_AUDIO_LOWER_VOLUME\",\n    \"DOM_VK_XF86XK_AUDIO_MEDIA\",\n    \"DOM_VK_XF86XK_AUDIO_MUTE\",\n    \"DOM_VK_XF86XK_AUDIO_NEXT\",\n    \"DOM_VK_XF86XK_AUDIO_PAUSE\",\n    \"DOM_VK_XF86XK_AUDIO_PLAY\",\n    \"DOM_VK_XF86XK_AUDIO_PREV\",\n    \"DOM_VK_XF86XK_AUDIO_RAISE_VOLUME\",\n    \"DOM_VK_XF86XK_AUDIO_RANDOM_PLAY\",\n    \"DOM_VK_XF86XK_AUDIO_RECORD\",\n    \"DOM_VK_XF86XK_AUDIO_REPEAT\",\n    \"DOM_VK_XF86XK_AUDIO_REWIND\",\n    \"DOM_VK_XF86XK_AUDIO_STOP\",\n    \"DOM_VK_XF86XK_AWAY\",\n    \"DOM_VK_XF86XK_BACK\",\n    \"DOM_VK_XF86XK_BACK_FORWARD\",\n    \"DOM_VK_XF86XK_BATTERY\",\n    \"DOM_VK_XF86XK_BLUE\",\n    \"DOM_VK_XF86XK_BLUETOOTH\",\n    \"DOM_VK_XF86XK_BOOK\",\n    \"DOM_VK_XF86XK_BRIGHTNESS_ADJUST\",\n    \"DOM_VK_XF86XK_CALCULATOR\",\n    \"DOM_VK_XF86XK_CALENDAR\",\n    \"DOM_VK_XF86XK_CD\",\n    \"DOM_VK_XF86XK_CLOSE\",\n    \"DOM_VK_XF86XK_COMMUNITY\",\n    \"DOM_VK_XF86XK_CONTRAST_ADJUST\",\n    \"DOM_VK_XF86XK_COPY\",\n    \"DOM_VK_XF86XK_CUT\",\n    \"DOM_VK_XF86XK_CYCLE_ANGLE\",\n    \"DOM_VK_XF86XK_DISPLAY\",\n    \"DOM_VK_XF86XK_DOCUMENTS\",\n    \"DOM_VK_XF86XK_DOS\",\n    \"DOM_VK_XF86XK_EJECT\",\n    \"DOM_VK_XF86XK_EXCEL\",\n    \"DOM_VK_XF86XK_EXPLORER\",\n    \"DOM_VK_XF86XK_FAVORITES\",\n    \"DOM_VK_XF86XK_FINANCE\",\n    \"DOM_VK_XF86XK_FORWARD\",\n    \"DOM_VK_XF86XK_FRAME_BACK\",\n    \"DOM_VK_XF86XK_FRAME_FORWARD\",\n    \"DOM_VK_XF86XK_GAME\",\n    \"DOM_VK_XF86XK_GO\",\n    \"DOM_VK_XF86XK_GREEN\",\n    \"DOM_VK_XF86XK_HIBERNATE\",\n    \"DOM_VK_XF86XK_HISTORY\",\n    \"DOM_VK_XF86XK_HOME_PAGE\",\n    \"DOM_VK_XF86XK_HOT_LINKS\",\n    \"DOM_VK_XF86XK_I_TOUCH\",\n    \"DOM_VK_XF86XK_KBD_BRIGHTNESS_DOWN\",\n    \"DOM_VK_XF86XK_KBD_BRIGHTNESS_UP\",\n    \"DOM_VK_XF86XK_KBD_LIGHT_ON_OFF\",\n    \"DOM_VK_XF86XK_LAUNCH0\",\n    \"DOM_VK_XF86XK_LAUNCH1\",\n    \"DOM_VK_XF86XK_LAUNCH2\",\n    \"DOM_VK_XF86XK_LAUNCH3\",\n    \"DOM_VK_XF86XK_LAUNCH4\",\n    \"DOM_VK_XF86XK_LAUNCH5\",\n    \"DOM_VK_XF86XK_LAUNCH6\",\n    \"DOM_VK_XF86XK_LAUNCH7\",\n    \"DOM_VK_XF86XK_LAUNCH8\",\n    \"DOM_VK_XF86XK_LAUNCH9\",\n    \"DOM_VK_XF86XK_LAUNCH_A\",\n    \"DOM_VK_XF86XK_LAUNCH_B\",\n    \"DOM_VK_XF86XK_LAUNCH_C\",\n    \"DOM_VK_XF86XK_LAUNCH_D\",\n    \"DOM_VK_XF86XK_LAUNCH_E\",\n    \"DOM_VK_XF86XK_LAUNCH_F\",\n    \"DOM_VK_XF86XK_LIGHT_BULB\",\n    \"DOM_VK_XF86XK_LOG_OFF\",\n    \"DOM_VK_XF86XK_MAIL\",\n    \"DOM_VK_XF86XK_MAIL_FORWARD\",\n    \"DOM_VK_XF86XK_MARKET\",\n    \"DOM_VK_XF86XK_MEETING\",\n    \"DOM_VK_XF86XK_MEMO\",\n    \"DOM_VK_XF86XK_MENU_KB\",\n    \"DOM_VK_XF86XK_MENU_PB\",\n    \"DOM_VK_XF86XK_MESSENGER\",\n    \"DOM_VK_XF86XK_MON_BRIGHTNESS_DOWN\",\n    \"DOM_VK_XF86XK_MON_BRIGHTNESS_UP\",\n    \"DOM_VK_XF86XK_MUSIC\",\n    \"DOM_VK_XF86XK_MY_COMPUTER\",\n    \"DOM_VK_XF86XK_MY_SITES\",\n    \"DOM_VK_XF86XK_NEW\",\n    \"DOM_VK_XF86XK_NEWS\",\n    \"DOM_VK_XF86XK_OFFICE_HOME\",\n    \"DOM_VK_XF86XK_OPEN\",\n    \"DOM_VK_XF86XK_OPEN_URL\",\n    \"DOM_VK_XF86XK_OPTION\",\n    \"DOM_VK_XF86XK_PASTE\",\n    \"DOM_VK_XF86XK_PHONE\",\n    \"DOM_VK_XF86XK_PICTURES\",\n    \"DOM_VK_XF86XK_POWER_DOWN\",\n    \"DOM_VK_XF86XK_POWER_OFF\",\n    \"DOM_VK_XF86XK_RED\",\n    \"DOM_VK_XF86XK_REFRESH\",\n    \"DOM_VK_XF86XK_RELOAD\",\n    \"DOM_VK_XF86XK_REPLY\",\n    \"DOM_VK_XF86XK_ROCKER_DOWN\",\n    \"DOM_VK_XF86XK_ROCKER_ENTER\",\n    \"DOM_VK_XF86XK_ROCKER_UP\",\n    \"DOM_VK_XF86XK_ROTATE_WINDOWS\",\n    \"DOM_VK_XF86XK_ROTATION_KB\",\n    \"DOM_VK_XF86XK_ROTATION_PB\",\n    \"DOM_VK_XF86XK_SAVE\",\n    \"DOM_VK_XF86XK_SCREEN_SAVER\",\n    \"DOM_VK_XF86XK_SCROLL_CLICK\",\n    \"DOM_VK_XF86XK_SCROLL_DOWN\",\n    \"DOM_VK_XF86XK_SCROLL_UP\",\n    \"DOM_VK_XF86XK_SEARCH\",\n    \"DOM_VK_XF86XK_SEND\",\n    \"DOM_VK_XF86XK_SHOP\",\n    \"DOM_VK_XF86XK_SPELL\",\n    \"DOM_VK_XF86XK_SPLIT_SCREEN\",\n    \"DOM_VK_XF86XK_STANDBY\",\n    \"DOM_VK_XF86XK_START\",\n    \"DOM_VK_XF86XK_STOP\",\n    \"DOM_VK_XF86XK_SUBTITLE\",\n    \"DOM_VK_XF86XK_SUPPORT\",\n    \"DOM_VK_XF86XK_SUSPEND\",\n    \"DOM_VK_XF86XK_TASK_PANE\",\n    \"DOM_VK_XF86XK_TERMINAL\",\n    \"DOM_VK_XF86XK_TIME\",\n    \"DOM_VK_XF86XK_TOOLS\",\n    \"DOM_VK_XF86XK_TOP_MENU\",\n    \"DOM_VK_XF86XK_TO_DO_LIST\",\n    \"DOM_VK_XF86XK_TRAVEL\",\n    \"DOM_VK_XF86XK_USER1KB\",\n    \"DOM_VK_XF86XK_USER2KB\",\n    \"DOM_VK_XF86XK_USER_PB\",\n    \"DOM_VK_XF86XK_UWB\",\n    \"DOM_VK_XF86XK_VENDOR_HOME\",\n    \"DOM_VK_XF86XK_VIDEO\",\n    \"DOM_VK_XF86XK_VIEW\",\n    \"DOM_VK_XF86XK_WAKE_UP\",\n    \"DOM_VK_XF86XK_WEB_CAM\",\n    \"DOM_VK_XF86XK_WHEEL_BUTTON\",\n    \"DOM_VK_XF86XK_WLAN\",\n    \"DOM_VK_XF86XK_WORD\",\n    \"DOM_VK_XF86XK_WWW\",\n    \"DOM_VK_XF86XK_XFER\",\n    \"DOM_VK_XF86XK_YELLOW\",\n    \"DOM_VK_XF86XK_ZOOM_IN\",\n    \"DOM_VK_XF86XK_ZOOM_OUT\",\n    \"DOM_VK_Y\",\n    \"DOM_VK_Z\",\n    \"DOM_VK_ZOOM\",\n    \"DONE\",\n    \"DONT_CARE\",\n    \"DOWNLOADING\",\n    \"DRAGDROP\",\n    \"DRAW_BUFFER0\",\n    \"DRAW_BUFFER1\",\n    \"DRAW_BUFFER10\",\n    \"DRAW_BUFFER11\",\n    \"DRAW_BUFFER12\",\n    \"DRAW_BUFFER13\",\n    \"DRAW_BUFFER14\",\n    \"DRAW_BUFFER15\",\n    \"DRAW_BUFFER2\",\n    \"DRAW_BUFFER3\",\n    \"DRAW_BUFFER4\",\n    \"DRAW_BUFFER5\",\n    \"DRAW_BUFFER6\",\n    \"DRAW_BUFFER7\",\n    \"DRAW_BUFFER8\",\n    \"DRAW_BUFFER9\",\n    \"DRAW_FRAMEBUFFER\",\n    \"DRAW_FRAMEBUFFER_BINDING\",\n    \"DST_ALPHA\",\n    \"DST_COLOR\",\n    \"DYNAMIC_COPY\",\n    \"DYNAMIC_DRAW\",\n    \"DYNAMIC_READ\",\n    \"DataChannel\",\n    \"DataCue\",\n    \"DataTransfer\",\n    \"DataTransferItem\",\n    \"DataTransferItemList\",\n    \"DataView\",\n    \"Database\",\n    \"Date\",\n    \"DateTimeFormat\",\n    \"Debug\",\n    \"DecompressionStream\",\n    \"Default Browser Helper\",\n    \"DelayNode\",\n    \"DesktopNotification\",\n    \"DesktopNotificationCenter\",\n    \"DeviceAcceleration\",\n    \"DeviceLightEvent\",\n    \"DeviceMotionEvent\",\n    \"DeviceMotionEventAcceleration\",\n    \"DeviceMotionEventRotationRate\",\n    \"DeviceOrientationEvent\",\n    \"DeviceProximityEvent\",\n    \"DeviceRotationRate\",\n    \"DeviceStorage\",\n    \"DeviceStorageChangeEvent\",\n    \"Directory\",\n    \"DisplayNames\",\n    \"Document\",\n    \"DocumentFragment\",\n    \"DocumentTimeline\",\n    \"DocumentType\",\n    \"DragEvent\",\n    \"DynamicsCompressorNode\",\n    \"E\",\n    \"ELEMENT_ARRAY_BUFFER\",\n    \"ELEMENT_ARRAY_BUFFER_BINDING\",\n    \"ELEMENT_NODE\",\n    \"EMPTY\",\n    \"ENCODING_ERR\",\n    \"ENDED\",\n    \"END_TO_END\",\n    \"END_TO_START\",\n    \"ENTITY_NODE\",\n    \"ENTITY_REFERENCE_NODE\",\n    \"EPSILON\",\n    \"EQUAL\",\n    \"EQUALPOWER\",\n    \"ERROR\",\n    \"EXPONENTIAL_DISTANCE\",\n    \"EXT_texture_filter_anisotropic\",\n    \"Element\",\n    \"ElementInternals\",\n    \"ElementQuery\",\n    \"EnterPictureInPictureEvent\",\n    \"Entity\",\n    \"EntityReference\",\n    \"Enumerator\",\n    \"Error\",\n    \"ErrorEvent\",\n    \"EvalError\",\n    \"Event\",\n    \"EventException\",\n    \"EventSource\",\n    \"EventTarget\",\n    \"External\",\n    \"FASTEST\",\n    \"FIDOSDK\",\n    \"FILTER_ACCEPT\",\n    \"FILTER_INTERRUPT\",\n    \"FILTER_REJECT\",\n    \"FILTER_SKIP\",\n    \"FINISHED_STATE\",\n    \"FIRST_ORDERED_NODE_TYPE\",\n    \"FLOAT\",\n    \"FLOAT_32_UNSIGNED_INT_24_8_REV\",\n    \"FLOAT_MAT2\",\n    \"FLOAT_MAT2x3\",\n    \"FLOAT_MAT2x4\",\n    \"FLOAT_MAT3\",\n    \"FLOAT_MAT3x2\",\n    \"FLOAT_MAT3x4\",\n    \"FLOAT_MAT4\",\n    \"FLOAT_MAT4x2\",\n    \"FLOAT_MAT4x3\",\n    \"FLOAT_VEC2\",\n    \"FLOAT_VEC3\",\n    \"FLOAT_VEC4\",\n    \"FOCUS\",\n    \"FONT_FACE_RULE\",\n    \"FONT_FEATURE_VALUES_RULE\",\n    \"FRAGMENT_SHADER\",\n    \"FRAGMENT_SHADER_DERIVATIVE_HINT\",\n    \"FRAGMENT_SHADER_DERIVATIVE_HINT_OES\",\n    \"FRAMEBUFFER\",\n    \"FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE\",\n    \"FRAMEBUFFER_ATTACHMENT_BLUE_SIZE\",\n    \"FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING\",\n    \"FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE\",\n    \"FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE\",\n    \"FRAMEBUFFER_ATTACHMENT_GREEN_SIZE\",\n    \"FRAMEBUFFER_ATTACHMENT_OBJECT_NAME\",\n    \"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE\",\n    \"FRAMEBUFFER_ATTACHMENT_RED_SIZE\",\n    \"FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE\",\n    \"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE\",\n    \"FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER\",\n    \"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL\",\n    \"FRAMEBUFFER_BINDING\",\n    \"FRAMEBUFFER_COMPLETE\",\n    \"FRAMEBUFFER_DEFAULT\",\n    \"FRAMEBUFFER_INCOMPLETE_ATTACHMENT\",\n    \"FRAMEBUFFER_INCOMPLETE_DIMENSIONS\",\n    \"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\",\n    \"FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\",\n    \"FRAMEBUFFER_UNSUPPORTED\",\n    \"FRONT\",\n    \"FRONT_AND_BACK\",\n    \"FRONT_FACE\",\n    \"FUNC_ADD\",\n    \"FUNC_REVERSE_SUBTRACT\",\n    \"FUNC_SUBTRACT\",\n    \"FeaturePolicy\",\n    \"FederatedCredential\",\n    \"Feed\",\n    \"FeedEntry\",\n    \"File\",\n    \"FileError\",\n    \"FileList\",\n    \"FileReader\",\n    \"FileSystem\",\n    \"FileSystemDirectoryEntry\",\n    \"FileSystemDirectoryReader\",\n    \"FileSystemEntry\",\n    \"FileSystemFileEntry\",\n    \"FinalizationRegistry\",\n    \"FindInPage\",\n    \"Float32Array\",\n    \"Float64Array\",\n    \"FocusEvent\",\n    \"FontFace\",\n    \"FontFaceSet\",\n    \"FontFaceSetLoadEvent\",\n    \"FormData\",\n    \"FormDataEvent\",\n    \"FragmentDirective\",\n    \"Function\",\n    \"GENERATE_MIPMAP_HINT\",\n    \"GEQUAL\",\n    \"GREATER\",\n    \"GREEN_BITS\",\n    \"GainNode\",\n    \"Gamepad\",\n    \"GamepadButton\",\n    \"GamepadEvent\",\n    \"GamepadHapticActuator\",\n    \"GamepadPose\",\n    \"Geolocation\",\n    \"GeolocationCoordinates\",\n    \"GeolocationPosition\",\n    \"GeolocationPositionError\",\n    \"GestureEvent\",\n    \"Global\",\n    \"Gyroscope\",\n    \"HALF_FLOAT\",\n    \"HAVE_CURRENT_DATA\",\n    \"HAVE_ENOUGH_DATA\",\n    \"HAVE_FUTURE_DATA\",\n    \"HAVE_METADATA\",\n    \"HAVE_NOTHING\",\n    \"HEADERS_RECEIVED\",\n    \"HIDDEN\",\n    \"HIERARCHY_REQUEST_ERR\",\n    \"HIGHPASS\",\n    \"HIGHSHELF\",\n    \"HIGH_FLOAT\",\n    \"HIGH_INT\",\n    \"HORIZONTAL\",\n    \"HORIZONTAL_AXIS\",\n    \"HRTF\",\n    \"HTMLAllCollection\",\n    \"HTMLAnchorElement\",\n    \"HTMLAppletElement\",\n    \"HTMLAreaElement\",\n    \"HTMLAreasCollection\",\n    \"HTMLAudioElement\",\n    \"HTMLBGSoundElement\",\n    \"HTMLBRElement\",\n    \"HTMLBaseElement\",\n    \"HTMLBaseFontElement\",\n    \"HTMLBlockElement\",\n    \"HTMLBlockquoteElement\",\n    \"HTMLBodyElement\",\n    \"HTMLButtonElement\",\n    \"HTMLCanvasElement\",\n    \"HTMLCollection\",\n    \"HTMLCommandElement\",\n    \"HTMLContentElement\",\n    \"HTMLDDElement\",\n    \"HTMLDListElement\",\n    \"HTMLDTElement\",\n    \"HTMLDataElement\",\n    \"HTMLDataListElement\",\n    \"HTMLDetailsElement\",\n    \"HTMLDialogElement\",\n    \"HTMLDirectoryElement\",\n    \"HTMLDivElement\",\n    \"HTMLDocument\",\n    \"HTMLElement\",\n    \"HTMLEmbedElement\",\n    \"HTMLFieldSetElement\",\n    \"HTMLFontElement\",\n    \"HTMLFormControlsCollection\",\n    \"HTMLFormElement\",\n    \"HTMLFrameElement\",\n    \"HTMLFrameSetElement\",\n    \"HTMLHRElement\",\n    \"HTMLHeadElement\",\n    \"HTMLHeadingElement\",\n    \"HTMLHtmlElement\",\n    \"HTMLIFrameElement\",\n    \"HTMLImageElement\",\n    \"HTMLInputElement\",\n    \"HTMLIsIndexElement\",\n    \"HTMLKeygenElement\",\n    \"HTMLLIElement\",\n    \"HTMLLabelElement\",\n    \"HTMLLegendElement\",\n    \"HTMLLinkElement\",\n    \"HTMLMapElement\",\n    \"HTMLMarqueeElement\",\n    \"HTMLMediaElement\",\n    \"HTMLMenuElement\",\n    \"HTMLMenuItemElement\",\n    \"HTMLMetaElement\",\n    \"HTMLMeterElement\",\n    \"HTMLModElement\",\n    \"HTMLNextIdElement\",\n    \"HTMLOListElement\",\n    \"HTMLObjectElement\",\n    \"HTMLOptGroupElement\",\n    \"HTMLOptionElement\",\n    \"HTMLOptionsCollection\",\n    \"HTMLOutputElement\",\n    \"HTMLParagraphElement\",\n    \"HTMLParamElement\",\n    \"HTMLPhraseElement\",\n    \"HTMLPictureElement\",\n    \"HTMLPreElement\",\n    \"HTMLProgressElement\",\n    \"HTMLPropertiesCollection\",\n    \"HTMLQuoteElement\",\n    \"HTMLScriptElement\",\n    \"HTMLSelectElement\",\n    \"HTMLShadowElement\",\n    \"HTMLSlotElement\",\n    \"HTMLSourceElement\",\n    \"HTMLSpanElement\",\n    \"HTMLStyleElement\",\n    \"HTMLTableCaptionElement\",\n    \"HTMLTableCellElement\",\n    \"HTMLTableColElement\",\n    \"HTMLTableDataCellElement\",\n    \"HTMLTableElement\",\n    \"HTMLTableHeaderCellElement\",\n    \"HTMLTableRowElement\",\n    \"HTMLTableSectionElement\",\n    \"HTMLTemplateElement\",\n    \"HTMLTextAreaElement\",\n    \"HTMLTimeElement\",\n    \"HTMLTitleElement\",\n    \"HTMLTrackElement\",\n    \"HTMLUListElement\",\n    \"HTMLUnknownElement\",\n    \"HTMLVideoElement\",\n    \"HashChangeEvent\",\n    \"Headers\",\n    \"History\",\n    \"Hz\",\n    \"ICE_CHECKING\",\n    \"ICE_CLOSED\",\n    \"ICE_COMPLETED\",\n    \"ICE_CONNECTED\",\n    \"ICE_FAILED\",\n    \"ICE_GATHERING\",\n    \"ICE_WAITING\",\n    \"IDBCursor\",\n    \"IDBCursorWithValue\",\n    \"IDBDatabase\",\n    \"IDBDatabaseException\",\n    \"IDBFactory\",\n    \"IDBFileHandle\",\n    \"IDBFileRequest\",\n    \"IDBIndex\",\n    \"IDBKeyRange\",\n    \"IDBMutableFile\",\n    \"IDBObjectStore\",\n    \"IDBOpenDBRequest\",\n    \"IDBRequest\",\n    \"IDBTransaction\",\n    \"IDBVersionChangeEvent\",\n    \"IDLE\",\n    \"IIRFilterNode\",\n    \"IMPLEMENTATION_COLOR_READ_FORMAT\",\n    \"IMPLEMENTATION_COLOR_READ_TYPE\",\n    \"IMPORT_RULE\",\n    \"INCR\",\n    \"INCR_WRAP\",\n    \"INDEX_SIZE_ERR\",\n    \"INSTALL\",\n    \"INSTALLED\",\n    \"INT\",\n    \"INTERLEAVED_ATTRIBS\",\n    \"INT_2_10_10_10_REV\",\n    \"INT_SAMPLER_2D\",\n    \"INT_SAMPLER_2D_ARRAY\",\n    \"INT_SAMPLER_3D\",\n    \"INT_SAMPLER_CUBE\",\n    \"INT_VEC2\",\n    \"INT_VEC3\",\n    \"INT_VEC4\",\n    \"INUSE_ATTRIBUTE_ERR\",\n    \"INVALID_ACCESS_ERR\",\n    \"INVALID_CHARACTER_ERR\",\n    \"INVALID_ENUM\",\n    \"INVALID_EXPRESSION_ERR\",\n    \"INVALID_FRAMEBUFFER_OPERATION\",\n    \"INVALID_INDEX\",\n    \"INVALID_MODIFICATION_ERR\",\n    \"INVALID_NODE_TYPE_ERR\",\n    \"INVALID_OPERATION\",\n    \"INVALID_STATE_ERR\",\n    \"INVALID_VALUE\",\n    \"INVERSE_DISTANCE\",\n    \"INVERT\",\n    \"IceCandidate\",\n    \"IdleDeadline\",\n    \"Image\",\n    \"ImageBitmap\",\n    \"ImageBitmapRenderingContext\",\n    \"ImageCapture\",\n    \"ImageData\",\n    \"Infinity\",\n    \"InputDeviceCapabilities\",\n    \"InputDeviceInfo\",\n    \"InputEvent\",\n    \"InputMethodContext\",\n    \"InstallState\",\n    \"InstallTrigger\",\n    \"Instance\",\n    \"Int16Array\",\n    \"Int32Array\",\n    \"Int8Array\",\n    \"Intent\",\n    \"InternalError\",\n    \"IntersectionObserver\",\n    \"IntersectionObserverEntry\",\n    \"Intl\",\n    \"IsSearchProviderInstalled\",\n    \"Iterator\",\n    \"JSON\",\n    \"Java Deployment Toolkit 7.0.250.17\",\n    \"Java(TM) Platform SE 7 U25\",\n    \"KEEP\",\n    \"KEYDOWN\",\n    \"KEYFRAMES_RULE\",\n    \"KEYFRAME_RULE\",\n    \"KEYPRESS\",\n    \"KEYUP\",\n    \"Key\",\n    \"KeyEvent\",\n    \"KeyOperation\",\n    \"KeyPair\",\n    \"Keyboard\",\n    \"KeyboardEvent\",\n    \"KeyboardLayoutMap\",\n    \"KeyframeEffect\",\n    \"LENGTHADJUST_SPACING\",\n    \"LENGTHADJUST_SPACINGANDGLYPHS\",\n    \"LENGTHADJUST_UNKNOWN\",\n    \"LEQUAL\",\n    \"LESS\",\n    \"LINEAR\",\n    \"LINEAR_DISTANCE\",\n    \"LINEAR_MIPMAP_LINEAR\",\n    \"LINEAR_MIPMAP_NEAREST\",\n    \"LINES\",\n    \"LINE_LOOP\",\n    \"LINE_STRIP\",\n    \"LINE_WIDTH\",\n    \"LINK_STATUS\",\n    \"LINUX\",\n    \"LIVE\",\n    \"LN10\",\n    \"LN2\",\n    \"LOADED\",\n    \"LOADING\",\n    \"LOCALE\",\n    \"LOG10E\",\n    \"LOG2E\",\n    \"LOWPASS\",\n    \"LOWSHELF\",\n    \"LOW_FLOAT\",\n    \"LOW_INT\",\n    \"LSException\",\n    \"LSParserFilter\",\n    \"LUMINANCE\",\n    \"LUMINANCE_ALPHA\",\n    \"LargestContentfulPaint\",\n    \"LayoutShift\",\n    \"LayoutShiftAttribution\",\n    \"LinearAccelerationSensor\",\n    \"LinkError\",\n    \"ListFormat\",\n    \"LocalMediaStream\",\n    \"Locale\",\n    \"Location\",\n    \"Lock\",\n    \"LockManager\",\n    \"MAC\",\n    \"MAX\",\n    \"MAX_3D_TEXTURE_SIZE\",\n    \"MAX_ARRAY_TEXTURE_LAYERS\",\n    \"MAX_CLIENT_WAIT_TIMEOUT_WEBGL\",\n    \"MAX_COLOR_ATTACHMENTS\",\n    \"MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS\",\n    \"MAX_COMBINED_TEXTURE_IMAGE_UNITS\",\n    \"MAX_COMBINED_UNIFORM_BLOCKS\",\n    \"MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS\",\n    \"MAX_CUBE_MAP_TEXTURE_SIZE\",\n    \"MAX_DRAW_BUFFERS\",\n    \"MAX_ELEMENTS_INDICES\",\n    \"MAX_ELEMENTS_VERTICES\",\n    \"MAX_ELEMENT_INDEX\",\n    \"MAX_FRAGMENT_INPUT_COMPONENTS\",\n    \"MAX_FRAGMENT_UNIFORM_BLOCKS\",\n    \"MAX_FRAGMENT_UNIFORM_COMPONENTS\",\n    \"MAX_FRAGMENT_UNIFORM_VECTORS\",\n    \"MAX_PROGRAM_TEXEL_OFFSET\",\n    \"MAX_RENDERBUFFER_SIZE\",\n    \"MAX_SAFE_INTEGER\",\n    \"MAX_SAMPLES\",\n    \"MAX_SERVER_WAIT_TIMEOUT\",\n    \"MAX_TEXTURE_IMAGE_UNITS\",\n    \"MAX_TEXTURE_LOD_BIAS\",\n    \"MAX_TEXTURE_MAX_ANISOTROPY_EXT\",\n    \"MAX_TEXTURE_SIZE\",\n    \"MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS\",\n    \"MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS\",\n    \"MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS\",\n    \"MAX_UNIFORM_BLOCK_SIZE\",\n    \"MAX_UNIFORM_BUFFER_BINDINGS\",\n    \"MAX_VALUE\",\n    \"MAX_VARYING_COMPONENTS\",\n    \"MAX_VARYING_VECTORS\",\n    \"MAX_VERTEX_ATTRIBS\",\n    \"MAX_VERTEX_OUTPUT_COMPONENTS\",\n    \"MAX_VERTEX_TEXTURE_IMAGE_UNITS\",\n    \"MAX_VERTEX_UNIFORM_BLOCKS\",\n    \"MAX_VERTEX_UNIFORM_COMPONENTS\",\n    \"MAX_VERTEX_UNIFORM_VECTORS\",\n    \"MAX_VIEWPORT_DIMS\",\n    \"MEDIA_ERR_ABORTED\",\n    \"MEDIA_ERR_DECODE\",\n    \"MEDIA_ERR_ENCRYPTED\",\n    \"MEDIA_ERR_NETWORK\",\n    \"MEDIA_ERR_SRC_NOT_SUPPORTED\",\n    \"MEDIA_KEYERR_CLIENT\",\n    \"MEDIA_KEYERR_DOMAIN\",\n    \"MEDIA_KEYERR_HARDWARECHANGE\",\n    \"MEDIA_KEYERR_OUTPUT\",\n    \"MEDIA_KEYERR_SERVICE\",\n    \"MEDIA_KEYERR_UNKNOWN\",\n    \"MEDIA_RULE\",\n    \"MEDIUM_FLOAT\",\n    \"MEDIUM_INT\",\n    \"META_MASK\",\n    \"MIDIAccess\",\n    \"MIDIConnectionEvent\",\n    \"MIDIInput\",\n    \"MIDIInputMap\",\n    \"MIDIMessageEvent\",\n    \"MIDIOutput\",\n    \"MIDIOutputMap\",\n    \"MIDIPort\",\n    \"MIN\",\n    \"MIN_PROGRAM_TEXEL_OFFSET\",\n    \"MIN_SAFE_INTEGER\",\n    \"MIN_VALUE\",\n    \"MIRRORED_REPEAT\",\n    \"MODE_ASYNCHRONOUS\",\n    \"MODE_SYNCHRONOUS\",\n    \"MODIFICATION\",\n    \"MOUSEDOWN\",\n    \"MOUSEDRAG\",\n    \"MOUSEMOVE\",\n    \"MOUSEOUT\",\n    \"MOUSEOVER\",\n    \"MOUSEUP\",\n    \"MOZ_KEYFRAMES_RULE\",\n    \"MOZ_KEYFRAME_RULE\",\n    \"MOZ_SOURCE_CURSOR\",\n    \"MOZ_SOURCE_ERASER\",\n    \"MOZ_SOURCE_KEYBOARD\",\n    \"MOZ_SOURCE_MOUSE\",\n    \"MOZ_SOURCE_PEN\",\n    \"MOZ_SOURCE_TOUCH\",\n    \"MOZ_SOURCE_UNKNOWN\",\n    \"MSBehaviorUrnsCollection\",\n    \"MSBlobBuilder\",\n    \"MSCSSMatrix\",\n    \"MSCSSProperties\",\n    \"MSCSSRuleList\",\n    \"MSCompatibleInfo\",\n    \"MSCompatibleInfoCollection\",\n    \"MSCurrentStyleCSSProperties\",\n    \"MSEventObj\",\n    \"MSGESTURE_FLAG_BEGIN\",\n    \"MSGESTURE_FLAG_CANCEL\",\n    \"MSGESTURE_FLAG_END\",\n    \"MSGESTURE_FLAG_INERTIA\",\n    \"MSGESTURE_FLAG_NONE\",\n    \"MSGesture\",\n    \"MSGestureEvent\",\n    \"MSGraphicsTrust\",\n    \"MSInputMethodContext\",\n    \"MSManipulationEvent\",\n    \"MSMediaKeyError\",\n    \"MSMediaKeyMessageEvent\",\n    \"MSMediaKeyNeededEvent\",\n    \"MSMediaKeySession\",\n    \"MSMediaKeys\",\n    \"MSMimeTypesCollection\",\n    \"MSPOINTER_TYPE_MOUSE\",\n    \"MSPOINTER_TYPE_PEN\",\n    \"MSPOINTER_TYPE_TOUCH\",\n    \"MSPluginsCollection\",\n    \"MSPointerEvent\",\n    \"MSRangeCollection\",\n    \"MSSiteModeEvent\",\n    \"MSStream\",\n    \"MSStreamReader\",\n    \"MSStyleCSSProperties\",\n    \"MS_ASYNC_CALLBACK_STATUS_ASSIGN_DELEGATE\",\n    \"MS_ASYNC_CALLBACK_STATUS_CANCEL\",\n    \"MS_ASYNC_CALLBACK_STATUS_CHOOSEANY\",\n    \"MS_ASYNC_CALLBACK_STATUS_ERROR\",\n    \"MS_ASYNC_CALLBACK_STATUS_JOIN\",\n    \"MS_ASYNC_OP_STATUS_CANCELED\",\n    \"MS_ASYNC_OP_STATUS_ERROR\",\n    \"MS_ASYNC_OP_STATUS_SUCCESS\",\n    \"MS_MANIPULATION_STATE_ACTIVE\",\n    \"MS_MANIPULATION_STATE_CANCELLED\",\n    \"MS_MANIPULATION_STATE_COMMITTED\",\n    \"MS_MANIPULATION_STATE_DRAGGING\",\n    \"MS_MANIPULATION_STATE_INERTIA\",\n    \"MS_MANIPULATION_STATE_PRESELECT\",\n    \"MS_MANIPULATION_STATE_SELECTING\",\n    \"MS_MANIPULATION_STATE_STOPPED\",\n    \"MS_MEDIA_ERR_ENCRYPTED\",\n    \"MS_MEDIA_KEYERR_CLIENT\",\n    \"MS_MEDIA_KEYERR_DOMAIN\",\n    \"MS_MEDIA_KEYERR_HARDWARECHANGE\",\n    \"MS_MEDIA_KEYERR_OUTPUT\",\n    \"MS_MEDIA_KEYERR_SERVICE\",\n    \"MS_MEDIA_KEYERR_UNKNOWN\",\n    \"Map\",\n    \"Math\",\n    \"MathMLElement\",\n    \"MediaCapabilities\",\n    \"MediaCapabilitiesInfo\",\n    \"MediaController\",\n    \"MediaDeviceInfo\",\n    \"MediaDevices\",\n    \"MediaElementAudioSourceNode\",\n    \"MediaEncryptedEvent\",\n    \"MediaError\",\n    \"MediaKeyError\",\n    \"MediaKeyEvent\",\n    \"MediaKeyMessageEvent\",\n    \"MediaKeyNeededEvent\",\n    \"MediaKeySession\",\n    \"MediaKeyStatusMap\",\n    \"MediaKeySystemAccess\",\n    \"MediaKeys\",\n    \"MediaList\",\n    \"MediaMetadata\",\n    \"MediaQueryList\",\n    \"MediaQueryListEvent\",\n    \"MediaRecorder\",\n    \"MediaRecorderErrorEvent\",\n    \"MediaSession\",\n    \"MediaSettingsRange\",\n    \"MediaSource\",\n    \"MediaStream\",\n    \"MediaStreamAudioDestinationNode\",\n    \"MediaStreamAudioSourceNode\",\n    \"MediaStreamEvent\",\n    \"MediaStreamTrack\",\n    \"MediaStreamTrackAudioSourceNode\",\n    \"MediaStreamTrackEvent\",\n    \"Memory\",\n    \"MessageChannel\",\n    \"MessageEvent\",\n    \"MessagePort\",\n    \"Methods\",\n    \"Microsoft® DRM\",\n    \"MimeType\",\n    \"MimeTypeArray\",\n    \"Module\",\n    \"MouseEvent\",\n    \"MouseScrollEvent\",\n    \"MouseWheelEvent\",\n    \"MozAnimation\",\n    \"MozAnimationDelay\",\n    \"MozAnimationDirection\",\n    \"MozAnimationDuration\",\n    \"MozAnimationFillMode\",\n    \"MozAnimationIterationCount\",\n    \"MozAnimationName\",\n    \"MozAnimationPlayState\",\n    \"MozAnimationTimingFunction\",\n    \"MozAppearance\",\n    \"MozBackfaceVisibility\",\n    \"MozBinding\",\n    \"MozBorderBottomColors\",\n    \"MozBorderEnd\",\n    \"MozBorderEndColor\",\n    \"MozBorderEndStyle\",\n    \"MozBorderEndWidth\",\n    \"MozBorderImage\",\n    \"MozBorderLeftColors\",\n    \"MozBorderRightColors\",\n    \"MozBorderStart\",\n    \"MozBorderStartColor\",\n    \"MozBorderStartStyle\",\n    \"MozBorderStartWidth\",\n    \"MozBorderTopColors\",\n    \"MozBoxAlign\",\n    \"MozBoxDirection\",\n    \"MozBoxFlex\",\n    \"MozBoxOrdinalGroup\",\n    \"MozBoxOrient\",\n    \"MozBoxPack\",\n    \"MozBoxSizing\",\n    \"MozCSSKeyframeRule\",\n    \"MozCSSKeyframesRule\",\n    \"MozColumnCount\",\n    \"MozColumnFill\",\n    \"MozColumnGap\",\n    \"MozColumnRule\",\n    \"MozColumnRuleColor\",\n    \"MozColumnRuleStyle\",\n    \"MozColumnRuleWidth\",\n    \"MozColumnWidth\",\n    \"MozColumns\",\n    \"MozContactChangeEvent\",\n    \"MozFloatEdge\",\n    \"MozFontFeatureSettings\",\n    \"MozFontLanguageOverride\",\n    \"MozForceBrokenImageIcon\",\n    \"MozHyphens\",\n    \"MozImageRegion\",\n    \"MozMarginEnd\",\n    \"MozMarginStart\",\n    \"MozMmsEvent\",\n    \"MozMmsMessage\",\n    \"MozMobileMessageThread\",\n    \"MozOSXFontSmoothing\",\n    \"MozOrient\",\n    \"MozOutlineRadius\",\n    \"MozOutlineRadiusBottomleft\",\n    \"MozOutlineRadiusBottomright\",\n    \"MozOutlineRadiusTopleft\",\n    \"MozOutlineRadiusTopright\",\n    \"MozPaddingEnd\",\n    \"MozPaddingStart\",\n    \"MozPerspective\",\n    \"MozPerspectiveOrigin\",\n    \"MozPowerManager\",\n    \"MozSettingsEvent\",\n    \"MozSmsEvent\",\n    \"MozSmsMessage\",\n    \"MozStackSizing\",\n    \"MozTabSize\",\n    \"MozTextAlignLast\",\n    \"MozTextDecorationColor\",\n    \"MozTextDecorationLine\",\n    \"MozTextDecorationStyle\",\n    \"MozTextSizeAdjust\",\n    \"MozTransform\",\n    \"MozTransformOrigin\",\n    \"MozTransformStyle\",\n    \"MozTransition\",\n    \"MozTransitionDelay\",\n    \"MozTransitionDuration\",\n    \"MozTransitionProperty\",\n    \"MozTransitionTimingFunction\",\n    \"MozUserFocus\",\n    \"MozUserInput\",\n    \"MozUserModify\",\n    \"MozUserSelect\",\n    \"MozWindowDragging\",\n    \"MozWindowShadow\",\n    \"MutationEvent\",\n    \"MutationObserver\",\n    \"MutationRecord\",\n    \"NAMESPACE_ERR\",\n    \"NAMESPACE_RULE\",\n    \"NEAREST\",\n    \"NEAREST_MIPMAP_LINEAR\",\n    \"NEAREST_MIPMAP_NEAREST\",\n    \"NEGATIVE_INFINITY\",\n    \"NETWORK_EMPTY\",\n    \"NETWORK_ERR\",\n    \"NETWORK_IDLE\",\n    \"NETWORK_LOADED\",\n    \"NETWORK_LOADING\",\n    \"NETWORK_NO_SOURCE\",\n    \"NEVER\",\n    \"NEW\",\n    \"NEXT\",\n    \"NEXT_NO_DUPLICATE\",\n    \"NICEST\",\n    \"NODE_AFTER\",\n    \"NODE_BEFORE\",\n    \"NODE_BEFORE_AND_AFTER\",\n    \"NODE_INSIDE\",\n    \"NONE\",\n    \"NON_TRANSIENT_ERR\",\n    \"NOTATION_NODE\",\n    \"NOTCH\",\n    \"NOTEQUAL\",\n    \"NOT_ALLOWED_ERR\",\n    \"NOT_FOUND_ERR\",\n    \"NOT_INSTALLED\",\n    \"NOT_READABLE_ERR\",\n    \"NOT_SUPPORTED_ERR\",\n    \"NO_DATA_ALLOWED_ERR\",\n    \"NO_ERR\",\n    \"NO_ERROR\",\n    \"NO_MODIFICATION_ALLOWED_ERR\",\n    \"NO_UPDATE\",\n    \"NUMBER_TYPE\",\n    \"NUM_COMPRESSED_TEXTURE_FORMATS\",\n    \"NaN\",\n    \"NamedNodeMap\",\n    \"Native Client\",\n    \"NavigationPreloadManager\",\n    \"Navigator\",\n    \"NearbyLinks\",\n    \"NetworkInformation\",\n    \"Node\",\n    \"NodeFilter\",\n    \"NodeIterator\",\n    \"NodeList\",\n    \"Notation\",\n    \"Notification\",\n    \"NotifyPaintEvent\",\n    \"Number\",\n    \"NumberFormat\",\n    \"OBJECT_TYPE\",\n    \"OBSOLETE\",\n    \"OES_element_index_uint\",\n    \"OES_standard_derivatives\",\n    \"OES_texture_float\",\n    \"OES_texture_float_linear\",\n    \"OK\",\n    \"ONE\",\n    \"ONE_MINUS_CONSTANT_ALPHA\",\n    \"ONE_MINUS_CONSTANT_COLOR\",\n    \"ONE_MINUS_DST_ALPHA\",\n    \"ONE_MINUS_DST_COLOR\",\n    \"ONE_MINUS_SRC_ALPHA\",\n    \"ONE_MINUS_SRC_COLOR\",\n    \"OPEN\",\n    \"OPENBSD\",\n    \"OPENED\",\n    \"OPENING\",\n    \"ORDERED_NODE_ITERATOR_TYPE\",\n    \"ORDERED_NODE_SNAPSHOT_TYPE\",\n    \"OS_UPDATE\",\n    \"OTHER_ERROR\",\n    \"OUT_OF_MEMORY\",\n    \"Object\",\n    \"OfflineAudioCompletionEvent\",\n    \"OfflineAudioContext\",\n    \"OfflineResourceList\",\n    \"OffscreenCanvas\",\n    \"OffscreenCanvasRenderingContext2D\",\n    \"OnInstalledReason\",\n    \"OnRestartRequiredReason\",\n    \"Option\",\n    \"OrientationSensor\",\n    \"OscillatorNode\",\n    \"OverconstrainedError\",\n    \"OverconstrainedErrorEvent\",\n    \"OverflowEvent\",\n    \"PACKAGE\",\n    \"PACK_ALIGNMENT\",\n    \"PACK_ROW_LENGTH\",\n    \"PACK_SKIP_PIXELS\",\n    \"PACK_SKIP_ROWS\",\n    \"PAGE_RULE\",\n    \"PARSE_ERR\",\n    \"PATHSEG_ARC_ABS\",\n    \"PATHSEG_ARC_REL\",\n    \"PATHSEG_CLOSEPATH\",\n    \"PATHSEG_CURVETO_CUBIC_ABS\",\n    \"PATHSEG_CURVETO_CUBIC_REL\",\n    \"PATHSEG_CURVETO_CUBIC_SMOOTH_ABS\",\n    \"PATHSEG_CURVETO_CUBIC_SMOOTH_REL\",\n    \"PATHSEG_CURVETO_QUADRATIC_ABS\",\n    \"PATHSEG_CURVETO_QUADRATIC_REL\",\n    \"PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS\",\n    \"PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL\",\n    \"PATHSEG_LINETO_ABS\",\n    \"PATHSEG_LINETO_HORIZONTAL_ABS\",\n    \"PATHSEG_LINETO_HORIZONTAL_REL\",\n    \"PATHSEG_LINETO_REL\",\n    \"PATHSEG_LINETO_VERTICAL_ABS\",\n    \"PATHSEG_LINETO_VERTICAL_REL\",\n    \"PATHSEG_MOVETO_ABS\",\n    \"PATHSEG_MOVETO_REL\",\n    \"PATHSEG_UNKNOWN\",\n    \"PATH_EXISTS_ERR\",\n    \"PEAKING\",\n    \"PERIODIC\",\n    \"PERMISSION_DENIED\",\n    \"PERSISTENT\",\n    \"PI\",\n    \"PIXEL_PACK_BUFFER\",\n    \"PIXEL_PACK_BUFFER_BINDING\",\n    \"PIXEL_UNPACK_BUFFER\",\n    \"PIXEL_UNPACK_BUFFER_BINDING\",\n    \"PLAYING_STATE\",\n    \"POINTS\",\n    \"POLYGON_OFFSET_FACTOR\",\n    \"POLYGON_OFFSET_FILL\",\n    \"POLYGON_OFFSET_UNITS\",\n    \"POSITION_UNAVAILABLE\",\n    \"POSITIVE_INFINITY\",\n    \"PREV\",\n    \"PREV_NO_DUPLICATE\",\n    \"PROCESSING_INSTRUCTION_NODE\",\n    \"PageChangeEvent\",\n    \"PageTransitionEvent\",\n    \"PaintRequest\",\n    \"PaintRequestList\",\n    \"PannerNode\",\n    \"PasswordCredential\",\n    \"Path2D\",\n    \"PaymentAddress\",\n    \"PaymentInstruments\",\n    \"PaymentManager\",\n    \"PaymentMethodChangeEvent\",\n    \"PaymentRequest\",\n    \"PaymentRequestUpdateEvent\",\n    \"PaymentResponse\",\n    \"Performance\",\n    \"PerformanceElementTiming\",\n    \"PerformanceEntry\",\n    \"PerformanceEventTiming\",\n    \"PerformanceLongTaskTiming\",\n    \"PerformanceMark\",\n    \"PerformanceMeasure\",\n    \"PerformanceNavigation\",\n    \"PerformanceNavigationTiming\",\n    \"PerformanceObserver\",\n    \"PerformanceObserverEntryList\",\n    \"PerformancePaintTiming\",\n    \"PerformanceResourceTiming\",\n    \"PerformanceServerTiming\",\n    \"PerformanceTiming\",\n    \"PeriodicSyncManager\",\n    \"PeriodicWave\",\n    \"PermissionStatus\",\n    \"Permissions\",\n    \"PhotoCapabilities\",\n    \"PictureInPictureWindow\",\n    \"PlatformArch\",\n    \"PlatformNaclArch\",\n    \"PlatformOs\",\n    \"Plugin\",\n    \"PluginArray\",\n    \"PluralRules\",\n    \"PointerEvent\",\n    \"PopStateEvent\",\n    \"PopupBlockedEvent\",\n    \"Position\",\n    \"PositionError\",\n    \"Presentation\",\n    \"PresentationAvailability\",\n    \"PresentationConnection\",\n    \"PresentationConnectionAvailableEvent\",\n    \"PresentationConnectionCloseEvent\",\n    \"PresentationConnectionList\",\n    \"PresentationReceiver\",\n    \"PresentationRequest\",\n    \"ProcessingInstruction\",\n    \"ProgressEvent\",\n    \"Promise\",\n    \"PromiseRejectionEvent\",\n    \"PropertyNodeList\",\n    \"Proxy\",\n    \"PublicKeyCredential\",\n    \"PushManager\",\n    \"PushSubscription\",\n    \"PushSubscriptionOptions\",\n    \"Q\",\n    \"QUERY_RESULT\",\n    \"QUERY_RESULT_AVAILABLE\",\n    \"QUOTA_ERR\",\n    \"QUOTA_EXCEEDED_ERR\",\n    \"QueryInterface\",\n    \"R11F_G11F_B10F\",\n    \"R16F\",\n    \"R16I\",\n    \"R16UI\",\n    \"R32F\",\n    \"R32I\",\n    \"R32UI\",\n    \"R8\",\n    \"R8I\",\n    \"R8UI\",\n    \"R8_SNORM\",\n    \"RASTERIZER_DISCARD\",\n    \"READY_TO_RUN\",\n    \"READ_BUFFER\",\n    \"READ_FRAMEBUFFER\",\n    \"READ_FRAMEBUFFER_BINDING\",\n    \"READ_ONLY\",\n    \"READ_ONLY_ERR\",\n    \"READ_WRITE\",\n    \"RED\",\n    \"RED_BITS\",\n    \"RED_INTEGER\",\n    \"REMOVAL\",\n    \"RENDERBUFFER\",\n    \"RENDERBUFFER_ALPHA_SIZE\",\n    \"RENDERBUFFER_BINDING\",\n    \"RENDERBUFFER_BLUE_SIZE\",\n    \"RENDERBUFFER_DEPTH_SIZE\",\n    \"RENDERBUFFER_GREEN_SIZE\",\n    \"RENDERBUFFER_HEIGHT\",\n    \"RENDERBUFFER_INTERNAL_FORMAT\",\n    \"RENDERBUFFER_RED_SIZE\",\n    \"RENDERBUFFER_SAMPLES\",\n    \"RENDERBUFFER_STENCIL_SIZE\",\n    \"RENDERBUFFER_WIDTH\",\n    \"RENDERER\",\n    \"RENDERING_INTENT_ABSOLUTE_COLORIMETRIC\",\n    \"RENDERING_INTENT_AUTO\",\n    \"RENDERING_INTENT_PERCEPTUAL\",\n    \"RENDERING_INTENT_RELATIVE_COLORIMETRIC\",\n    \"RENDERING_INTENT_SATURATION\",\n    \"RENDERING_INTENT_UNKNOWN\",\n    \"REPEAT\",\n    \"REPLACE\",\n    \"RG\",\n    \"RG16F\",\n    \"RG16I\",\n    \"RG16UI\",\n    \"RG32F\",\n    \"RG32I\",\n    \"RG32UI\",\n    \"RG8\",\n    \"RG8I\",\n    \"RG8UI\",\n    \"RG8_SNORM\",\n    \"RGB\",\n    \"RGB10_A2\",\n    \"RGB10_A2UI\",\n    \"RGB16F\",\n    \"RGB16I\",\n    \"RGB16UI\",\n    \"RGB32F\",\n    \"RGB32I\",\n    \"RGB32UI\",\n    \"RGB565\",\n    \"RGB5_A1\",\n    \"RGB8\",\n    \"RGB8I\",\n    \"RGB8UI\",\n    \"RGB8_SNORM\",\n    \"RGB9_E5\",\n    \"RGBA\",\n    \"RGBA16F\",\n    \"RGBA16I\",\n    \"RGBA16UI\",\n    \"RGBA32F\",\n    \"RGBA32I\",\n    \"RGBA32UI\",\n    \"RGBA4\",\n    \"RGBA8\",\n    \"RGBA8I\",\n    \"RGBA8UI\",\n    \"RGBA8_SNORM\",\n    \"RGBA_INTEGER\",\n    \"RGBColor\",\n    \"RGB_INTEGER\",\n    \"RG_INTEGER\",\n    \"ROTATION_CLOCKWISE\",\n    \"ROTATION_COUNTERCLOCKWISE\",\n    \"RTCCertificate\",\n    \"RTCDTMFSender\",\n    \"RTCDTMFToneChangeEvent\",\n    \"RTCDataChannel\",\n    \"RTCDataChannelEvent\",\n    \"RTCDtlsTransport\",\n    \"RTCError\",\n    \"RTCErrorEvent\",\n    \"RTCIceCandidate\",\n    \"RTCIceTransport\",\n    \"RTCPeerConnection\",\n    \"RTCPeerConnectionIceErrorEvent\",\n    \"RTCPeerConnectionIceEvent\",\n    \"RTCRtpReceiver\",\n    \"RTCRtpSender\",\n    \"RTCRtpTransceiver\",\n    \"RTCSctpTransport\",\n    \"RTCSessionDescription\",\n    \"RTCStatsReport\",\n    \"RTCTrackEvent\",\n    \"RUNNING\",\n    \"RadioNodeList\",\n    \"Range\",\n    \"RangeError\",\n    \"RangeException\",\n    \"ReadableByteStream\",\n    \"ReadableStream\",\n    \"ReadableStreamDefaultReader\",\n    \"RecordErrorEvent\",\n    \"Rect\",\n    \"ReferenceError\",\n    \"Reflect\",\n    \"RegExp\",\n    \"RelativeOrientationSensor\",\n    \"RelativeTimeFormat\",\n    \"RemotePlayback\",\n    \"ReportingObserver\",\n    \"Request\",\n    \"RequestUpdateCheckStatus\",\n    \"ResizeObserver\",\n    \"ResizeObserverEntry\",\n    \"ResizeObserverSize\",\n    \"Response\",\n    \"RunningState\",\n    \"RuntimeError\",\n    \"SAMPLER_2D\",\n    \"SAMPLER_2D_ARRAY\",\n    \"SAMPLER_2D_ARRAY_SHADOW\",\n    \"SAMPLER_2D_SHADOW\",\n    \"SAMPLER_3D\",\n    \"SAMPLER_BINDING\",\n    \"SAMPLER_CUBE\",\n    \"SAMPLER_CUBE_SHADOW\",\n    \"SAMPLES\",\n    \"SAMPLE_ALPHA_TO_COVERAGE\",\n    \"SAMPLE_BUFFERS\",\n    \"SAMPLE_COVERAGE\",\n    \"SAMPLE_COVERAGE_INVERT\",\n    \"SAMPLE_COVERAGE_VALUE\",\n    \"SAWTOOTH\",\n    \"SCHEDULED_STATE\",\n    \"SCISSOR_BOX\",\n    \"SCISSOR_TEST\",\n    \"SCROLL_PAGE_DOWN\",\n    \"SCROLL_PAGE_UP\",\n    \"SDP_ANSWER\",\n    \"SDP_OFFER\",\n    \"SDP_PRANSWER\",\n    \"SECURITY_ERR\",\n    \"SELECT\",\n    \"SEPARATE_ATTRIBS\",\n    \"SERIALIZE_ERR\",\n    \"SEVERITY_ERROR\",\n    \"SEVERITY_FATAL_ERROR\",\n    \"SEVERITY_WARNING\",\n    \"SHADER_COMPILER\",\n    \"SHADER_TYPE\",\n    \"SHADING_LANGUAGE_VERSION\",\n    \"SHARED_MODULE_UPDATE\",\n    \"SHIFT_MASK\",\n    \"SHORT\",\n    \"SHOWING\",\n    \"SHOW_ALL\",\n    \"SHOW_ATTRIBUTE\",\n    \"SHOW_CDATA_SECTION\",\n    \"SHOW_COMMENT\",\n    \"SHOW_DOCUMENT\",\n    \"SHOW_DOCUMENT_FRAGMENT\",\n    \"SHOW_DOCUMENT_TYPE\",\n    \"SHOW_ELEMENT\",\n    \"SHOW_ENTITY\",\n    \"SHOW_ENTITY_REFERENCE\",\n    \"SHOW_NOTATION\",\n    \"SHOW_PROCESSING_INSTRUCTION\",\n    \"SHOW_TEXT\",\n    \"SIGNALED\",\n    \"SIGNED_NORMALIZED\",\n    \"SINE\",\n    \"SKIN\",\n    \"SOUNDFIELD\",\n    \"SQLError\",\n    \"SQLException\",\n    \"SQLResultSet\",\n    \"SQLResultSetRowList\",\n    \"SQLTransaction\",\n    \"SQRT1_2\",\n    \"SQRT2\",\n    \"SQUARE\",\n    \"SRC_ALPHA\",\n    \"SRC_ALPHA_SATURATE\",\n    \"SRC_COLOR\",\n    \"SRGB\",\n    \"SRGB8\",\n    \"SRGB8_ALPHA8\",\n    \"START_TO_END\",\n    \"START_TO_START\",\n    \"STATIC_COPY\",\n    \"STATIC_DRAW\",\n    \"STATIC_READ\",\n    \"STENCIL\",\n    \"STENCIL_ATTACHMENT\",\n    \"STENCIL_BACK_FAIL\",\n    \"STENCIL_BACK_FUNC\",\n    \"STENCIL_BACK_PASS_DEPTH_FAIL\",\n    \"STENCIL_BACK_PASS_DEPTH_PASS\",\n    \"STENCIL_BACK_REF\",\n    \"STENCIL_BACK_VALUE_MASK\",\n    \"STENCIL_BACK_WRITEMASK\",\n    \"STENCIL_BITS\",\n    \"STENCIL_BUFFER_BIT\",\n    \"STENCIL_CLEAR_VALUE\",\n    \"STENCIL_FAIL\",\n    \"STENCIL_FUNC\",\n    \"STENCIL_INDEX\",\n    \"STENCIL_INDEX8\",\n    \"STENCIL_PASS_DEPTH_FAIL\",\n    \"STENCIL_PASS_DEPTH_PASS\",\n    \"STENCIL_REF\",\n    \"STENCIL_TEST\",\n    \"STENCIL_VALUE_MASK\",\n    \"STENCIL_WRITEMASK\",\n    \"STREAM_COPY\",\n    \"STREAM_DRAW\",\n    \"STREAM_READ\",\n    \"STRING_TYPE\",\n    \"STYLE_RULE\",\n    \"SUBPIXEL_BITS\",\n    \"SUPPORTS_RULE\",\n    \"SVGAElement\",\n    \"SVGAltGlyphDefElement\",\n    \"SVGAltGlyphElement\",\n    \"SVGAltGlyphItemElement\",\n    \"SVGAngle\",\n    \"SVGAnimateColorElement\",\n    \"SVGAnimateElement\",\n    \"SVGAnimateMotionElement\",\n    \"SVGAnimateTransformElement\",\n    \"SVGAnimatedAngle\",\n    \"SVGAnimatedBoolean\",\n    \"SVGAnimatedEnumeration\",\n    \"SVGAnimatedInteger\",\n    \"SVGAnimatedLength\",\n    \"SVGAnimatedLengthList\",\n    \"SVGAnimatedNumber\",\n    \"SVGAnimatedNumberList\",\n    \"SVGAnimatedPreserveAspectRatio\",\n    \"SVGAnimatedRect\",\n    \"SVGAnimatedString\",\n    \"SVGAnimatedTransformList\",\n    \"SVGAnimationElement\",\n    \"SVGCircleElement\",\n    \"SVGClipPathElement\",\n    \"SVGColor\",\n    \"SVGComponentTransferFunctionElement\",\n    \"SVGCursorElement\",\n    \"SVGDefsElement\",\n    \"SVGDescElement\",\n    \"SVGDiscardElement\",\n    \"SVGDocument\",\n    \"SVGElement\",\n    \"SVGElementInstance\",\n    \"SVGElementInstanceList\",\n    \"SVGEllipseElement\",\n    \"SVGException\",\n    \"SVGFEBlendElement\",\n    \"SVGFEColorMatrixElement\",\n    \"SVGFEComponentTransferElement\",\n    \"SVGFECompositeElement\",\n    \"SVGFEConvolveMatrixElement\",\n    \"SVGFEDiffuseLightingElement\",\n    \"SVGFEDisplacementMapElement\",\n    \"SVGFEDistantLightElement\",\n    \"SVGFEDropShadowElement\",\n    \"SVGFEFloodElement\",\n    \"SVGFEFuncAElement\",\n    \"SVGFEFuncBElement\",\n    \"SVGFEFuncGElement\",\n    \"SVGFEFuncRElement\",\n    \"SVGFEGaussianBlurElement\",\n    \"SVGFEImageElement\",\n    \"SVGFEMergeElement\",\n    \"SVGFEMergeNodeElement\",\n    \"SVGFEMorphologyElement\",\n    \"SVGFEOffsetElement\",\n    \"SVGFEPointLightElement\",\n    \"SVGFESpecularLightingElement\",\n    \"SVGFESpotLightElement\",\n    \"SVGFETileElement\",\n    \"SVGFETurbulenceElement\",\n    \"SVGFilterElement\",\n    \"SVGFontElement\",\n    \"SVGFontFaceElement\",\n    \"SVGFontFaceFormatElement\",\n    \"SVGFontFaceNameElement\",\n    \"SVGFontFaceSrcElement\",\n    \"SVGFontFaceUriElement\",\n    \"SVGForeignObjectElement\",\n    \"SVGGElement\",\n    \"SVGGeometryElement\",\n    \"SVGGlyphElement\",\n    \"SVGGlyphRefElement\",\n    \"SVGGradientElement\",\n    \"SVGGraphicsElement\",\n    \"SVGHKernElement\",\n    \"SVGImageElement\",\n    \"SVGLength\",\n    \"SVGLengthList\",\n    \"SVGLineElement\",\n    \"SVGLinearGradientElement\",\n    \"SVGMPathElement\",\n    \"SVGMarkerElement\",\n    \"SVGMaskElement\",\n    \"SVGMatrix\",\n    \"SVGMetadataElement\",\n    \"SVGMissingGlyphElement\",\n    \"SVGNumber\",\n    \"SVGNumberList\",\n    \"SVGPaint\",\n    \"SVGPathElement\",\n    \"SVGPathSeg\",\n    \"SVGPathSegArcAbs\",\n    \"SVGPathSegArcRel\",\n    \"SVGPathSegClosePath\",\n    \"SVGPathSegCurvetoCubicAbs\",\n    \"SVGPathSegCurvetoCubicRel\",\n    \"SVGPathSegCurvetoCubicSmoothAbs\",\n    \"SVGPathSegCurvetoCubicSmoothRel\",\n    \"SVGPathSegCurvetoQuadraticAbs\",\n    \"SVGPathSegCurvetoQuadraticRel\",\n    \"SVGPathSegCurvetoQuadraticSmoothAbs\",\n    \"SVGPathSegCurvetoQuadraticSmoothRel\",\n    \"SVGPathSegLinetoAbs\",\n    \"SVGPathSegLinetoHorizontalAbs\",\n    \"SVGPathSegLinetoHorizontalRel\",\n    \"SVGPathSegLinetoRel\",\n    \"SVGPathSegLinetoVerticalAbs\",\n    \"SVGPathSegLinetoVerticalRel\",\n    \"SVGPathSegList\",\n    \"SVGPathSegMovetoAbs\",\n    \"SVGPathSegMovetoRel\",\n    \"SVGPatternElement\",\n    \"SVGPoint\",\n    \"SVGPointList\",\n    \"SVGPolygonElement\",\n    \"SVGPolylineElement\",\n    \"SVGPreserveAspectRatio\",\n    \"SVGRadialGradientElement\",\n    \"SVGRect\",\n    \"SVGRectElement\",\n    \"SVGRenderingIntent\",\n    \"SVGSVGElement\",\n    \"SVGScriptElement\",\n    \"SVGSetElement\",\n    \"SVGStopElement\",\n    \"SVGStringList\",\n    \"SVGStyleElement\",\n    \"SVGSwitchElement\",\n    \"SVGSymbolElement\",\n    \"SVGTRefElement\",\n    \"SVGTSpanElement\",\n    \"SVGTextContentElement\",\n    \"SVGTextElement\",\n    \"SVGTextPathElement\",\n    \"SVGTextPositioningElement\",\n    \"SVGTitleElement\",\n    \"SVGTransform\",\n    \"SVGTransformList\",\n    \"SVGUnitTypes\",\n    \"SVGUseElement\",\n    \"SVGVKernElement\",\n    \"SVGViewElement\",\n    \"SVGViewSpec\",\n    \"SVGZoomAndPan\",\n    \"SVGZoomEvent\",\n    \"SVG_ANGLETYPE_DEG\",\n    \"SVG_ANGLETYPE_GRAD\",\n    \"SVG_ANGLETYPE_RAD\",\n    \"SVG_ANGLETYPE_UNKNOWN\",\n    \"SVG_ANGLETYPE_UNSPECIFIED\",\n    \"SVG_CHANNEL_A\",\n    \"SVG_CHANNEL_B\",\n    \"SVG_CHANNEL_G\",\n    \"SVG_CHANNEL_R\",\n    \"SVG_CHANNEL_UNKNOWN\",\n    \"SVG_COLORTYPE_CURRENTCOLOR\",\n    \"SVG_COLORTYPE_RGBCOLOR\",\n    \"SVG_COLORTYPE_RGBCOLOR_ICCCOLOR\",\n    \"SVG_COLORTYPE_UNKNOWN\",\n    \"SVG_EDGEMODE_DUPLICATE\",\n    \"SVG_EDGEMODE_NONE\",\n    \"SVG_EDGEMODE_UNKNOWN\",\n    \"SVG_EDGEMODE_WRAP\",\n    \"SVG_FEBLEND_MODE_COLOR\",\n    \"SVG_FEBLEND_MODE_COLOR_BURN\",\n    \"SVG_FEBLEND_MODE_COLOR_DODGE\",\n    \"SVG_FEBLEND_MODE_DARKEN\",\n    \"SVG_FEBLEND_MODE_DIFFERENCE\",\n    \"SVG_FEBLEND_MODE_EXCLUSION\",\n    \"SVG_FEBLEND_MODE_HARD_LIGHT\",\n    \"SVG_FEBLEND_MODE_HUE\",\n    \"SVG_FEBLEND_MODE_LIGHTEN\",\n    \"SVG_FEBLEND_MODE_LUMINOSITY\",\n    \"SVG_FEBLEND_MODE_MULTIPLY\",\n    \"SVG_FEBLEND_MODE_NORMAL\",\n    \"SVG_FEBLEND_MODE_OVERLAY\",\n    \"SVG_FEBLEND_MODE_SATURATION\",\n    \"SVG_FEBLEND_MODE_SCREEN\",\n    \"SVG_FEBLEND_MODE_SOFT_LIGHT\",\n    \"SVG_FEBLEND_MODE_UNKNOWN\",\n    \"SVG_FECOLORMATRIX_TYPE_HUEROTATE\",\n    \"SVG_FECOLORMATRIX_TYPE_LUMINANCETOALPHA\",\n    \"SVG_FECOLORMATRIX_TYPE_MATRIX\",\n    \"SVG_FECOLORMATRIX_TYPE_SATURATE\",\n    \"SVG_FECOLORMATRIX_TYPE_UNKNOWN\",\n    \"SVG_FECOMPONENTTRANSFER_TYPE_DISCRETE\",\n    \"SVG_FECOMPONENTTRANSFER_TYPE_GAMMA\",\n    \"SVG_FECOMPONENTTRANSFER_TYPE_IDENTITY\",\n    \"SVG_FECOMPONENTTRANSFER_TYPE_LINEAR\",\n    \"SVG_FECOMPONENTTRANSFER_TYPE_TABLE\",\n    \"SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN\",\n    \"SVG_FECOMPOSITE_OPERATOR_ARITHMETIC\",\n    \"SVG_FECOMPOSITE_OPERATOR_ATOP\",\n    \"SVG_FECOMPOSITE_OPERATOR_IN\",\n    \"SVG_FECOMPOSITE_OPERATOR_OUT\",\n    \"SVG_FECOMPOSITE_OPERATOR_OVER\",\n    \"SVG_FECOMPOSITE_OPERATOR_UNKNOWN\",\n    \"SVG_FECOMPOSITE_OPERATOR_XOR\",\n    \"SVG_INVALID_VALUE_ERR\",\n    \"SVG_LENGTHTYPE_CM\",\n    \"SVG_LENGTHTYPE_EMS\",\n    \"SVG_LENGTHTYPE_EXS\",\n    \"SVG_LENGTHTYPE_IN\",\n    \"SVG_LENGTHTYPE_MM\",\n    \"SVG_LENGTHTYPE_NUMBER\",\n    \"SVG_LENGTHTYPE_PC\",\n    \"SVG_LENGTHTYPE_PERCENTAGE\",\n    \"SVG_LENGTHTYPE_PT\",\n    \"SVG_LENGTHTYPE_PX\",\n    \"SVG_LENGTHTYPE_UNKNOWN\",\n    \"SVG_MARKERUNITS_STROKEWIDTH\",\n    \"SVG_MARKERUNITS_UNKNOWN\",\n    \"SVG_MARKERUNITS_USERSPACEONUSE\",\n    \"SVG_MARKER_ORIENT_ANGLE\",\n    \"SVG_MARKER_ORIENT_AUTO\",\n    \"SVG_MARKER_ORIENT_UNKNOWN\",\n    \"SVG_MASKTYPE_ALPHA\",\n    \"SVG_MASKTYPE_LUMINANCE\",\n    \"SVG_MATRIX_NOT_INVERTABLE\",\n    \"SVG_MEETORSLICE_MEET\",\n    \"SVG_MEETORSLICE_SLICE\",\n    \"SVG_MEETORSLICE_UNKNOWN\",\n    \"SVG_MORPHOLOGY_OPERATOR_DILATE\",\n    \"SVG_MORPHOLOGY_OPERATOR_ERODE\",\n    \"SVG_MORPHOLOGY_OPERATOR_UNKNOWN\",\n    \"SVG_PAINTTYPE_CURRENTCOLOR\",\n    \"SVG_PAINTTYPE_NONE\",\n    \"SVG_PAINTTYPE_RGBCOLOR\",\n    \"SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR\",\n    \"SVG_PAINTTYPE_UNKNOWN\",\n    \"SVG_PAINTTYPE_URI\",\n    \"SVG_PAINTTYPE_URI_CURRENTCOLOR\",\n    \"SVG_PAINTTYPE_URI_NONE\",\n    \"SVG_PAINTTYPE_URI_RGBCOLOR\",\n    \"SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR\",\n    \"SVG_PRESERVEASPECTRATIO_NONE\",\n    \"SVG_PRESERVEASPECTRATIO_UNKNOWN\",\n    \"SVG_PRESERVEASPECTRATIO_XMAXYMAX\",\n    \"SVG_PRESERVEASPECTRATIO_XMAXYMID\",\n    \"SVG_PRESERVEASPECTRATIO_XMAXYMIN\",\n    \"SVG_PRESERVEASPECTRATIO_XMIDYMAX\",\n    \"SVG_PRESERVEASPECTRATIO_XMIDYMID\",\n    \"SVG_PRESERVEASPECTRATIO_XMIDYMIN\",\n    \"SVG_PRESERVEASPECTRATIO_XMINYMAX\",\n    \"SVG_PRESERVEASPECTRATIO_XMINYMID\",\n    \"SVG_PRESERVEASPECTRATIO_XMINYMIN\",\n    \"SVG_SPREADMETHOD_PAD\",\n    \"SVG_SPREADMETHOD_REFLECT\",\n    \"SVG_SPREADMETHOD_REPEAT\",\n    \"SVG_SPREADMETHOD_UNKNOWN\",\n    \"SVG_STITCHTYPE_NOSTITCH\",\n    \"SVG_STITCHTYPE_STITCH\",\n    \"SVG_STITCHTYPE_UNKNOWN\",\n    \"SVG_TRANSFORM_MATRIX\",\n    \"SVG_TRANSFORM_ROTATE\",\n    \"SVG_TRANSFORM_SCALE\",\n    \"SVG_TRANSFORM_SKEWX\",\n    \"SVG_TRANSFORM_SKEWY\",\n    \"SVG_TRANSFORM_TRANSLATE\",\n    \"SVG_TRANSFORM_UNKNOWN\",\n    \"SVG_TURBULENCE_TYPE_FRACTALNOISE\",\n    \"SVG_TURBULENCE_TYPE_TURBULENCE\",\n    \"SVG_TURBULENCE_TYPE_UNKNOWN\",\n    \"SVG_UNIT_TYPE_OBJECTBOUNDINGBOX\",\n    \"SVG_UNIT_TYPE_UNKNOWN\",\n    \"SVG_UNIT_TYPE_USERSPACEONUSE\",\n    \"SVG_WRONG_TYPE_ERR\",\n    \"SVG_ZOOMANDPAN_DISABLE\",\n    \"SVG_ZOOMANDPAN_MAGNIFY\",\n    \"SVG_ZOOMANDPAN_UNKNOWN\",\n    \"SYNC_CONDITION\",\n    \"SYNC_FENCE\",\n    \"SYNC_FLAGS\",\n    \"SYNC_FLUSH_COMMANDS_BIT\",\n    \"SYNC_GPU_COMMANDS_COMPLETE\",\n    \"SYNC_STATUS\",\n    \"SYNTAX_ERR\",\n    \"SavedPages\",\n    \"Screen\",\n    \"ScreenOrientation\",\n    \"Script\",\n    \"ScriptEngine\",\n    \"ScriptEngineBuildVersion\",\n    \"ScriptEngineMajorVersion\",\n    \"ScriptEngineMinorVersion\",\n    \"ScriptProcessorNode\",\n    \"ScrollAreaEvent\",\n    \"SecurityPolicyViolationEvent\",\n    \"Selection\",\n    \"Sensor\",\n    \"SensorErrorEvent\",\n    \"ServiceWorker\",\n    \"ServiceWorkerContainer\",\n    \"ServiceWorkerMessageEvent\",\n    \"ServiceWorkerRegistration\",\n    \"SessionDescription\",\n    \"Set\",\n    \"ShadowRoot\",\n    \"SharedArrayBuffer\",\n    \"SharedWorker\",\n    \"SimpleGestureEvent\",\n    \"SourceBuffer\",\n    \"SourceBufferList\",\n    \"SpeechSynthesis\",\n    \"SpeechSynthesisErrorEvent\",\n    \"SpeechSynthesisEvent\",\n    \"SpeechSynthesisUtterance\",\n    \"SpeechSynthesisVoice\",\n    \"StaticRange\",\n    \"StereoPannerNode\",\n    \"StopIteration\",\n    \"Storage\",\n    \"StorageEvent\",\n    \"StorageManager\",\n    \"String\",\n    \"StyleMedia\",\n    \"StylePropertyMap\",\n    \"StylePropertyMapReadOnly\",\n    \"StyleSheet\",\n    \"StyleSheetList\",\n    \"StyleSheetPageList\",\n    \"SubmitEvent\",\n    \"SubtleCrypto\",\n    \"Symbol\",\n    \"SyncManager\",\n    \"SyntaxError\",\n    \"TEMPORARY\",\n    \"TEXTPATH_METHODTYPE_ALIGN\",\n    \"TEXTPATH_METHODTYPE_STRETCH\",\n    \"TEXTPATH_METHODTYPE_UNKNOWN\",\n    \"TEXTPATH_SPACINGTYPE_AUTO\",\n    \"TEXTPATH_SPACINGTYPE_EXACT\",\n    \"TEXTPATH_SPACINGTYPE_UNKNOWN\",\n    \"TEXTURE\",\n    \"TEXTURE0\",\n    \"TEXTURE1\",\n    \"TEXTURE10\",\n    \"TEXTURE11\",\n    \"TEXTURE12\",\n    \"TEXTURE13\",\n    \"TEXTURE14\",\n    \"TEXTURE15\",\n    \"TEXTURE16\",\n    \"TEXTURE17\",\n    \"TEXTURE18\",\n    \"TEXTURE19\",\n    \"TEXTURE2\",\n    \"TEXTURE20\",\n    \"TEXTURE21\",\n    \"TEXTURE22\",\n    \"TEXTURE23\",\n    \"TEXTURE24\",\n    \"TEXTURE25\",\n    \"TEXTURE26\",\n    \"TEXTURE27\",\n    \"TEXTURE28\",\n    \"TEXTURE29\",\n    \"TEXTURE3\",\n    \"TEXTURE30\",\n    \"TEXTURE31\",\n    \"TEXTURE4\",\n    \"TEXTURE5\",\n    \"TEXTURE6\",\n    \"TEXTURE7\",\n    \"TEXTURE8\",\n    \"TEXTURE9\",\n    \"TEXTURE_2D\",\n    \"TEXTURE_2D_ARRAY\",\n    \"TEXTURE_3D\",\n    \"TEXTURE_BASE_LEVEL\",\n    \"TEXTURE_BINDING_2D\",\n    \"TEXTURE_BINDING_2D_ARRAY\",\n    \"TEXTURE_BINDING_3D\",\n    \"TEXTURE_BINDING_CUBE_MAP\",\n    \"TEXTURE_COMPARE_FUNC\",\n    \"TEXTURE_COMPARE_MODE\",\n    \"TEXTURE_CUBE_MAP\",\n    \"TEXTURE_CUBE_MAP_NEGATIVE_X\",\n    \"TEXTURE_CUBE_MAP_NEGATIVE_Y\",\n    \"TEXTURE_CUBE_MAP_NEGATIVE_Z\",\n    \"TEXTURE_CUBE_MAP_POSITIVE_X\",\n    \"TEXTURE_CUBE_MAP_POSITIVE_Y\",\n    \"TEXTURE_CUBE_MAP_POSITIVE_Z\",\n    \"TEXTURE_IMMUTABLE_FORMAT\",\n    \"TEXTURE_IMMUTABLE_LEVELS\",\n    \"TEXTURE_MAG_FILTER\",\n    \"TEXTURE_MAX_ANISOTROPY_EXT\",\n    \"TEXTURE_MAX_LEVEL\",\n    \"TEXTURE_MAX_LOD\",\n    \"TEXTURE_MIN_FILTER\",\n    \"TEXTURE_MIN_LOD\",\n    \"TEXTURE_WRAP_R\",\n    \"TEXTURE_WRAP_S\",\n    \"TEXTURE_WRAP_T\",\n    \"TEXT_NODE\",\n    \"THROTTLED\",\n    \"TIMEOUT\",\n    \"TIMEOUT_ERR\",\n    \"TIMEOUT_EXPIRED\",\n    \"TIMEOUT_IGNORED\",\n    \"TOO_LARGE_ERR\",\n    \"TRANSACTION_INACTIVE_ERR\",\n    \"TRANSFORM_FEEDBACK\",\n    \"TRANSFORM_FEEDBACK_ACTIVE\",\n    \"TRANSFORM_FEEDBACK_BINDING\",\n    \"TRANSFORM_FEEDBACK_BUFFER\",\n    \"TRANSFORM_FEEDBACK_BUFFER_BINDING\",\n    \"TRANSFORM_FEEDBACK_BUFFER_MODE\",\n    \"TRANSFORM_FEEDBACK_BUFFER_SIZE\",\n    \"TRANSFORM_FEEDBACK_BUFFER_START\",\n    \"TRANSFORM_FEEDBACK_PAUSED\",\n    \"TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN\",\n    \"TRANSFORM_FEEDBACK_VARYINGS\",\n    \"TRIANGLE\",\n    \"TRIANGLES\",\n    \"TRIANGLE_FAN\",\n    \"TRIANGLE_STRIP\",\n    \"TYPE_BACK_FORWARD\",\n    \"TYPE_ERR\",\n    \"TYPE_MISMATCH_ERR\",\n    \"TYPE_NAVIGATE\",\n    \"TYPE_RELOAD\",\n    \"TYPE_RESERVED\",\n    \"Table\",\n    \"TaskAttributionTiming\",\n    \"Text\",\n    \"TextDecoder\",\n    \"TextDecoderStream\",\n    \"TextEncoder\",\n    \"TextEncoderStream\",\n    \"TextEvent\",\n    \"TextMetrics\",\n    \"TextRange\",\n    \"TextRangeCollection\",\n    \"TextTrack\",\n    \"TextTrackCue\",\n    \"TextTrackCueList\",\n    \"TextTrackList\",\n    \"TimeEvent\",\n    \"TimeRanges\",\n    \"Touch\",\n    \"TouchEvent\",\n    \"TouchList\",\n    \"TrackEvent\",\n    \"TransformStream\",\n    \"TransitionEvent\",\n    \"TreeWalker\",\n    \"TrustedHTML\",\n    \"TrustedScript\",\n    \"TrustedScriptURL\",\n    \"TrustedTypePolicy\",\n    \"TrustedTypePolicyFactory\",\n    \"TypeError\",\n    \"U2F\",\n    \"UIEvent\",\n    \"UNCACHED\",\n    \"UNIFORM_ARRAY_STRIDE\",\n    \"UNIFORM_BLOCK_ACTIVE_UNIFORMS\",\n    \"UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES\",\n    \"UNIFORM_BLOCK_BINDING\",\n    \"UNIFORM_BLOCK_DATA_SIZE\",\n    \"UNIFORM_BLOCK_INDEX\",\n    \"UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER\",\n    \"UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER\",\n    \"UNIFORM_BUFFER\",\n    \"UNIFORM_BUFFER_BINDING\",\n    \"UNIFORM_BUFFER_OFFSET_ALIGNMENT\",\n    \"UNIFORM_BUFFER_SIZE\",\n    \"UNIFORM_BUFFER_START\",\n    \"UNIFORM_IS_ROW_MAJOR\",\n    \"UNIFORM_MATRIX_STRIDE\",\n    \"UNIFORM_OFFSET\",\n    \"UNIFORM_SIZE\",\n    \"UNIFORM_TYPE\",\n    \"UNKNOWN_ERR\",\n    \"UNKNOWN_RULE\",\n    \"UNMASKED_RENDERER_WEBGL\",\n    \"UNMASKED_VENDOR_WEBGL\",\n    \"UNORDERED_NODE_ITERATOR_TYPE\",\n    \"UNORDERED_NODE_SNAPSHOT_TYPE\",\n    \"UNPACK_ALIGNMENT\",\n    \"UNPACK_COLORSPACE_CONVERSION_WEBGL\",\n    \"UNPACK_FLIP_Y_WEBGL\",\n    \"UNPACK_IMAGE_HEIGHT\",\n    \"UNPACK_PREMULTIPLY_ALPHA_WEBGL\",\n    \"UNPACK_ROW_LENGTH\",\n    \"UNPACK_SKIP_IMAGES\",\n    \"UNPACK_SKIP_PIXELS\",\n    \"UNPACK_SKIP_ROWS\",\n    \"UNSCHEDULED_STATE\",\n    \"UNSENT\",\n    \"UNSIGNALED\",\n    \"UNSIGNED_BYTE\",\n    \"UNSIGNED_INT\",\n    \"UNSIGNED_INT_10F_11F_11F_REV\",\n    \"UNSIGNED_INT_24_8\",\n    \"UNSIGNED_INT_2_10_10_10_REV\",\n    \"UNSIGNED_INT_5_9_9_9_REV\",\n    \"UNSIGNED_INT_SAMPLER_2D\",\n    \"UNSIGNED_INT_SAMPLER_2D_ARRAY\",\n    \"UNSIGNED_INT_SAMPLER_3D\",\n    \"UNSIGNED_INT_SAMPLER_CUBE\",\n    \"UNSIGNED_INT_VEC2\",\n    \"UNSIGNED_INT_VEC3\",\n    \"UNSIGNED_INT_VEC4\",\n    \"UNSIGNED_NORMALIZED\",\n    \"UNSIGNED_SHORT\",\n    \"UNSIGNED_SHORT_4_4_4_4\",\n    \"UNSIGNED_SHORT_5_5_5_1\",\n    \"UNSIGNED_SHORT_5_6_5\",\n    \"UNSPECIFIED_EVENT_TYPE_ERR\",\n    \"UPDATE\",\n    \"UPDATEREADY\",\n    \"UPDATE_AVAILABLE\",\n    \"URIError\",\n    \"URL\",\n    \"URLSearchParams\",\n    \"URLUnencoded\",\n    \"URL_MISMATCH_ERR\",\n    \"USB\",\n    \"USBAlternateInterface\",\n    \"USBConfiguration\",\n    \"USBConnectionEvent\",\n    \"USBDevice\",\n    \"USBEndpoint\",\n    \"USBInTransferResult\",\n    \"USBInterface\",\n    \"USBIsochronousInTransferPacket\",\n    \"USBIsochronousInTransferResult\",\n    \"USBIsochronousOutTransferPacket\",\n    \"USBIsochronousOutTransferResult\",\n    \"USBOutTransferResult\",\n    \"UTC\",\n    \"Uint16Array\",\n    \"Uint32Array\",\n    \"Uint8Array\",\n    \"Uint8ClampedArray\",\n    \"UserActivation\",\n    \"UserMessageHandler\",\n    \"UserMessageHandlersNamespace\",\n    \"UserProximityEvent\",\n    \"VALIDATE_STATUS\",\n    \"VALIDATION_ERR\",\n    \"VARIABLES_RULE\",\n    \"VBArray\",\n    \"VENDOR\",\n    \"VERSION\",\n    \"VERSION_CHANGE\",\n    \"VERSION_ERR\",\n    \"VERTEX_ARRAY_BINDING\",\n    \"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING\",\n    \"VERTEX_ATTRIB_ARRAY_DIVISOR\",\n    \"VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE\",\n    \"VERTEX_ATTRIB_ARRAY_ENABLED\",\n    \"VERTEX_ATTRIB_ARRAY_INTEGER\",\n    \"VERTEX_ATTRIB_ARRAY_NORMALIZED\",\n    \"VERTEX_ATTRIB_ARRAY_POINTER\",\n    \"VERTEX_ATTRIB_ARRAY_SIZE\",\n    \"VERTEX_ATTRIB_ARRAY_STRIDE\",\n    \"VERTEX_ATTRIB_ARRAY_TYPE\",\n    \"VERTEX_SHADER\",\n    \"VERTICAL\",\n    \"VERTICAL_AXIS\",\n    \"VER_ERR\",\n    \"VIEWPORT\",\n    \"VIEWPORT_RULE\",\n    \"VRDisplay\",\n    \"VRDisplayCapabilities\",\n    \"VRDisplayEvent\",\n    \"VREyeParameters\",\n    \"VRFieldOfView\",\n    \"VRFrameData\",\n    \"VRPose\",\n    \"VRStageParameters\",\n    \"VTTCue\",\n    \"VTTRegion\",\n    \"ValidityState\",\n    \"VideoPlaybackQuality\",\n    \"VideoStreamTrack\",\n    \"VideoTrack\",\n    \"VideoTrackList\",\n    \"VisualViewport\",\n    \"WAIT_FAILED\",\n    \"WEBGL_compressed_texture_s3tc\",\n    \"WEBGL_debug_renderer_info\",\n    \"WEBKIT_FILTER_RULE\",\n    \"WEBKIT_FORCE_AT_FORCE_MOUSE_DOWN\",\n    \"WEBKIT_FORCE_AT_MOUSE_DOWN\",\n    \"WEBKIT_KEYFRAMES_RULE\",\n    \"WEBKIT_KEYFRAME_RULE\",\n    \"WEBKIT_REGION_RULE\",\n    \"WIN\",\n    \"WRONG_DOCUMENT_ERR\",\n    \"WakeLock\",\n    \"WakeLockSentinel\",\n    \"WaveShaperNode\",\n    \"WeakMap\",\n    \"WeakRef\",\n    \"WeakSet\",\n    \"WebAssembly\",\n    \"WebGL2RenderingContext\",\n    \"WebGLActiveInfo\",\n    \"WebGLBuffer\",\n    \"WebGLContextEvent\",\n    \"WebGLFramebuffer\",\n    \"WebGLObject\",\n    \"WebGLProgram\",\n    \"WebGLQuery\",\n    \"WebGLRenderbuffer\",\n    \"WebGLRenderingContext\",\n    \"WebGLSampler\",\n    \"WebGLShader\",\n    \"WebGLShaderPrecisionFormat\",\n    \"WebGLSync\",\n    \"WebGLTexture\",\n    \"WebGLTransformFeedback\",\n    \"WebGLUniformLocation\",\n    \"WebGLVertexArray\",\n    \"WebGLVertexArrayObject\",\n    \"WebKit built-in PDF\",\n    \"WebKitAnimationEvent\",\n    \"WebKitBlobBuilder\",\n    \"WebKitCSSFilterRule\",\n    \"WebKitCSSFilterValue\",\n    \"WebKitCSSKeyframeRule\",\n    \"WebKitCSSKeyframesRule\",\n    \"WebKitCSSMatrix\",\n    \"WebKitCSSRegionRule\",\n    \"WebKitCSSTransformValue\",\n    \"WebKitDataCue\",\n    \"WebKitGamepad\",\n    \"WebKitMediaKeyError\",\n    \"WebKitMediaKeyMessageEvent\",\n    \"WebKitMediaKeyNeededEvent\",\n    \"WebKitMediaKeySession\",\n    \"WebKitMediaKeys\",\n    \"WebKitMediaSource\",\n    \"WebKitMutationObserver\",\n    \"WebKitNamespace\",\n    \"WebKitPlaybackTargetAvailabilityEvent\",\n    \"WebKitPoint\",\n    \"WebKitShadowRoot\",\n    \"WebKitSourceBuffer\",\n    \"WebKitSourceBufferList\",\n    \"WebKitTransitionEvent\",\n    \"WebSocket\",\n    \"WebkitAlignContent\",\n    \"WebkitAlignItems\",\n    \"WebkitAlignSelf\",\n    \"WebkitAnimation\",\n    \"WebkitAnimationDelay\",\n    \"WebkitAnimationDirection\",\n    \"WebkitAnimationDuration\",\n    \"WebkitAnimationFillMode\",\n    \"WebkitAnimationIterationCount\",\n    \"WebkitAnimationName\",\n    \"WebkitAnimationPlayState\",\n    \"WebkitAnimationTimingFunction\",\n    \"WebkitAppearance\",\n    \"WebkitBackfaceVisibility\",\n    \"WebkitBackgroundClip\",\n    \"WebkitBackgroundOrigin\",\n    \"WebkitBackgroundSize\",\n    \"WebkitBorderBottomLeftRadius\",\n    \"WebkitBorderBottomRightRadius\",\n    \"WebkitBorderImage\",\n    \"WebkitBorderRadius\",\n    \"WebkitBorderTopLeftRadius\",\n    \"WebkitBorderTopRightRadius\",\n    \"WebkitBoxAlign\",\n    \"WebkitBoxDirection\",\n    \"WebkitBoxFlex\",\n    \"WebkitBoxOrdinalGroup\",\n    \"WebkitBoxOrient\",\n    \"WebkitBoxPack\",\n    \"WebkitBoxShadow\",\n    \"WebkitBoxSizing\",\n    \"WebkitFilter\",\n    \"WebkitFlex\",\n    \"WebkitFlexBasis\",\n    \"WebkitFlexDirection\",\n    \"WebkitFlexFlow\",\n    \"WebkitFlexGrow\",\n    \"WebkitFlexShrink\",\n    \"WebkitFlexWrap\",\n    \"WebkitJustifyContent\",\n    \"WebkitLineClamp\",\n    \"WebkitMask\",\n    \"WebkitMaskClip\",\n    \"WebkitMaskComposite\",\n    \"WebkitMaskImage\",\n    \"WebkitMaskOrigin\",\n    \"WebkitMaskPosition\",\n    \"WebkitMaskPositionX\",\n    \"WebkitMaskPositionY\",\n    \"WebkitMaskRepeat\",\n    \"WebkitMaskSize\",\n    \"WebkitOrder\",\n    \"WebkitPerspective\",\n    \"WebkitPerspectiveOrigin\",\n    \"WebkitTextFillColor\",\n    \"WebkitTextSizeAdjust\",\n    \"WebkitTextStroke\",\n    \"WebkitTextStrokeColor\",\n    \"WebkitTextStrokeWidth\",\n    \"WebkitTransform\",\n    \"WebkitTransformOrigin\",\n    \"WebkitTransformStyle\",\n    \"WebkitTransition\",\n    \"WebkitTransitionDelay\",\n    \"WebkitTransitionDuration\",\n    \"WebkitTransitionProperty\",\n    \"WebkitTransitionTimingFunction\",\n    \"WebkitUserSelect\",\n    \"WheelEvent\",\n    \"Window\",\n    \"Windows Media Player Plug-in Dynamic Link Library\",\n    \"Windows Presentation Foundation\",\n    \"Worker\",\n    \"Worklet\",\n    \"WritableStream\",\n    \"WritableStreamDefaultWriter\",\n    \"X86_32\",\n    \"X86_64\",\n    \"XMLDocument\",\n    \"XMLHttpRequest\",\n    \"XMLHttpRequestEventTarget\",\n    \"XMLHttpRequestException\",\n    \"XMLHttpRequestProgressEvent\",\n    \"XMLHttpRequestUpload\",\n    \"XMLSerializer\",\n    \"XMLStylesheetProcessingInstruction\",\n    \"XPathEvaluator\",\n    \"XPathException\",\n    \"XPathExpression\",\n    \"XPathNSResolver\",\n    \"XPathResult\",\n    \"XR\",\n    \"XRBoundedReferenceSpace\",\n    \"XRDOMOverlayState\",\n    \"XRFrame\",\n    \"XRHitTestResult\",\n    \"XRHitTestSource\",\n    \"XRInputSource\",\n    \"XRInputSourceArray\",\n    \"XRInputSourceEvent\",\n    \"XRInputSourcesChangeEvent\",\n    \"XRLayer\",\n    \"XRPose\",\n    \"XRRay\",\n    \"XRReferenceSpace\",\n    \"XRReferenceSpaceEvent\",\n    \"XRRenderState\",\n    \"XRRigidTransform\",\n    \"XRSession\",\n    \"XRSessionEvent\",\n    \"XRSpace\",\n    \"XRSystem\",\n    \"XRTransientInputHitTestResult\",\n    \"XRTransientInputHitTestSource\",\n    \"XRView\",\n    \"XRViewerPose\",\n    \"XRViewport\",\n    \"XRWebGLLayer\",\n    \"XSLTProcessor\",\n    \"ZERO\",\n    \"_XD0M_\",\n    \"_YD0M_\",\n    \"__defineGetter__\",\n    \"__defineSetter__\",\n    \"__lookupGetter__\",\n    \"__lookupSetter__\",\n    \"__opera\",\n    \"__proto__\",\n    \"__relevantExtensionKeys\",\n    \"_browserjsran\",\n    \"a\",\n    \"aLink\",\n    \"abbr\",\n    \"abort\",\n    \"aborted\",\n    \"abs\",\n    \"absolute\",\n    \"acceleration\",\n    \"accelerationIncludingGravity\",\n    \"accelerator\",\n    \"accept\",\n    \"acceptCharset\",\n    \"acceptNode\",\n    \"accessKey\",\n    \"accessKeyLabel\",\n    \"accuracy\",\n    \"acos\",\n    \"acosh\",\n    \"action\",\n    \"actionURL\",\n    \"actions\",\n    \"activated\",\n    \"active\",\n    \"activeCues\",\n    \"activeElement\",\n    \"activeSourceBuffers\",\n    \"activeSourceCount\",\n    \"activeTexture\",\n    \"activeVRDisplays\",\n    \"actualBoundingBoxAscent\",\n    \"actualBoundingBoxDescent\",\n    \"actualBoundingBoxLeft\",\n    \"actualBoundingBoxRight\",\n    \"add\",\n    \"addAll\",\n    \"addBehavior\",\n    \"addCandidate\",\n    \"addColorStop\",\n    \"addCue\",\n    \"addElement\",\n    \"addEventListener\",\n    \"addFilter\",\n    \"addFromString\",\n    \"addFromUri\",\n    \"addIceCandidate\",\n    \"addImport\",\n    \"addListener\",\n    \"addModule\",\n    \"addNamed\",\n    \"addPageRule\",\n    \"addPath\",\n    \"addPointer\",\n    \"addRange\",\n    \"addRegion\",\n    \"addRule\",\n    \"addRules\",\n    \"addSearchEngine\",\n    \"addSourceBuffer\",\n    \"addStream\",\n    \"addTextTrack\",\n    \"addTrack\",\n    \"addTransceiver\",\n    \"addWakeLockListener\",\n    \"added\",\n    \"addedNodes\",\n    \"additionalName\",\n    \"additiveSymbols\",\n    \"addons\",\n    \"address\",\n    \"addressLine\",\n    \"adoptNode\",\n    \"adoptText\",\n    \"adoptedCallback\",\n    \"adoptedStyleSheets\",\n    \"adr\",\n    \"advance\",\n    \"after\",\n    \"album\",\n    \"alert\",\n    \"algorithm\",\n    \"align\",\n    \"align-content\",\n    \"align-items\",\n    \"align-self\",\n    \"alignContent\",\n    \"alignItems\",\n    \"alignSelf\",\n    \"alignmentBaseline\",\n    \"alinkColor\",\n    \"all\",\n    \"allSettled\",\n    \"allow\",\n    \"allowFullscreen\",\n    \"allowPaymentRequest\",\n    \"allowTransparency\",\n    \"allowedDirections\",\n    \"allowedFeatures\",\n    \"allowsFeature\",\n    \"alpha\",\n    \"alphabeticBaseline\",\n    \"alt\",\n    \"altGraphKey\",\n    \"altHtml\",\n    \"altKey\",\n    \"altLeft\",\n    \"alternate\",\n    \"alternateSetting\",\n    \"alternates\",\n    \"altitude\",\n    \"altitudeAccuracy\",\n    \"amplitude\",\n    \"ancestorOrigins\",\n    \"anchor\",\n    \"anchorNode\",\n    \"anchorOffset\",\n    \"anchors\",\n    \"and\",\n    \"angle\",\n    \"angularAcceleration\",\n    \"angularVelocity\",\n    \"animVal\",\n    \"animate\",\n    \"animatedInstanceRoot\",\n    \"animatedNormalizedPathSegList\",\n    \"animatedPathSegList\",\n    \"animatedPoints\",\n    \"animation\",\n    \"animation-delay\",\n    \"animation-direction\",\n    \"animation-duration\",\n    \"animation-fill-mode\",\n    \"animation-iteration-count\",\n    \"animation-name\",\n    \"animation-play-state\",\n    \"animation-timing-function\",\n    \"animationDelay\",\n    \"animationDirection\",\n    \"animationDuration\",\n    \"animationFillMode\",\n    \"animationIterationCount\",\n    \"animationName\",\n    \"animationPlayState\",\n    \"animationStartTime\",\n    \"animationTimingFunction\",\n    \"animationsPaused\",\n    \"anniversary\",\n    \"antialias\",\n    \"any\",\n    \"app\",\n    \"appCodeName\",\n    \"appMinorVersion\",\n    \"appName\",\n    \"appNotifications\",\n    \"appVersion\",\n    \"appearance\",\n    \"append\",\n    \"appendBuffer\",\n    \"appendChild\",\n    \"appendData\",\n    \"appendItem\",\n    \"appendMedium\",\n    \"appendNamed\",\n    \"appendRule\",\n    \"appendStream\",\n    \"appendWindowEnd\",\n    \"appendWindowStart\",\n    \"appleTrailingWord\",\n    \"applets\",\n    \"application/apple-default-browser\",\n    \"application/asx\",\n    \"application/java-deployment-toolkit\",\n    \"application/pdf\",\n    \"application/postscript\",\n    \"application/x-drm\",\n    \"application/x-drm-v2\",\n    \"application/x-google-chrome-pdf\",\n    \"application/x-java-applet\",\n    \"application/x-java-applet;deploy=10.25.2\",\n    \"application/x-java-applet;javafx=2.2.25\",\n    \"application/x-java-applet;jpi-version=1.7.0_25\",\n    \"application/x-java-applet;version=1.1\",\n    \"application/x-java-applet;version=1.1.1\",\n    \"application/x-java-applet;version=1.1.2\",\n    \"application/x-java-applet;version=1.1.3\",\n    \"application/x-java-applet;version=1.2\",\n    \"application/x-java-applet;version=1.2.1\",\n    \"application/x-java-applet;version=1.2.2\",\n    \"application/x-java-applet;version=1.3\",\n    \"application/x-java-applet;version=1.3.1\",\n    \"application/x-java-applet;version=1.4\",\n    \"application/x-java-applet;version=1.4.1\",\n    \"application/x-java-applet;version=1.4.2\",\n    \"application/x-java-applet;version=1.5\",\n    \"application/x-java-applet;version=1.6\",\n    \"application/x-java-applet;version=1.7\",\n    \"application/x-java-bean\",\n    \"application/x-java-bean;jpi-version=1.7.0_25\",\n    \"application/x-java-bean;version=1.1\",\n    \"application/x-java-bean;version=1.1.1\",\n    \"application/x-java-bean;version=1.1.2\",\n    \"application/x-java-bean;version=1.1.3\",\n    \"application/x-java-bean;version=1.2\",\n    \"application/x-java-bean;version=1.2.1\",\n    \"application/x-java-bean;version=1.2.2\",\n    \"application/x-java-bean;version=1.3\",\n    \"application/x-java-bean;version=1.3.1\",\n    \"application/x-java-bean;version=1.4\",\n    \"application/x-java-bean;version=1.4.1\",\n    \"application/x-java-bean;version=1.4.2\",\n    \"application/x-java-bean;version=1.5\",\n    \"application/x-java-bean;version=1.6\",\n    \"application/x-java-bean;version=1.7\",\n    \"application/x-java-vm\",\n    \"application/x-java-vm-npruntime\",\n    \"application/x-mplayer2\",\n    \"application/x-ms-xbap\",\n    \"application/x-nacl\",\n    \"application/x-pnacl\",\n    \"application/xaml+xml\",\n    \"applicationCache\",\n    \"applicationServerKey\",\n    \"apply\",\n    \"applyConstraints\",\n    \"applyElement\",\n    \"arc\",\n    \"arcTo\",\n    \"archive\",\n    \"areas\",\n    \"arguments\",\n    \"aria-activedescendant\",\n    \"aria-busy\",\n    \"aria-checked\",\n    \"aria-controls\",\n    \"aria-describedby\",\n    \"aria-disabled\",\n    \"aria-expanded\",\n    \"aria-flowto\",\n    \"aria-haspopup\",\n    \"aria-hidden\",\n    \"aria-invalid\",\n    \"aria-labelledby\",\n    \"aria-level\",\n    \"aria-live\",\n    \"aria-multiselectable\",\n    \"aria-owns\",\n    \"aria-posinset\",\n    \"aria-pressed\",\n    \"aria-readonly\",\n    \"aria-relevant\",\n    \"aria-required\",\n    \"aria-secret\",\n    \"aria-selected\",\n    \"aria-setsize\",\n    \"aria-valuemax\",\n    \"aria-valuemin\",\n    \"aria-valuenow\",\n    \"ariaAtomic\",\n    \"ariaAutoComplete\",\n    \"ariaBusy\",\n    \"ariaChecked\",\n    \"ariaColCount\",\n    \"ariaColIndex\",\n    \"ariaColSpan\",\n    \"ariaCurrent\",\n    \"ariaDescription\",\n    \"ariaDisabled\",\n    \"ariaExpanded\",\n    \"ariaHasPopup\",\n    \"ariaHidden\",\n    \"ariaKeyShortcuts\",\n    \"ariaLabel\",\n    \"ariaLevel\",\n    \"ariaLive\",\n    \"ariaModal\",\n    \"ariaMultiLine\",\n    \"ariaMultiSelectable\",\n    \"ariaOrientation\",\n    \"ariaPlaceholder\",\n    \"ariaPosInSet\",\n    \"ariaPressed\",\n    \"ariaReadOnly\",\n    \"ariaRelevant\",\n    \"ariaRequired\",\n    \"ariaRoleDescription\",\n    \"ariaRowCount\",\n    \"ariaRowIndex\",\n    \"ariaRowSpan\",\n    \"ariaSelected\",\n    \"ariaSetSize\",\n    \"ariaSort\",\n    \"ariaValueMax\",\n    \"ariaValueMin\",\n    \"ariaValueNow\",\n    \"ariaValueText\",\n    \"arrayBuffer\",\n    \"artist\",\n    \"artwork\",\n    \"as\",\n    \"asIntN\",\n    \"asUintN\",\n    \"asin\",\n    \"asinh\",\n    \"assert\",\n    \"assign\",\n    \"assignedElements\",\n    \"assignedNodes\",\n    \"assignedSlot\",\n    \"async\",\n    \"asyncIterator\",\n    \"atEnd\",\n    \"atan\",\n    \"atan2\",\n    \"atanh\",\n    \"atob\",\n    \"atomic\",\n    \"attachEvent\",\n    \"attachInternals\",\n    \"attachShader\",\n    \"attachShadow\",\n    \"attachments\",\n    \"attack\",\n    \"attestationObject\",\n    \"attrChange\",\n    \"attrName\",\n    \"attributeChangedCallback\",\n    \"attributeFilter\",\n    \"attributeName\",\n    \"attributeNamespace\",\n    \"attributeOldValue\",\n    \"attributeStyleMap\",\n    \"attributes\",\n    \"attribution\",\n    \"audio/x-ms-wax\",\n    \"audio/x-ms-wma\",\n    \"audioBitsPerSecond\",\n    \"audioTracks\",\n    \"audioWorklet\",\n    \"authenticatedSignedWrites\",\n    \"authenticatorData\",\n    \"autoIncrement\",\n    \"autobuffer\",\n    \"autocapitalize\",\n    \"autocomplete\",\n    \"autocorrect\",\n    \"autofocus\",\n    \"automationRate\",\n    \"autoplay\",\n    \"availHeight\",\n    \"availLeft\",\n    \"availTop\",\n    \"availWidth\",\n    \"availability\",\n    \"available\",\n    \"aversion\",\n    \"ax\",\n    \"axes\",\n    \"axis\",\n    \"ay\",\n    \"azimuth\",\n    \"b\",\n    \"back\",\n    \"backdropFilter\",\n    \"backface-visibility\",\n    \"backfaceVisibility\",\n    \"background\",\n    \"background-attachment\",\n    \"background-blend-mode\",\n    \"background-clip\",\n    \"background-color\",\n    \"background-image\",\n    \"background-origin\",\n    \"background-position\",\n    \"background-position-x\",\n    \"background-position-y\",\n    \"background-repeat\",\n    \"background-size\",\n    \"backgroundAttachment\",\n    \"backgroundBlendMode\",\n    \"backgroundClip\",\n    \"backgroundColor\",\n    \"backgroundFetch\",\n    \"backgroundImage\",\n    \"backgroundOrigin\",\n    \"backgroundPosition\",\n    \"backgroundPositionX\",\n    \"backgroundPositionY\",\n    \"backgroundRepeat\",\n    \"backgroundRepeatX\",\n    \"backgroundRepeatY\",\n    \"backgroundSize\",\n    \"badInput\",\n    \"badge\",\n    \"balance\",\n    \"baseFrequencyX\",\n    \"baseFrequencyY\",\n    \"baseLatency\",\n    \"baseLayer\",\n    \"baseName\",\n    \"baseNode\",\n    \"baseOffset\",\n    \"baseURI\",\n    \"baseVal\",\n    \"baselineShift\",\n    \"battery\",\n    \"bday\",\n    \"before\",\n    \"beginElement\",\n    \"beginElementAt\",\n    \"beginPath\",\n    \"beginQuery\",\n    \"beginTransformFeedback\",\n    \"behavior\",\n    \"behaviorCookie\",\n    \"behaviorPart\",\n    \"behaviorUrns\",\n    \"beta\",\n    \"bezierCurveTo\",\n    \"bgColor\",\n    \"bgProperties\",\n    \"bias\",\n    \"big\",\n    \"binaryType\",\n    \"bind\",\n    \"bindAttribLocation\",\n    \"bindBuffer\",\n    \"bindBufferBase\",\n    \"bindBufferRange\",\n    \"bindFramebuffer\",\n    \"bindRenderbuffer\",\n    \"bindSampler\",\n    \"bindTexture\",\n    \"bindTransformFeedback\",\n    \"bindVertexArray\",\n    \"blendColor\",\n    \"blendEquation\",\n    \"blendEquationSeparate\",\n    \"blendFunc\",\n    \"blendFuncSeparate\",\n    \"blink\",\n    \"blitFramebuffer\",\n    \"blob\",\n    \"block-size\",\n    \"blockDirection\",\n    \"blockSize\",\n    \"blockedURI\",\n    \"blue\",\n    \"bluetooth\",\n    \"blur\",\n    \"body\",\n    \"bodyUsed\",\n    \"bold\",\n    \"bookmarks\",\n    \"booleanValue\",\n    \"border\",\n    \"border-block\",\n    \"border-block-color\",\n    \"border-block-end\",\n    \"border-block-end-color\",\n    \"border-block-end-style\",\n    \"border-block-end-width\",\n    \"border-block-start\",\n    \"border-block-start-color\",\n    \"border-block-start-style\",\n    \"border-block-start-width\",\n    \"border-block-style\",\n    \"border-block-width\",\n    \"border-bottom\",\n    \"border-bottom-color\",\n    \"border-bottom-left-radius\",\n    \"border-bottom-right-radius\",\n    \"border-bottom-style\",\n    \"border-bottom-width\",\n    \"border-collapse\",\n    \"border-color\",\n    \"border-end-end-radius\",\n    \"border-end-start-radius\",\n    \"border-image\",\n    \"border-image-outset\",\n    \"border-image-repeat\",\n    \"border-image-slice\",\n    \"border-image-source\",\n    \"border-image-width\",\n    \"border-inline\",\n    \"border-inline-color\",\n    \"border-inline-end\",\n    \"border-inline-end-color\",\n    \"border-inline-end-style\",\n    \"border-inline-end-width\",\n    \"border-inline-start\",\n    \"border-inline-start-color\",\n    \"border-inline-start-style\",\n    \"border-inline-start-width\",\n    \"border-inline-style\",\n    \"border-inline-width\",\n    \"border-left\",\n    \"border-left-color\",\n    \"border-left-style\",\n    \"border-left-width\",\n    \"border-radius\",\n    \"border-right\",\n    \"border-right-color\",\n    \"border-right-style\",\n    \"border-right-width\",\n    \"border-spacing\",\n    \"border-start-end-radius\",\n    \"border-start-start-radius\",\n    \"border-style\",\n    \"border-top\",\n    \"border-top-color\",\n    \"border-top-left-radius\",\n    \"border-top-right-radius\",\n    \"border-top-style\",\n    \"border-top-width\",\n    \"border-width\",\n    \"borderBlock\",\n    \"borderBlockColor\",\n    \"borderBlockEnd\",\n    \"borderBlockEndColor\",\n    \"borderBlockEndStyle\",\n    \"borderBlockEndWidth\",\n    \"borderBlockStart\",\n    \"borderBlockStartColor\",\n    \"borderBlockStartStyle\",\n    \"borderBlockStartWidth\",\n    \"borderBlockStyle\",\n    \"borderBlockWidth\",\n    \"borderBottom\",\n    \"borderBottomColor\",\n    \"borderBottomLeftRadius\",\n    \"borderBottomRightRadius\",\n    \"borderBottomStyle\",\n    \"borderBottomWidth\",\n    \"borderBoxSize\",\n    \"borderCollapse\",\n    \"borderColor\",\n    \"borderColorDark\",\n    \"borderColorLight\",\n    \"borderEndEndRadius\",\n    \"borderEndStartRadius\",\n    \"borderImage\",\n    \"borderImageOutset\",\n    \"borderImageRepeat\",\n    \"borderImageSlice\",\n    \"borderImageSource\",\n    \"borderImageWidth\",\n    \"borderInline\",\n    \"borderInlineColor\",\n    \"borderInlineEnd\",\n    \"borderInlineEndColor\",\n    \"borderInlineEndStyle\",\n    \"borderInlineEndWidth\",\n    \"borderInlineStart\",\n    \"borderInlineStartColor\",\n    \"borderInlineStartStyle\",\n    \"borderInlineStartWidth\",\n    \"borderInlineStyle\",\n    \"borderInlineWidth\",\n    \"borderLeft\",\n    \"borderLeftColor\",\n    \"borderLeftStyle\",\n    \"borderLeftWidth\",\n    \"borderRadius\",\n    \"borderRight\",\n    \"borderRightColor\",\n    \"borderRightStyle\",\n    \"borderRightWidth\",\n    \"borderSpacing\",\n    \"borderStartEndRadius\",\n    \"borderStartStartRadius\",\n    \"borderStyle\",\n    \"borderTop\",\n    \"borderTopColor\",\n    \"borderTopLeftRadius\",\n    \"borderTopRightRadius\",\n    \"borderTopStyle\",\n    \"borderTopWidth\",\n    \"borderWidth\",\n    \"bottom\",\n    \"bottomMargin\",\n    \"bound\",\n    \"boundElements\",\n    \"boundingClientRect\",\n    \"boundingHeight\",\n    \"boundingLeft\",\n    \"boundingTop\",\n    \"boundingWidth\",\n    \"bounds\",\n    \"boundsGeometry\",\n    \"box-decoration-break\",\n    \"box-shadow\",\n    \"box-sizing\",\n    \"boxDecorationBreak\",\n    \"boxShadow\",\n    \"boxSizing\",\n    \"break-after\",\n    \"break-before\",\n    \"break-inside\",\n    \"breakAfter\",\n    \"breakBefore\",\n    \"breakInside\",\n    \"breakType\",\n    \"broadcast\",\n    \"browserLanguage\",\n    \"btoa\",\n    \"bubbles\",\n    \"buffer\",\n    \"bufferData\",\n    \"bufferDepth\",\n    \"bufferSize\",\n    \"bufferSubData\",\n    \"buffered\",\n    \"bufferedAmount\",\n    \"bufferedAmountLowThreshold\",\n    \"bufferedRendering\",\n    \"buildID\",\n    \"buildNumber\",\n    \"button\",\n    \"buttonID\",\n    \"buttons\",\n    \"byteLength\",\n    \"byteOffset\",\n    \"bytesWritten\",\n    \"c\",\n    \"cache\",\n    \"caches\",\n    \"calendar\",\n    \"call\",\n    \"caller\",\n    \"canBeFormatted\",\n    \"canBeMounted\",\n    \"canBeShared\",\n    \"canHaveChildren\",\n    \"canHaveHTML\",\n    \"canInsertDTMF\",\n    \"canMakePayment\",\n    \"canPlayType\",\n    \"canPresent\",\n    \"canTrickleIceCandidates\",\n    \"cancel\",\n    \"cancelAndHoldAtTime\",\n    \"cancelAnimationFrame\",\n    \"cancelBubble\",\n    \"cancelIdleCallback\",\n    \"cancelScheduledValues\",\n    \"cancelVideoFrameCallback\",\n    \"cancelWatchAvailability\",\n    \"cancelable\",\n    \"candidate\",\n    \"canonicalUUID\",\n    \"canvas\",\n    \"capabilities\",\n    \"caption\",\n    \"caption-side\",\n    \"captionSide\",\n    \"capture\",\n    \"captureEvents\",\n    \"captureStackTrace\",\n    \"captureStream\",\n    \"caret-color\",\n    \"caretBidiLevel\",\n    \"caretColor\",\n    \"caretPositionFromPoint\",\n    \"caretRangeFromPoint\",\n    \"caseFirst\",\n    \"cast\",\n    \"catch\",\n    \"category\",\n    \"cbrt\",\n    \"cd\",\n    \"ceil\",\n    \"cellIndex\",\n    \"cellPadding\",\n    \"cellSpacing\",\n    \"cells\",\n    \"ch\",\n    \"chOff\",\n    \"chain\",\n    \"challenge\",\n    \"changeType\",\n    \"changeVersion\",\n    \"changedTouches\",\n    \"channel\",\n    \"channelCount\",\n    \"channelCountMode\",\n    \"channelInterpretation\",\n    \"char\",\n    \"charAt\",\n    \"charCode\",\n    \"charCodeAt\",\n    \"charIndex\",\n    \"charLength\",\n    \"characterData\",\n    \"characterDataOldValue\",\n    \"characterSet\",\n    \"characteristic\",\n    \"charging\",\n    \"chargingTime\",\n    \"charset\",\n    \"check\",\n    \"checkEnclosure\",\n    \"checkFramebufferStatus\",\n    \"checkInstalled\",\n    \"checkIntersection\",\n    \"checkValidity\",\n    \"checked\",\n    \"childElementCount\",\n    \"childList\",\n    \"childNodes\",\n    \"children\",\n    \"chrome\",\n    \"ciphertext\",\n    \"cite\",\n    \"city\",\n    \"claimInterface\",\n    \"claimed\",\n    \"classList\",\n    \"className\",\n    \"classid\",\n    \"clear\",\n    \"clearAppBadge\",\n    \"clearAttributes\",\n    \"clearBufferfi\",\n    \"clearBufferfv\",\n    \"clearBufferiv\",\n    \"clearBufferuiv\",\n    \"clearColor\",\n    \"clearData\",\n    \"clearDepth\",\n    \"clearHalt\",\n    \"clearImmediate\",\n    \"clearInterval\",\n    \"clearLiveSeekableRange\",\n    \"clearMarks\",\n    \"clearMeasures\",\n    \"clearParameters\",\n    \"clearRect\",\n    \"clearResourceTimings\",\n    \"clearShadow\",\n    \"clearStencil\",\n    \"clearTimeout\",\n    \"clearWatch\",\n    \"click\",\n    \"clickCount\",\n    \"clientDataJSON\",\n    \"clientHeight\",\n    \"clientInformation\",\n    \"clientLeft\",\n    \"clientRect\",\n    \"clientRects\",\n    \"clientTop\",\n    \"clientWaitSync\",\n    \"clientWidth\",\n    \"clientX\",\n    \"clientY\",\n    \"clip\",\n    \"clip-path\",\n    \"clip-rule\",\n    \"clipBottom\",\n    \"clipLeft\",\n    \"clipPath\",\n    \"clipPathUnits\",\n    \"clipRight\",\n    \"clipRule\",\n    \"clipTop\",\n    \"clipboard\",\n    \"clipboardData\",\n    \"clone\",\n    \"cloneContents\",\n    \"cloneNode\",\n    \"cloneRange\",\n    \"close\",\n    \"closePath\",\n    \"closed\",\n    \"closest\",\n    \"clz\",\n    \"clz32\",\n    \"cm\",\n    \"cmp\",\n    \"code\",\n    \"codeBase\",\n    \"codePointAt\",\n    \"codeType\",\n    \"colSpan\",\n    \"collapse\",\n    \"collapseToEnd\",\n    \"collapseToStart\",\n    \"collapsed\",\n    \"collation\",\n    \"collect\",\n    \"colno\",\n    \"color\",\n    \"color-adjust\",\n    \"color-interpolation\",\n    \"color-interpolation-filters\",\n    \"colorAdjust\",\n    \"colorDepth\",\n    \"colorInterpolation\",\n    \"colorInterpolationFilters\",\n    \"colorMask\",\n    \"colorProfile\",\n    \"colorRendering\",\n    \"colorScheme\",\n    \"colorType\",\n    \"cols\",\n    \"column\",\n    \"column-count\",\n    \"column-fill\",\n    \"column-gap\",\n    \"column-rule\",\n    \"column-rule-color\",\n    \"column-rule-style\",\n    \"column-rule-width\",\n    \"column-span\",\n    \"column-width\",\n    \"columnCount\",\n    \"columnFill\",\n    \"columnGap\",\n    \"columnNumber\",\n    \"columnRule\",\n    \"columnRuleColor\",\n    \"columnRuleStyle\",\n    \"columnRuleWidth\",\n    \"columnSpan\",\n    \"columnWidth\",\n    \"columns\",\n    \"command\",\n    \"commit\",\n    \"commitLoadTime\",\n    \"commitPreferences\",\n    \"commitStyles\",\n    \"commonAncestorContainer\",\n    \"compact\",\n    \"compare\",\n    \"compareBoundaryPoints\",\n    \"compareDocumentPosition\",\n    \"compareEndPoints\",\n    \"compareExchange\",\n    \"compareNode\",\n    \"comparePoint\",\n    \"compatMode\",\n    \"compatible\",\n    \"compile\",\n    \"compileShader\",\n    \"compileStreaming\",\n    \"complete\",\n    \"component\",\n    \"componentFromPoint\",\n    \"composed\",\n    \"composedPath\",\n    \"composite\",\n    \"compositionEndOffset\",\n    \"compositionStartOffset\",\n    \"compressedTexImage2D\",\n    \"compressedTexImage3D\",\n    \"compressedTexSubImage2D\",\n    \"compressedTexSubImage3D\",\n    \"computedStyleMap\",\n    \"concat\",\n    \"conditionText\",\n    \"coneInnerAngle\",\n    \"coneOuterAngle\",\n    \"coneOuterGain\",\n    \"configuration\",\n    \"configurationName\",\n    \"configurationValue\",\n    \"configurations\",\n    \"confirm\",\n    \"confirmComposition\",\n    \"confirmSiteSpecificTrackingException\",\n    \"confirmWebWideTrackingException\",\n    \"connect\",\n    \"connectEnd\",\n    \"connectStart\",\n    \"connected\",\n    \"connectedCallback\",\n    \"connection\",\n    \"connectionInfo\",\n    \"connectionList\",\n    \"connectionSpeed\",\n    \"connectionState\",\n    \"connections\",\n    \"console\",\n    \"consoleHistory\",\n    \"consolidate\",\n    \"constraint\",\n    \"constrictionActive\",\n    \"construct\",\n    \"constructor\",\n    \"contactID\",\n    \"contain\",\n    \"containIntrinsicSize\",\n    \"containerId\",\n    \"containerName\",\n    \"containerSrc\",\n    \"containerType\",\n    \"contains\",\n    \"containsNode\",\n    \"content\",\n    \"contentBoxSize\",\n    \"contentDocument\",\n    \"contentEditable\",\n    \"contentHint\",\n    \"contentOverflow\",\n    \"contentRect\",\n    \"contentScriptType\",\n    \"contentStyleType\",\n    \"contentType\",\n    \"contentWindow\",\n    \"context\",\n    \"contextMenu\",\n    \"contextmenu\",\n    \"continue\",\n    \"continuePrimaryKey\",\n    \"continuous\",\n    \"control\",\n    \"controlTransferIn\",\n    \"controlTransferOut\",\n    \"controller\",\n    \"controls\",\n    \"controlsList\",\n    \"convertToBlob\",\n    \"convertToSpecifiedUnits\",\n    \"cookie\",\n    \"cookieEnabled\",\n    \"coords\",\n    \"copyBufferSubData\",\n    \"copyFromChannel\",\n    \"copyTexImage2D\",\n    \"copyTexSubImage2D\",\n    \"copyTexSubImage3D\",\n    \"copyToChannel\",\n    \"copyWithin\",\n    \"correspondingElement\",\n    \"correspondingUseElement\",\n    \"corruptedVideoFrames\",\n    \"cos\",\n    \"cosh\",\n    \"count\",\n    \"countReset\",\n    \"counter-increment\",\n    \"counter-reset\",\n    \"counter-set\",\n    \"counterIncrement\",\n    \"counterReset\",\n    \"counterSet\",\n    \"country\",\n    \"cpuClass\",\n    \"cpuSleepAllowed\",\n    \"create\",\n    \"createAnalyser\",\n    \"createAnswer\",\n    \"createAttribute\",\n    \"createAttributeNS\",\n    \"createBiquadFilter\",\n    \"createBuffer\",\n    \"createBufferSource\",\n    \"createCDATASection\",\n    \"createCSSStyleSheet\",\n    \"createCaption\",\n    \"createChannelMerger\",\n    \"createChannelSplitter\",\n    \"createComment\",\n    \"createConstantSource\",\n    \"createContextualFragment\",\n    \"createControlRange\",\n    \"createConvolver\",\n    \"createDTMFSender\",\n    \"createDataChannel\",\n    \"createDelay\",\n    \"createDelayNode\",\n    \"createDocument\",\n    \"createDocumentFragment\",\n    \"createDocumentType\",\n    \"createDynamicsCompressor\",\n    \"createElement\",\n    \"createElementNS\",\n    \"createEntityReference\",\n    \"createEvent\",\n    \"createEventObject\",\n    \"createExpression\",\n    \"createFramebuffer\",\n    \"createFunction\",\n    \"createGain\",\n    \"createGainNode\",\n    \"createHTML\",\n    \"createHTMLDocument\",\n    \"createIIRFilter\",\n    \"createImageBitmap\",\n    \"createImageData\",\n    \"createIndex\",\n    \"createJavaScriptNode\",\n    \"createLinearGradient\",\n    \"createMediaElementSource\",\n    \"createMediaKeys\",\n    \"createMediaStreamDestination\",\n    \"createMediaStreamSource\",\n    \"createMediaStreamTrackSource\",\n    \"createMutableFile\",\n    \"createNSResolver\",\n    \"createNodeIterator\",\n    \"createNotification\",\n    \"createObjectStore\",\n    \"createObjectURL\",\n    \"createOffer\",\n    \"createOscillator\",\n    \"createPanner\",\n    \"createPattern\",\n    \"createPeriodicWave\",\n    \"createPolicy\",\n    \"createPopup\",\n    \"createProcessingInstruction\",\n    \"createProgram\",\n    \"createQuery\",\n    \"createRadialGradient\",\n    \"createRange\",\n    \"createRangeCollection\",\n    \"createReader\",\n    \"createRenderbuffer\",\n    \"createSVGAngle\",\n    \"createSVGLength\",\n    \"createSVGMatrix\",\n    \"createSVGNumber\",\n    \"createSVGPathSegArcAbs\",\n    \"createSVGPathSegArcRel\",\n    \"createSVGPathSegClosePath\",\n    \"createSVGPathSegCurvetoCubicAbs\",\n    \"createSVGPathSegCurvetoCubicRel\",\n    \"createSVGPathSegCurvetoCubicSmoothAbs\",\n    \"createSVGPathSegCurvetoCubicSmoothRel\",\n    \"createSVGPathSegCurvetoQuadraticAbs\",\n    \"createSVGPathSegCurvetoQuadraticRel\",\n    \"createSVGPathSegCurvetoQuadraticSmoothAbs\",\n    \"createSVGPathSegCurvetoQuadraticSmoothRel\",\n    \"createSVGPathSegLinetoAbs\",\n    \"createSVGPathSegLinetoHorizontalAbs\",\n    \"createSVGPathSegLinetoHorizontalRel\",\n    \"createSVGPathSegLinetoRel\",\n    \"createSVGPathSegLinetoVerticalAbs\",\n    \"createSVGPathSegLinetoVerticalRel\",\n    \"createSVGPathSegMovetoAbs\",\n    \"createSVGPathSegMovetoRel\",\n    \"createSVGPoint\",\n    \"createSVGRect\",\n    \"createSVGTransform\",\n    \"createSVGTransformFromMatrix\",\n    \"createSampler\",\n    \"createScript\",\n    \"createScriptProcessor\",\n    \"createScriptURL\",\n    \"createSession\",\n    \"createShader\",\n    \"createShadowRoot\",\n    \"createStereoPanner\",\n    \"createStyleSheet\",\n    \"createTBody\",\n    \"createTFoot\",\n    \"createTHead\",\n    \"createTextNode\",\n    \"createTextRange\",\n    \"createTexture\",\n    \"createTouch\",\n    \"createTouchList\",\n    \"createTransformFeedback\",\n    \"createTreeWalker\",\n    \"createVertexArray\",\n    \"createWaveShaper\",\n    \"creationTime\",\n    \"credentials\",\n    \"crossOrigin\",\n    \"crossOriginIsolated\",\n    \"crypto\",\n    \"csi\",\n    \"csp\",\n    \"cssFloat\",\n    \"cssRules\",\n    \"cssText\",\n    \"cssValueType\",\n    \"ctrlKey\",\n    \"ctrlLeft\",\n    \"cues\",\n    \"cullFace\",\n    \"currency\",\n    \"currencyDisplay\",\n    \"current\",\n    \"currentDirection\",\n    \"currentLocalDescription\",\n    \"currentNode\",\n    \"currentPage\",\n    \"currentRect\",\n    \"currentRemoteDescription\",\n    \"currentScale\",\n    \"currentScript\",\n    \"currentSrc\",\n    \"currentState\",\n    \"currentStyle\",\n    \"currentTarget\",\n    \"currentTime\",\n    \"currentTranslate\",\n    \"currentView\",\n    \"cursor\",\n    \"curve\",\n    \"customElements\",\n    \"customError\",\n    \"customSections\",\n    \"cx\",\n    \"cy\",\n    \"d\",\n    \"data\",\n    \"dataFld\",\n    \"dataFormatAs\",\n    \"dataLoss\",\n    \"dataLossMessage\",\n    \"dataPageSize\",\n    \"dataSrc\",\n    \"dataTransfer\",\n    \"database\",\n    \"databases\",\n    \"dataset\",\n    \"dateTime\",\n    \"day\",\n    \"db\",\n    \"debug\",\n    \"debuggerEnabled\",\n    \"declare\",\n    \"decode\",\n    \"decodeAudioData\",\n    \"decodeURI\",\n    \"decodeURIComponent\",\n    \"decodedBodySize\",\n    \"decoding\",\n    \"decodingInfo\",\n    \"decrypt\",\n    \"default\",\n    \"defaultCharset\",\n    \"defaultChecked\",\n    \"defaultMuted\",\n    \"defaultPlaybackRate\",\n    \"defaultPolicy\",\n    \"defaultPrevented\",\n    \"defaultRequest\",\n    \"defaultSelected\",\n    \"defaultStatus\",\n    \"defaultURL\",\n    \"defaultValue\",\n    \"defaultView\",\n    \"defaultstatus\",\n    \"defer\",\n    \"define\",\n    \"defineMagicFunction\",\n    \"defineMagicVariable\",\n    \"defineProperties\",\n    \"defineProperty\",\n    \"deg\",\n    \"delay\",\n    \"delayTime\",\n    \"delegatesFocus\",\n    \"delete\",\n    \"deleteBuffer\",\n    \"deleteCaption\",\n    \"deleteCell\",\n    \"deleteContents\",\n    \"deleteData\",\n    \"deleteDatabase\",\n    \"deleteFramebuffer\",\n    \"deleteFromDocument\",\n    \"deleteIndex\",\n    \"deleteMedium\",\n    \"deleteObjectStore\",\n    \"deleteProgram\",\n    \"deleteProperty\",\n    \"deleteQuery\",\n    \"deleteRenderbuffer\",\n    \"deleteRow\",\n    \"deleteRule\",\n    \"deleteSampler\",\n    \"deleteShader\",\n    \"deleteSync\",\n    \"deleteTFoot\",\n    \"deleteTHead\",\n    \"deleteTexture\",\n    \"deleteTransformFeedback\",\n    \"deleteVertexArray\",\n    \"deliverChangeRecords\",\n    \"delivery\",\n    \"deliveryInfo\",\n    \"deliveryStatus\",\n    \"deliveryTimestamp\",\n    \"delta\",\n    \"deltaMode\",\n    \"deltaX\",\n    \"deltaY\",\n    \"deltaZ\",\n    \"dependentLocality\",\n    \"depthFar\",\n    \"depthFunc\",\n    \"depthMask\",\n    \"depthNear\",\n    \"depthRange\",\n    \"deref\",\n    \"deriveBits\",\n    \"deriveKey\",\n    \"description\",\n    \"deselectAll\",\n    \"designMode\",\n    \"desiredSize\",\n    \"destination\",\n    \"destinationURL\",\n    \"detach\",\n    \"detachEvent\",\n    \"detachShader\",\n    \"detail\",\n    \"details\",\n    \"detect\",\n    \"detune\",\n    \"device\",\n    \"deviceClass\",\n    \"deviceId\",\n    \"deviceMemory\",\n    \"devicePixelContentBoxSize\",\n    \"devicePixelRatio\",\n    \"deviceProtocol\",\n    \"deviceSessionId\",\n    \"deviceSubclass\",\n    \"deviceVersionMajor\",\n    \"deviceVersionMinor\",\n    \"deviceVersionSubminor\",\n    \"deviceXDPI\",\n    \"deviceYDPI\",\n    \"didTimeout\",\n    \"diffuseConstant\",\n    \"digest\",\n    \"dimensions\",\n    \"dir\",\n    \"dirName\",\n    \"dirXml\",\n    \"direction\",\n    \"dirxml\",\n    \"disable\",\n    \"disablePictureInPicture\",\n    \"disableRemotePlayback\",\n    \"disableVertexAttribArray\",\n    \"disabled\",\n    \"dischargingTime\",\n    \"disconnect\",\n    \"disconnectedCallback\",\n    \"dispatch\",\n    \"dispatchEvent\",\n    \"dispatchToListener\",\n    \"display\",\n    \"displayId\",\n    \"displayName\",\n    \"disposition\",\n    \"distanceModel\",\n    \"div\",\n    \"divisor\",\n    \"djsapi\",\n    \"djsproxy\",\n    \"doImport\",\n    \"doNotTrack\",\n    \"doScroll\",\n    \"doctype\",\n    \"document\",\n    \"documentElement\",\n    \"documentMode\",\n    \"documentURI\",\n    \"dolphin\",\n    \"dolphinGameCenter\",\n    \"dolphininfo\",\n    \"dolphinmeta\",\n    \"domComplete\",\n    \"domContentLoadedEventEnd\",\n    \"domContentLoadedEventStart\",\n    \"domInteractive\",\n    \"domLoading\",\n    \"domOverlayState\",\n    \"domain\",\n    \"domainLookupEnd\",\n    \"domainLookupStart\",\n    \"dominant-baseline\",\n    \"dominantBaseline\",\n    \"done\",\n    \"dopplerFactor\",\n    \"dotAll\",\n    \"downDegrees\",\n    \"downlink\",\n    \"download\",\n    \"downloadTotal\",\n    \"downloaded\",\n    \"dpcm\",\n    \"dpi\",\n    \"dppx\",\n    \"dragDrop\",\n    \"draggable\",\n    \"drawArrays\",\n    \"drawArraysInstanced\",\n    \"drawArraysInstancedANGLE\",\n    \"drawBuffers\",\n    \"drawCustomFocusRing\",\n    \"drawElements\",\n    \"drawElementsInstanced\",\n    \"drawElementsInstancedANGLE\",\n    \"drawFocusIfNeeded\",\n    \"drawImage\",\n    \"drawImageFromRect\",\n    \"drawRangeElements\",\n    \"drawSystemFocusRing\",\n    \"drawingBufferHeight\",\n    \"drawingBufferWidth\",\n    \"dropEffect\",\n    \"droppedVideoFrames\",\n    \"dropzone\",\n    \"dtmf\",\n    \"dump\",\n    \"duplicate\",\n    \"durability\",\n    \"duration\",\n    \"dvname\",\n    \"dvnum\",\n    \"dx\",\n    \"dy\",\n    \"dynsrc\",\n    \"e\",\n    \"edgeMode\",\n    \"effect\",\n    \"effectAllowed\",\n    \"effectiveDirective\",\n    \"effectiveType\",\n    \"elapsedTime\",\n    \"element\",\n    \"elementFromPoint\",\n    \"elementTiming\",\n    \"elements\",\n    \"elementsFromPoint\",\n    \"elevation\",\n    \"ellipse\",\n    \"em\",\n    \"emHeightAscent\",\n    \"emHeightDescent\",\n    \"email\",\n    \"embeds\",\n    \"emma\",\n    \"empty\",\n    \"empty-cells\",\n    \"emptyCells\",\n    \"emptyHTML\",\n    \"emptyScript\",\n    \"emulatedPosition\",\n    \"enable\",\n    \"enableBackground\",\n    \"enableDelegations\",\n    \"enableHighAccuracy\",\n    \"enableStyleSheetsForSet\",\n    \"enableVertexAttribArray\",\n    \"enabled\",\n    \"enabledPlugin\",\n    \"encode\",\n    \"encodeInto\",\n    \"encodeURI\",\n    \"encodeURIComponent\",\n    \"encodedBodySize\",\n    \"encoding\",\n    \"encodingInfo\",\n    \"encrypt\",\n    \"enctype\",\n    \"end\",\n    \"endContainer\",\n    \"endElement\",\n    \"endElementAt\",\n    \"endOfStream\",\n    \"endOffset\",\n    \"endQuery\",\n    \"endTime\",\n    \"endTransformFeedback\",\n    \"ended\",\n    \"endpoint\",\n    \"endpointNumber\",\n    \"endpoints\",\n    \"endsWith\",\n    \"enterKeyHint\",\n    \"entities\",\n    \"entries\",\n    \"entryType\",\n    \"enumerate\",\n    \"enumerateDevices\",\n    \"enumerateEditable\",\n    \"environmentBlendMode\",\n    \"epubCaptionSide\",\n    \"epubTextCombine\",\n    \"epubTextEmphasis\",\n    \"epubTextEmphasisColor\",\n    \"epubTextEmphasisStyle\",\n    \"epubTextOrientation\",\n    \"epubTextTransform\",\n    \"epubWordBreak\",\n    \"epubWritingMode\",\n    \"equals\",\n    \"era\",\n    \"error\",\n    \"errorCode\",\n    \"errorDetail\",\n    \"errorText\",\n    \"escape\",\n    \"estimate\",\n    \"eval\",\n    \"evaluate\",\n    \"event\",\n    \"eventPhase\",\n    \"every\",\n    \"ex\",\n    \"exception\",\n    \"exchange\",\n    \"exec\",\n    \"execCommand\",\n    \"execCommandShowHelp\",\n    \"execScript\",\n    \"executeSql\",\n    \"exitFullscreen\",\n    \"exitPictureInPicture\",\n    \"exitPointerLock\",\n    \"exitPresent\",\n    \"exp\",\n    \"expand\",\n    \"expandEntityReferences\",\n    \"expando\",\n    \"expansion\",\n    \"expiration\",\n    \"expirationTime\",\n    \"expires\",\n    \"expiryDate\",\n    \"explicitOriginalTarget\",\n    \"expm1\",\n    \"exponent\",\n    \"exponentialRampToValueAtTime\",\n    \"exportKey\",\n    \"exports\",\n    \"extend\",\n    \"extensions\",\n    \"extentNode\",\n    \"extentOffset\",\n    \"external\",\n    \"externalResourcesRequired\",\n    \"extractContents\",\n    \"extractable\",\n    \"eye\",\n    \"f\",\n    \"face\",\n    \"factoryReset\",\n    \"failureReason\",\n    \"fallback\",\n    \"family\",\n    \"familyName\",\n    \"farthestViewportElement\",\n    \"fastSeek\",\n    \"fatal\",\n    \"featurePolicy\",\n    \"featureSettings\",\n    \"features\",\n    \"fenceSync\",\n    \"fetch\",\n    \"fetchStart\",\n    \"fftSize\",\n    \"fgColor\",\n    \"fieldOfView\",\n    \"file\",\n    \"fileCreatedDate\",\n    \"fileHandle\",\n    \"fileModifiedDate\",\n    \"fileName\",\n    \"fileSize\",\n    \"fileUpdatedDate\",\n    \"filename\",\n    \"files\",\n    \"filesystem\",\n    \"fill\",\n    \"fill-opacity\",\n    \"fill-rule\",\n    \"fillLightMode\",\n    \"fillOpacity\",\n    \"fillRect\",\n    \"fillRule\",\n    \"fillStyle\",\n    \"fillText\",\n    \"filter\",\n    \"filterResX\",\n    \"filterResY\",\n    \"filterUnits\",\n    \"filters\",\n    \"finally\",\n    \"find\",\n    \"findIndex\",\n    \"findRule\",\n    \"findText\",\n    \"finish\",\n    \"finishDocumentLoadTime\",\n    \"finishLoadTime\",\n    \"finished\",\n    \"fireEvent\",\n    \"firesTouchEvents\",\n    \"first\",\n    \"firstChild\",\n    \"firstElementChild\",\n    \"firstPage\",\n    \"firstPaintAfterLoadTime\",\n    \"firstPaintTime\",\n    \"fixed\",\n    \"flags\",\n    \"flat\",\n    \"flatMap\",\n    \"flex\",\n    \"flex-basis\",\n    \"flex-direction\",\n    \"flex-flow\",\n    \"flex-grow\",\n    \"flex-shrink\",\n    \"flex-wrap\",\n    \"flexBasis\",\n    \"flexDirection\",\n    \"flexFlow\",\n    \"flexGrow\",\n    \"flexShrink\",\n    \"flexWrap\",\n    \"flipX\",\n    \"flipY\",\n    \"float\",\n    \"flood-color\",\n    \"flood-opacity\",\n    \"floodColor\",\n    \"floodOpacity\",\n    \"floor\",\n    \"flush\",\n    \"focus\",\n    \"focusNode\",\n    \"focusOffset\",\n    \"font\",\n    \"font-family\",\n    \"font-feature-settings\",\n    \"font-kerning\",\n    \"font-language-override\",\n    \"font-size\",\n    \"font-size-adjust\",\n    \"font-stretch\",\n    \"font-style\",\n    \"font-synthesis\",\n    \"font-variant\",\n    \"font-variant-alternates\",\n    \"font-variant-caps\",\n    \"font-variant-east-asian\",\n    \"font-variant-ligatures\",\n    \"font-variant-numeric\",\n    \"font-variant-position\",\n    \"font-weight\",\n    \"fontBoundingBoxAscent\",\n    \"fontBoundingBoxDescent\",\n    \"fontDisplay\",\n    \"fontFamily\",\n    \"fontFeatureSettings\",\n    \"fontKerning\",\n    \"fontLanguageOverride\",\n    \"fontOpticalSizing\",\n    \"fontSize\",\n    \"fontSizeAdjust\",\n    \"fontSmoothingEnabled\",\n    \"fontStretch\",\n    \"fontStyle\",\n    \"fontSynthesis\",\n    \"fontVariant\",\n    \"fontVariantAlternates\",\n    \"fontVariantCaps\",\n    \"fontVariantEastAsian\",\n    \"fontVariantLigatures\",\n    \"fontVariantNumeric\",\n    \"fontVariantPosition\",\n    \"fontVariationSettings\",\n    \"fontWeight\",\n    \"fontcolor\",\n    \"fontfaces\",\n    \"fonts\",\n    \"fontsize\",\n    \"for\",\n    \"forEach\",\n    \"force\",\n    \"forceRedraw\",\n    \"form\",\n    \"formAction\",\n    \"formData\",\n    \"formEnctype\",\n    \"formMethod\",\n    \"formNoValidate\",\n    \"formTarget\",\n    \"format\",\n    \"formatRange\",\n    \"formatRangeToParts\",\n    \"formatToParts\",\n    \"forms\",\n    \"forward\",\n    \"forwardX\",\n    \"forwardY\",\n    \"forwardZ\",\n    \"foundation\",\n    \"fr\",\n    \"fragmentDirective\",\n    \"frame\",\n    \"frameBorder\",\n    \"frameElement\",\n    \"frameSpacing\",\n    \"framebuffer\",\n    \"framebufferHeight\",\n    \"framebufferRenderbuffer\",\n    \"framebufferTexture2D\",\n    \"framebufferTextureLayer\",\n    \"framebufferWidth\",\n    \"frames\",\n    \"freeSpace\",\n    \"freeze\",\n    \"frequency\",\n    \"frequencyBinCount\",\n    \"from\",\n    \"fromCharCode\",\n    \"fromCodePoint\",\n    \"fromElement\",\n    \"fromEntries\",\n    \"fromFloat32Array\",\n    \"fromFloat64Array\",\n    \"fromMatrix\",\n    \"fromPoint\",\n    \"fromQuad\",\n    \"fromRect\",\n    \"frontFace\",\n    \"fround\",\n    \"fullPath\",\n    \"fullScreen\",\n    \"fullscreen\",\n    \"fullscreenElement\",\n    \"fullscreenEnabled\",\n    \"fx\",\n    \"fy\",\n    \"gain\",\n    \"gamepad\",\n    \"gamma\",\n    \"gap\",\n    \"gatheringState\",\n    \"gatt\",\n    \"genderIdentity\",\n    \"generateCertificate\",\n    \"generateKey\",\n    \"generateMipmap\",\n    \"generateRequest\",\n    \"geolocation\",\n    \"gestureObject\",\n    \"get\",\n    \"getActiveAttrib\",\n    \"getActiveUniform\",\n    \"getActiveUniformBlockName\",\n    \"getActiveUniformBlockParameter\",\n    \"getActiveUniforms\",\n    \"getAdditionalLanguages\",\n    \"getAdjacentText\",\n    \"getAll\",\n    \"getAllKeys\",\n    \"getAllResponseHeaders\",\n    \"getAllowlistForFeature\",\n    \"getAnimations\",\n    \"getAsFile\",\n    \"getAsString\",\n    \"getAttachedShaders\",\n    \"getAttribLocation\",\n    \"getAttribute\",\n    \"getAttributeNS\",\n    \"getAttributeNames\",\n    \"getAttributeNode\",\n    \"getAttributeNodeNS\",\n    \"getAttributeType\",\n    \"getAudioTracks\",\n    \"getAvailability\",\n    \"getBBox\",\n    \"getBattery\",\n    \"getBigInt64\",\n    \"getBigUint64\",\n    \"getBlob\",\n    \"getBookmark\",\n    \"getBoundingClientRect\",\n    \"getBounds\",\n    \"getBufferParameter\",\n    \"getBufferSubData\",\n    \"getByteFrequencyData\",\n    \"getByteTimeDomainData\",\n    \"getCSSCanvasContext\",\n    \"getCTM\",\n    \"getCandidateWindowClientRect\",\n    \"getCanonicalLocales\",\n    \"getCapabilities\",\n    \"getChannelData\",\n    \"getCharNumAtPosition\",\n    \"getCharacteristic\",\n    \"getCharacteristics\",\n    \"getClientExtensionResults\",\n    \"getClientRect\",\n    \"getClientRects\",\n    \"getCoalescedEvents\",\n    \"getCompositionAlternatives\",\n    \"getComputedStyle\",\n    \"getComputedTextLength\",\n    \"getComputedTiming\",\n    \"getConfiguration\",\n    \"getConstraints\",\n    \"getContext\",\n    \"getContextAttributes\",\n    \"getContributingSources\",\n    \"getCount\",\n    \"getCounterValue\",\n    \"getCueAsHTML\",\n    \"getCueById\",\n    \"getCurrentPosition\",\n    \"getCurrentTime\",\n    \"getData\",\n    \"getDatabaseNames\",\n    \"getDate\",\n    \"getDay\",\n    \"getDefaultComputedStyle\",\n    \"getDescriptor\",\n    \"getDescriptors\",\n    \"getDestinationInsertionPoints\",\n    \"getDetails\",\n    \"getDevices\",\n    \"getDirectory\",\n    \"getDisplayMedia\",\n    \"getDistributedNodes\",\n    \"getEditable\",\n    \"getElementById\",\n    \"getElementsByClassName\",\n    \"getElementsByName\",\n    \"getElementsByTagName\",\n    \"getElementsByTagNameNS\",\n    \"getEnclosureList\",\n    \"getEndPositionOfChar\",\n    \"getEntries\",\n    \"getEntriesByName\",\n    \"getEntriesByType\",\n    \"getError\",\n    \"getExtension\",\n    \"getExtentOfChar\",\n    \"getEyeParameters\",\n    \"getFeature\",\n    \"getFile\",\n    \"getFiles\",\n    \"getFilesAndDirectories\",\n    \"getFingerprints\",\n    \"getFloat32\",\n    \"getFloat64\",\n    \"getFloatFrequencyData\",\n    \"getFloatTimeDomainData\",\n    \"getFloatValue\",\n    \"getFragDataLocation\",\n    \"getFrameData\",\n    \"getFramebufferAttachmentParameter\",\n    \"getFrequencyResponse\",\n    \"getFullYear\",\n    \"getGamepads\",\n    \"getHitTestResults\",\n    \"getHitTestResultsForTransientInput\",\n    \"getHours\",\n    \"getIdentityAssertion\",\n    \"getIds\",\n    \"getImageData\",\n    \"getIndexedParameter\",\n    \"getInstalled\",\n    \"getInstalledRelatedApps\",\n    \"getInt16\",\n    \"getInt32\",\n    \"getInt8\",\n    \"getInternalformatParameter\",\n    \"getIntersectionList\",\n    \"getIsInstalled\",\n    \"getItem\",\n    \"getItems\",\n    \"getKey\",\n    \"getKeyframes\",\n    \"getLayers\",\n    \"getLayoutMap\",\n    \"getLineDash\",\n    \"getLocalCandidates\",\n    \"getLocalParameters\",\n    \"getLocalStreams\",\n    \"getLocalizationResource\",\n    \"getMarks\",\n    \"getMatchedCSSRules\",\n    \"getMeasures\",\n    \"getMetadata\",\n    \"getMilliseconds\",\n    \"getMinutes\",\n    \"getModifierState\",\n    \"getMonth\",\n    \"getNamedItem\",\n    \"getNamedItemNS\",\n    \"getNativeFramebufferScaleFactor\",\n    \"getNotifications\",\n    \"getNotifier\",\n    \"getNumberOfChars\",\n    \"getOffsetReferenceSpace\",\n    \"getOutputTimestamp\",\n    \"getOverrideHistoryNavigationMode\",\n    \"getOverrideStyle\",\n    \"getOwnPropertyDescriptor\",\n    \"getOwnPropertyDescriptors\",\n    \"getOwnPropertyNames\",\n    \"getOwnPropertySymbols\",\n    \"getParameter\",\n    \"getParameters\",\n    \"getParent\",\n    \"getPathSegAtLength\",\n    \"getPhotoCapabilities\",\n    \"getPhotoSettings\",\n    \"getPointAtLength\",\n    \"getPose\",\n    \"getPredictedEvents\",\n    \"getPreference\",\n    \"getPreferenceDefault\",\n    \"getPresentationAttribute\",\n    \"getPreventDefault\",\n    \"getPrimaryService\",\n    \"getPrimaryServices\",\n    \"getProgramInfoLog\",\n    \"getProgramParameter\",\n    \"getPropertyCSSValue\",\n    \"getPropertyPriority\",\n    \"getPropertyShorthand\",\n    \"getPropertyType\",\n    \"getPropertyValue\",\n    \"getPrototypeOf\",\n    \"getQuery\",\n    \"getQueryParameter\",\n    \"getRGBColorValue\",\n    \"getRandomValues\",\n    \"getRangeAt\",\n    \"getReader\",\n    \"getReceivers\",\n    \"getRectValue\",\n    \"getRegistration\",\n    \"getRegistrations\",\n    \"getRemoteCandidates\",\n    \"getRemoteCertificates\",\n    \"getRemoteParameters\",\n    \"getRemoteStreams\",\n    \"getRenderbufferParameter\",\n    \"getResponseHeader\",\n    \"getRevision\",\n    \"getRoot\",\n    \"getRootNode\",\n    \"getRotationOfChar\",\n    \"getRules\",\n    \"getSVGDocument\",\n    \"getSamplerParameter\",\n    \"getScreenCTM\",\n    \"getSeconds\",\n    \"getSelectedCandidatePair\",\n    \"getSelection\",\n    \"getSelf\",\n    \"getSenders\",\n    \"getService\",\n    \"getSettings\",\n    \"getShaderInfoLog\",\n    \"getShaderParameter\",\n    \"getShaderPrecisionFormat\",\n    \"getShaderSource\",\n    \"getSimpleDuration\",\n    \"getSiteIcons\",\n    \"getSources\",\n    \"getSpeculativeParserUrls\",\n    \"getStartDate\",\n    \"getStartPositionOfChar\",\n    \"getStartTime\",\n    \"getState\",\n    \"getStats\",\n    \"getStatusForPolicy\",\n    \"getStorageUpdates\",\n    \"getStreamById\",\n    \"getStringValue\",\n    \"getSubStringLength\",\n    \"getSubscription\",\n    \"getSupportedConstraints\",\n    \"getSupportedExtensions\",\n    \"getSupportedFormats\",\n    \"getSyncParameter\",\n    \"getSynchronizationSources\",\n    \"getTags\",\n    \"getTargetRanges\",\n    \"getTexParameter\",\n    \"getTime\",\n    \"getTimezoneOffset\",\n    \"getTiming\",\n    \"getTotalLength\",\n    \"getTrackById\",\n    \"getTracks\",\n    \"getTransceivers\",\n    \"getTransform\",\n    \"getTransformFeedbackVarying\",\n    \"getTransformToElement\",\n    \"getTransports\",\n    \"getType\",\n    \"getTypeMapping\",\n    \"getUTCDate\",\n    \"getUTCDay\",\n    \"getUTCFullYear\",\n    \"getUTCHours\",\n    \"getUTCMilliseconds\",\n    \"getUTCMinutes\",\n    \"getUTCMonth\",\n    \"getUTCSeconds\",\n    \"getUint16\",\n    \"getUint32\",\n    \"getUint8\",\n    \"getUniform\",\n    \"getUniformBlockIndex\",\n    \"getUniformIndices\",\n    \"getUniformLocation\",\n    \"getUserMedia\",\n    \"getVRDisplays\",\n    \"getValues\",\n    \"getVarDate\",\n    \"getVariableValue\",\n    \"getVertexAttrib\",\n    \"getVertexAttribOffset\",\n    \"getVideoPlaybackQuality\",\n    \"getVideoTracks\",\n    \"getViewerPose\",\n    \"getViewport\",\n    \"getVoices\",\n    \"getWakeLockState\",\n    \"getWriter\",\n    \"getYear\",\n    \"givenName\",\n    \"global\",\n    \"globalAlpha\",\n    \"globalCompositeOperation\",\n    \"globalThis\",\n    \"glyphOrientationHorizontal\",\n    \"glyphOrientationVertical\",\n    \"glyphRef\",\n    \"go\",\n    \"grabFrame\",\n    \"grad\",\n    \"gradientTransform\",\n    \"gradientUnits\",\n    \"grammars\",\n    \"green\",\n    \"grid\",\n    \"grid-area\",\n    \"grid-auto-columns\",\n    \"grid-auto-flow\",\n    \"grid-auto-rows\",\n    \"grid-column\",\n    \"grid-column-end\",\n    \"grid-column-gap\",\n    \"grid-column-start\",\n    \"grid-gap\",\n    \"grid-row\",\n    \"grid-row-end\",\n    \"grid-row-gap\",\n    \"grid-row-start\",\n    \"grid-template\",\n    \"grid-template-areas\",\n    \"grid-template-columns\",\n    \"grid-template-rows\",\n    \"gridArea\",\n    \"gridAutoColumns\",\n    \"gridAutoFlow\",\n    \"gridAutoRows\",\n    \"gridColumn\",\n    \"gridColumnEnd\",\n    \"gridColumnGap\",\n    \"gridColumnStart\",\n    \"gridGap\",\n    \"gridRow\",\n    \"gridRowEnd\",\n    \"gridRowGap\",\n    \"gridRowStart\",\n    \"gridTemplate\",\n    \"gridTemplateAreas\",\n    \"gridTemplateColumns\",\n    \"gridTemplateRows\",\n    \"gripSpace\",\n    \"group\",\n    \"groupCollapsed\",\n    \"groupEnd\",\n    \"groupId\",\n    \"grow\",\n    \"hadRecentInput\",\n    \"hand\",\n    \"handedness\",\n    \"hangingBaseline\",\n    \"hangingPunctuation\",\n    \"hapticActuators\",\n    \"hardwareConcurrency\",\n    \"has\",\n    \"hasAttribute\",\n    \"hasAttributeNS\",\n    \"hasAttributes\",\n    \"hasBeenActive\",\n    \"hasChildNodes\",\n    \"hasComposition\",\n    \"hasEnrolledInstrument\",\n    \"hasExtension\",\n    \"hasExternalDisplay\",\n    \"hasFeature\",\n    \"hasFocus\",\n    \"hasInstance\",\n    \"hasLayout\",\n    \"hasListener\",\n    \"hasListeners\",\n    \"hasOrientation\",\n    \"hasOwnProperty\",\n    \"hasPointerCapture\",\n    \"hasPosition\",\n    \"hasReading\",\n    \"hasStorageAccess\",\n    \"hash\",\n    \"head\",\n    \"headers\",\n    \"heading\",\n    \"height\",\n    \"hidden\",\n    \"hide\",\n    \"hideFocus\",\n    \"high\",\n    \"highWaterMark\",\n    \"hint\",\n    \"history\",\n    \"honorificPrefix\",\n    \"honorificSuffix\",\n    \"horizontalOverflow\",\n    \"host\",\n    \"hostCandidate\",\n    \"hostname\",\n    \"hour\",\n    \"hour12\",\n    \"hourCycle\",\n    \"href\",\n    \"hrefTranslate\",\n    \"hreflang\",\n    \"hspace\",\n    \"html5TagCheckInerface\",\n    \"htmlFor\",\n    \"htmlText\",\n    \"httpEquiv\",\n    \"httpRequestStatusCode\",\n    \"hwTimestamp\",\n    \"hyphens\",\n    \"hypot\",\n    \"iccId\",\n    \"iceConnectionState\",\n    \"iceGatheringState\",\n    \"iceTransport\",\n    \"icon\",\n    \"iconURL\",\n    \"id\",\n    \"identifier\",\n    \"identity\",\n    \"ideographicBaseline\",\n    \"idpLoginUrl\",\n    \"ignoreBOM\",\n    \"ignoreCase\",\n    \"ignoreDepthValues\",\n    \"ignoreMutedMedia\",\n    \"ignorePunctuation\",\n    \"image-orientation\",\n    \"image-rendering\",\n    \"imageHeight\",\n    \"imageOrientation\",\n    \"imageRendering\",\n    \"imageSizes\",\n    \"imageSmoothingEnabled\",\n    \"imageSmoothingQuality\",\n    \"imageSrcset\",\n    \"imageWidth\",\n    \"images\",\n    \"ime-mode\",\n    \"imeMode\",\n    \"implementation\",\n    \"import\",\n    \"importKey\",\n    \"importNode\",\n    \"importStylesheet\",\n    \"imports\",\n    \"impp\",\n    \"imul\",\n    \"in\",\n    \"in1\",\n    \"in2\",\n    \"inBandMetadataTrackDispatchType\",\n    \"inRange\",\n    \"includes\",\n    \"incremental\",\n    \"indeterminate\",\n    \"index\",\n    \"indexNames\",\n    \"indexOf\",\n    \"indexedDB\",\n    \"indicate\",\n    \"inertiaDestinationX\",\n    \"inertiaDestinationY\",\n    \"info\",\n    \"init\",\n    \"initAnimationEvent\",\n    \"initBeforeLoadEvent\",\n    \"initClipboardEvent\",\n    \"initCloseEvent\",\n    \"initCommandEvent\",\n    \"initCompositionEvent\",\n    \"initCustomEvent\",\n    \"initData\",\n    \"initDataType\",\n    \"initDeviceMotionEvent\",\n    \"initDeviceOrientationEvent\",\n    \"initDragEvent\",\n    \"initErrorEvent\",\n    \"initEvent\",\n    \"initFocusEvent\",\n    \"initGestureEvent\",\n    \"initHashChangeEvent\",\n    \"initKeyEvent\",\n    \"initKeyboardEvent\",\n    \"initMSManipulationEvent\",\n    \"initMessageEvent\",\n    \"initMouseEvent\",\n    \"initMouseScrollEvent\",\n    \"initMouseWheelEvent\",\n    \"initMutationEvent\",\n    \"initNSMouseEvent\",\n    \"initOverflowEvent\",\n    \"initPageEvent\",\n    \"initPageTransitionEvent\",\n    \"initPointerEvent\",\n    \"initPopStateEvent\",\n    \"initProgressEvent\",\n    \"initScrollAreaEvent\",\n    \"initSimpleGestureEvent\",\n    \"initStorageEvent\",\n    \"initTextEvent\",\n    \"initTimeEvent\",\n    \"initTouchEvent\",\n    \"initTransitionEvent\",\n    \"initUIEvent\",\n    \"initWebKitAnimationEvent\",\n    \"initWebKitTransitionEvent\",\n    \"initWebKitWheelEvent\",\n    \"initWheelEvent\",\n    \"initialTime\",\n    \"initialize\",\n    \"initiatorType\",\n    \"inline-size\",\n    \"inlineSize\",\n    \"inlineVerticalFieldOfView\",\n    \"inner\",\n    \"innerHTML\",\n    \"innerHeight\",\n    \"innerText\",\n    \"innerWidth\",\n    \"input\",\n    \"inputBuffer\",\n    \"inputEncoding\",\n    \"inputMethod\",\n    \"inputMode\",\n    \"inputSource\",\n    \"inputSources\",\n    \"inputType\",\n    \"inputs\",\n    \"insertAdjacentElement\",\n    \"insertAdjacentHTML\",\n    \"insertAdjacentText\",\n    \"insertBefore\",\n    \"insertCell\",\n    \"insertDTMF\",\n    \"insertData\",\n    \"insertId\",\n    \"insertItemBefore\",\n    \"insertNode\",\n    \"insertRow\",\n    \"insertRule\",\n    \"inset\",\n    \"inset-block\",\n    \"inset-block-end\",\n    \"inset-block-start\",\n    \"inset-inline\",\n    \"inset-inline-end\",\n    \"inset-inline-start\",\n    \"insetBlock\",\n    \"insetBlockEnd\",\n    \"insetBlockStart\",\n    \"insetInline\",\n    \"insetInlineEnd\",\n    \"insetInlineStart\",\n    \"install\",\n    \"installChrome\",\n    \"installPackage\",\n    \"installState\",\n    \"installing\",\n    \"instanceRoot\",\n    \"instantiate\",\n    \"instantiateStreaming\",\n    \"instruments\",\n    \"integrity\",\n    \"interactionMode\",\n    \"intercept\",\n    \"interfaceClass\",\n    \"interfaceName\",\n    \"interfaceNumber\",\n    \"interfaceProtocol\",\n    \"interfaceSubclass\",\n    \"interfaces\",\n    \"interimResults\",\n    \"internalSubset\",\n    \"interpretation\",\n    \"intersectionRatio\",\n    \"intersectionRect\",\n    \"intersectsNode\",\n    \"interval\",\n    \"invalidIteratorState\",\n    \"invalidateFramebuffer\",\n    \"invalidateSubFramebuffer\",\n    \"inverse\",\n    \"invertSelf\",\n    \"is\",\n    \"is2D\",\n    \"isActive\",\n    \"isAlternate\",\n    \"isArray\",\n    \"isBingCurrentSearchDefault\",\n    \"isBuffer\",\n    \"isCandidateWindowVisible\",\n    \"isChar\",\n    \"isCollapsed\",\n    \"isComposing\",\n    \"isConcatSpreadable\",\n    \"isConnected\",\n    \"isContentEditable\",\n    \"isContentHandlerRegistered\",\n    \"isContextLost\",\n    \"isDefaultNamespace\",\n    \"isDirectory\",\n    \"isDisabled\",\n    \"isEnabled\",\n    \"isEqual\",\n    \"isEqualNode\",\n    \"isExtensible\",\n    \"isExternalCTAP2SecurityKeySupported\",\n    \"isFile\",\n    \"isFinite\",\n    \"isFramebuffer\",\n    \"isFrozen\",\n    \"isGenerator\",\n    \"isHTML\",\n    \"isHistoryNavigation\",\n    \"isId\",\n    \"isIdentity\",\n    \"isInjected\",\n    \"isInstalled\",\n    \"isInteger\",\n    \"isIntersecting\",\n    \"isLockFree\",\n    \"isMap\",\n    \"isMultiLine\",\n    \"isNaN\",\n    \"isOpen\",\n    \"isPointInFill\",\n    \"isPointInPath\",\n    \"isPointInRange\",\n    \"isPointInStroke\",\n    \"isPrefAlternate\",\n    \"isPresenting\",\n    \"isPrimary\",\n    \"isProgram\",\n    \"isPropertyImplicit\",\n    \"isProtocolHandlerRegistered\",\n    \"isPrototypeOf\",\n    \"isQuery\",\n    \"isRenderbuffer\",\n    \"isSafeInteger\",\n    \"isSameNode\",\n    \"isSampler\",\n    \"isScript\",\n    \"isScriptURL\",\n    \"isSealed\",\n    \"isSecureContext\",\n    \"isSessionSupported\",\n    \"isShader\",\n    \"isSupported\",\n    \"isSync\",\n    \"isTextEdit\",\n    \"isTexture\",\n    \"isTransformFeedback\",\n    \"isTrusted\",\n    \"isTypeSupported\",\n    \"isTypeSupportedWithFeatures\",\n    \"isUserVerifyingPlatformAuthenticatorAvailable\",\n    \"isVertexArray\",\n    \"isView\",\n    \"isVisible\",\n    \"isochronousTransferIn\",\n    \"isochronousTransferOut\",\n    \"isolation\",\n    \"italics\",\n    \"item\",\n    \"itemId\",\n    \"itemProp\",\n    \"itemRef\",\n    \"itemScope\",\n    \"itemType\",\n    \"itemValue\",\n    \"items\",\n    \"iterateNext\",\n    \"iterator\",\n    \"javaEnabled\",\n    \"jobTitle\",\n    \"join\",\n    \"jsHeapSizeLimit\",\n    \"json\",\n    \"justify-content\",\n    \"justify-items\",\n    \"justify-self\",\n    \"justifyContent\",\n    \"justifyItems\",\n    \"justifySelf\",\n    \"k1\",\n    \"k2\",\n    \"k3\",\n    \"k4\",\n    \"kHz\",\n    \"keepalive\",\n    \"kernelMatrix\",\n    \"kernelUnitLengthX\",\n    \"kernelUnitLengthY\",\n    \"kerning\",\n    \"key\",\n    \"keyCode\",\n    \"keyFor\",\n    \"keyIdentifier\",\n    \"keyLightEnabled\",\n    \"keyLocation\",\n    \"keyPath\",\n    \"keyStatuses\",\n    \"keySystem\",\n    \"keyText\",\n    \"keyUsage\",\n    \"keyboard\",\n    \"keys\",\n    \"keytype\",\n    \"kind\",\n    \"knee\",\n    \"label\",\n    \"labels\",\n    \"lang\",\n    \"language\",\n    \"languages\",\n    \"largeArcFlag\",\n    \"lastActivePanel\",\n    \"lastChild\",\n    \"lastElementChild\",\n    \"lastEventId\",\n    \"lastIndex\",\n    \"lastIndexOf\",\n    \"lastInputTime\",\n    \"lastMatch\",\n    \"lastMessageSubject\",\n    \"lastMessageType\",\n    \"lastModified\",\n    \"lastModifiedDate\",\n    \"lastPage\",\n    \"lastParen\",\n    \"lastState\",\n    \"lastStyleSheetSet\",\n    \"latitude\",\n    \"layerX\",\n    \"layerY\",\n    \"layoutFlow\",\n    \"layoutGrid\",\n    \"layoutGridChar\",\n    \"layoutGridLine\",\n    \"layoutGridMode\",\n    \"layoutGridType\",\n    \"lbound\",\n    \"left\",\n    \"leftContext\",\n    \"leftDegrees\",\n    \"leftMargin\",\n    \"leftProjectionMatrix\",\n    \"leftViewMatrix\",\n    \"length\",\n    \"lengthAdjust\",\n    \"lengthComputable\",\n    \"letter-spacing\",\n    \"letterSpacing\",\n    \"level\",\n    \"lighting-color\",\n    \"lightingColor\",\n    \"limitingConeAngle\",\n    \"line\",\n    \"line-break\",\n    \"line-height\",\n    \"lineAlign\",\n    \"lineBreak\",\n    \"lineCap\",\n    \"lineDashOffset\",\n    \"lineHeight\",\n    \"lineJoin\",\n    \"lineNumber\",\n    \"lineTo\",\n    \"lineWidth\",\n    \"linearAcceleration\",\n    \"linearRampToValueAtTime\",\n    \"linearVelocity\",\n    \"lineno\",\n    \"lines\",\n    \"link\",\n    \"linkColor\",\n    \"linkProgram\",\n    \"links\",\n    \"list\",\n    \"list-style\",\n    \"list-style-image\",\n    \"list-style-position\",\n    \"list-style-type\",\n    \"listStyle\",\n    \"listStyleImage\",\n    \"listStylePosition\",\n    \"listStyleType\",\n    \"listener\",\n    \"load\",\n    \"loadEventEnd\",\n    \"loadEventStart\",\n    \"loadTime\",\n    \"loadTimes\",\n    \"loaded\",\n    \"loading\",\n    \"localDescription\",\n    \"localName\",\n    \"localService\",\n    \"localStorage\",\n    \"locale\",\n    \"localeCompare\",\n    \"location\",\n    \"locationbar\",\n    \"lock\",\n    \"locked\",\n    \"lockedFile\",\n    \"locks\",\n    \"log\",\n    \"log10\",\n    \"log1p\",\n    \"log2\",\n    \"logicalXDPI\",\n    \"logicalYDPI\",\n    \"longDesc\",\n    \"longitude\",\n    \"lookupNamespaceURI\",\n    \"lookupPrefix\",\n    \"loop\",\n    \"loopEnd\",\n    \"loopStart\",\n    \"looping\",\n    \"low\",\n    \"lower\",\n    \"lowerBound\",\n    \"lowerOpen\",\n    \"lowsrc\",\n    \"m11\",\n    \"m12\",\n    \"m13\",\n    \"m14\",\n    \"m21\",\n    \"m22\",\n    \"m23\",\n    \"m24\",\n    \"m31\",\n    \"m32\",\n    \"m33\",\n    \"m34\",\n    \"m41\",\n    \"m42\",\n    \"m43\",\n    \"m44\",\n    \"makeXRCompatible\",\n    \"manifest\",\n    \"manufacturer\",\n    \"manufacturerName\",\n    \"map\",\n    \"mapping\",\n    \"margin\",\n    \"margin-block\",\n    \"margin-block-end\",\n    \"margin-block-start\",\n    \"margin-bottom\",\n    \"margin-inline\",\n    \"margin-inline-end\",\n    \"margin-inline-start\",\n    \"margin-left\",\n    \"margin-right\",\n    \"margin-top\",\n    \"marginBlock\",\n    \"marginBlockEnd\",\n    \"marginBlockStart\",\n    \"marginBottom\",\n    \"marginHeight\",\n    \"marginInline\",\n    \"marginInlineEnd\",\n    \"marginInlineStart\",\n    \"marginLeft\",\n    \"marginRight\",\n    \"marginTop\",\n    \"marginWidth\",\n    \"mark\",\n    \"markTimeline\",\n    \"marker\",\n    \"marker-end\",\n    \"marker-mid\",\n    \"marker-offset\",\n    \"marker-start\",\n    \"markerEnd\",\n    \"markerHeight\",\n    \"markerMid\",\n    \"markerOffset\",\n    \"markerStart\",\n    \"markerUnits\",\n    \"markerWidth\",\n    \"marks\",\n    \"mask\",\n    \"mask-clip\",\n    \"mask-composite\",\n    \"mask-image\",\n    \"mask-mode\",\n    \"mask-origin\",\n    \"mask-position\",\n    \"mask-position-x\",\n    \"mask-position-y\",\n    \"mask-repeat\",\n    \"mask-size\",\n    \"mask-type\",\n    \"maskClip\",\n    \"maskComposite\",\n    \"maskContentUnits\",\n    \"maskImage\",\n    \"maskMode\",\n    \"maskOrigin\",\n    \"maskPosition\",\n    \"maskPositionX\",\n    \"maskPositionY\",\n    \"maskRepeat\",\n    \"maskSize\",\n    \"maskType\",\n    \"maskUnits\",\n    \"match\",\n    \"matchAll\",\n    \"matchMedia\",\n    \"matchMedium\",\n    \"matches\",\n    \"matrix\",\n    \"matrixTransform\",\n    \"max\",\n    \"max-block-size\",\n    \"max-height\",\n    \"max-inline-size\",\n    \"max-width\",\n    \"maxActions\",\n    \"maxAlternatives\",\n    \"maxBlockSize\",\n    \"maxChannelCount\",\n    \"maxChannels\",\n    \"maxConnectionsPerServer\",\n    \"maxDecibels\",\n    \"maxDistance\",\n    \"maxHeight\",\n    \"maxInlineSize\",\n    \"maxLayers\",\n    \"maxLength\",\n    \"maxMessageSize\",\n    \"maxPacketLifeTime\",\n    \"maxRetransmits\",\n    \"maxTouchPoints\",\n    \"maxValue\",\n    \"maxWidth\",\n    \"maxZoom\",\n    \"maximize\",\n    \"maximumAge\",\n    \"maximumFractionDigits\",\n    \"measure\",\n    \"measureText\",\n    \"media\",\n    \"mediaCapabilities\",\n    \"mediaDevices\",\n    \"mediaElement\",\n    \"mediaGroup\",\n    \"mediaKeys\",\n    \"mediaSession\",\n    \"mediaStream\",\n    \"mediaText\",\n    \"meetOrSlice\",\n    \"memory\",\n    \"menubar\",\n    \"mergeAttributes\",\n    \"message\",\n    \"messageClass\",\n    \"messageHandlers\",\n    \"messageType\",\n    \"metaKey\",\n    \"metadata\",\n    \"method\",\n    \"methodDetails\",\n    \"methodName\",\n    \"mid\",\n    \"mimeType\",\n    \"mimeTypes\",\n    \"min\",\n    \"min-block-size\",\n    \"min-height\",\n    \"min-inline-size\",\n    \"min-width\",\n    \"minBlockSize\",\n    \"minDecibels\",\n    \"minHeight\",\n    \"minInlineSize\",\n    \"minLength\",\n    \"minValue\",\n    \"minWidth\",\n    \"minZoom\",\n    \"minimize\",\n    \"minimumFractionDigits\",\n    \"minimumIntegerDigits\",\n    \"minute\",\n    \"miterLimit\",\n    \"mix-blend-mode\",\n    \"mixBlendMode\",\n    \"mm\",\n    \"mode\",\n    \"modify\",\n    \"month\",\n    \"motion\",\n    \"motionOffset\",\n    \"motionPath\",\n    \"motionRotation\",\n    \"mount\",\n    \"move\",\n    \"moveBy\",\n    \"moveEnd\",\n    \"moveFirst\",\n    \"moveFocusDown\",\n    \"moveFocusLeft\",\n    \"moveFocusRight\",\n    \"moveFocusUp\",\n    \"moveNext\",\n    \"moveRow\",\n    \"moveStart\",\n    \"moveTo\",\n    \"moveToBookmark\",\n    \"moveToElementText\",\n    \"moveToPoint\",\n    \"movementX\",\n    \"movementY\",\n    \"mozAdd\",\n    \"mozAnimationStartTime\",\n    \"mozAnon\",\n    \"mozApps\",\n    \"mozAudioCaptured\",\n    \"mozAudioChannelType\",\n    \"mozAutoplayEnabled\",\n    \"mozCancelAnimationFrame\",\n    \"mozCancelFullScreen\",\n    \"mozCancelRequestAnimationFrame\",\n    \"mozCaptureStream\",\n    \"mozCaptureStreamUntilEnded\",\n    \"mozClearDataAt\",\n    \"mozContact\",\n    \"mozContacts\",\n    \"mozCreateFileHandle\",\n    \"mozCurrentTransform\",\n    \"mozCurrentTransformInverse\",\n    \"mozCursor\",\n    \"mozDash\",\n    \"mozDashOffset\",\n    \"mozDecodedFrames\",\n    \"mozExitPointerLock\",\n    \"mozFillRule\",\n    \"mozFragmentEnd\",\n    \"mozFrameDelay\",\n    \"mozFullScreen\",\n    \"mozFullScreenElement\",\n    \"mozFullScreenEnabled\",\n    \"mozGetAll\",\n    \"mozGetAllKeys\",\n    \"mozGetAsFile\",\n    \"mozGetDataAt\",\n    \"mozGetMetadata\",\n    \"mozGetUserMedia\",\n    \"mozHasAudio\",\n    \"mozHasItem\",\n    \"mozHidden\",\n    \"mozImageSmoothingEnabled\",\n    \"mozIndexedDB\",\n    \"mozInnerScreenX\",\n    \"mozInnerScreenY\",\n    \"mozInputSource\",\n    \"mozIsTextField\",\n    \"mozItem\",\n    \"mozItemCount\",\n    \"mozItems\",\n    \"mozLength\",\n    \"mozLockOrientation\",\n    \"mozMatchesSelector\",\n    \"mozMovementX\",\n    \"mozMovementY\",\n    \"mozOpaque\",\n    \"mozOrientation\",\n    \"mozPaintCount\",\n    \"mozPaintedFrames\",\n    \"mozParsedFrames\",\n    \"mozPay\",\n    \"mozPointerLockElement\",\n    \"mozPresentedFrames\",\n    \"mozPreservesPitch\",\n    \"mozPressure\",\n    \"mozPrintCallback\",\n    \"mozRTCIceCandidate\",\n    \"mozRTCPeerConnection\",\n    \"mozRTCSessionDescription\",\n    \"mozRemove\",\n    \"mozRequestAnimationFrame\",\n    \"mozRequestFullScreen\",\n    \"mozRequestPointerLock\",\n    \"mozSetDataAt\",\n    \"mozSetImageElement\",\n    \"mozSourceNode\",\n    \"mozSrcObject\",\n    \"mozSystem\",\n    \"mozTCPSocket\",\n    \"mozTextStyle\",\n    \"mozTypesAt\",\n    \"mozUnlockOrientation\",\n    \"mozUserCancelled\",\n    \"mozVisibilityState\",\n    \"ms\",\n    \"msAnimation\",\n    \"msAnimationDelay\",\n    \"msAnimationDirection\",\n    \"msAnimationDuration\",\n    \"msAnimationFillMode\",\n    \"msAnimationIterationCount\",\n    \"msAnimationName\",\n    \"msAnimationPlayState\",\n    \"msAnimationStartTime\",\n    \"msAnimationTimingFunction\",\n    \"msBackfaceVisibility\",\n    \"msBlockProgression\",\n    \"msCSSOMElementFloatMetrics\",\n    \"msCaching\",\n    \"msCachingEnabled\",\n    \"msCancelRequestAnimationFrame\",\n    \"msCapsLockWarningOff\",\n    \"msClearImmediate\",\n    \"msClose\",\n    \"msContentZoomChaining\",\n    \"msContentZoomFactor\",\n    \"msContentZoomLimit\",\n    \"msContentZoomLimitMax\",\n    \"msContentZoomLimitMin\",\n    \"msContentZoomSnap\",\n    \"msContentZoomSnapPoints\",\n    \"msContentZoomSnapType\",\n    \"msContentZooming\",\n    \"msConvertURL\",\n    \"msCrypto\",\n    \"msDoNotTrack\",\n    \"msElementsFromPoint\",\n    \"msElementsFromRect\",\n    \"msExitFullscreen\",\n    \"msExtendedCode\",\n    \"msFillRule\",\n    \"msFirstPaint\",\n    \"msFlex\",\n    \"msFlexAlign\",\n    \"msFlexDirection\",\n    \"msFlexFlow\",\n    \"msFlexItemAlign\",\n    \"msFlexLinePack\",\n    \"msFlexNegative\",\n    \"msFlexOrder\",\n    \"msFlexPack\",\n    \"msFlexPositive\",\n    \"msFlexPreferredSize\",\n    \"msFlexWrap\",\n    \"msFlowFrom\",\n    \"msFlowInto\",\n    \"msFontFeatureSettings\",\n    \"msFullscreenElement\",\n    \"msFullscreenEnabled\",\n    \"msGetInputContext\",\n    \"msGetRegionContent\",\n    \"msGetUntransformedBounds\",\n    \"msGraphicsTrustStatus\",\n    \"msGridColumn\",\n    \"msGridColumnAlign\",\n    \"msGridColumnSpan\",\n    \"msGridColumns\",\n    \"msGridRow\",\n    \"msGridRowAlign\",\n    \"msGridRowSpan\",\n    \"msGridRows\",\n    \"msHidden\",\n    \"msHighContrastAdjust\",\n    \"msHyphenateLimitChars\",\n    \"msHyphenateLimitLines\",\n    \"msHyphenateLimitZone\",\n    \"msHyphens\",\n    \"msImageSmoothingEnabled\",\n    \"msImeAlign\",\n    \"msIndexedDB\",\n    \"msInterpolationMode\",\n    \"msIsStaticHTML\",\n    \"msKeySystem\",\n    \"msKeys\",\n    \"msLaunchUri\",\n    \"msLockOrientation\",\n    \"msManipulationViewsEnabled\",\n    \"msMatchMedia\",\n    \"msMatchesSelector\",\n    \"msMaxTouchPoints\",\n    \"msOrientation\",\n    \"msOverflowStyle\",\n    \"msPerspective\",\n    \"msPerspectiveOrigin\",\n    \"msPlayToDisabled\",\n    \"msPlayToPreferredSourceUri\",\n    \"msPlayToPrimary\",\n    \"msPointerEnabled\",\n    \"msRegionOverflow\",\n    \"msReleasePointerCapture\",\n    \"msRequestAnimationFrame\",\n    \"msRequestFullscreen\",\n    \"msSaveBlob\",\n    \"msSaveOrOpenBlob\",\n    \"msScrollChaining\",\n    \"msScrollLimit\",\n    \"msScrollLimitXMax\",\n    \"msScrollLimitXMin\",\n    \"msScrollLimitYMax\",\n    \"msScrollLimitYMin\",\n    \"msScrollRails\",\n    \"msScrollSnapPointsX\",\n    \"msScrollSnapPointsY\",\n    \"msScrollSnapType\",\n    \"msScrollSnapX\",\n    \"msScrollSnapY\",\n    \"msScrollTranslation\",\n    \"msSetImmediate\",\n    \"msSetMediaKeys\",\n    \"msSetPointerCapture\",\n    \"msTextCombineHorizontal\",\n    \"msTextSizeAdjust\",\n    \"msToBlob\",\n    \"msTouchAction\",\n    \"msTouchSelect\",\n    \"msTraceAsyncCallbackCompleted\",\n    \"msTraceAsyncCallbackStarting\",\n    \"msTraceAsyncOperationCompleted\",\n    \"msTraceAsyncOperationStarting\",\n    \"msTransform\",\n    \"msTransformOrigin\",\n    \"msTransformStyle\",\n    \"msTransition\",\n    \"msTransitionDelay\",\n    \"msTransitionDuration\",\n    \"msTransitionProperty\",\n    \"msTransitionTimingFunction\",\n    \"msUnlockOrientation\",\n    \"msUpdateAsyncCallbackRelation\",\n    \"msUserSelect\",\n    \"msVisibilityState\",\n    \"msWrapFlow\",\n    \"msWrapMargin\",\n    \"msWrapThrough\",\n    \"msWriteProfilerMark\",\n    \"msZoom\",\n    \"msZoomTo\",\n    \"mt\",\n    \"mul\",\n    \"multiEntry\",\n    \"multiSelectionObj\",\n    \"multiline\",\n    \"multiple\",\n    \"multiply\",\n    \"multiplySelf\",\n    \"mutableFile\",\n    \"muted\",\n    \"n\",\n    \"name\",\n    \"nameProp\",\n    \"namedItem\",\n    \"namedRecordset\",\n    \"names\",\n    \"namespaceURI\",\n    \"namespaces\",\n    \"naturalHeight\",\n    \"naturalWidth\",\n    \"navigate\",\n    \"navigation\",\n    \"navigationMode\",\n    \"navigationPreload\",\n    \"navigationStart\",\n    \"navigationType\",\n    \"navigator\",\n    \"near\",\n    \"nearestViewportElement\",\n    \"negative\",\n    \"negotiated\",\n    \"netscape\",\n    \"networkState\",\n    \"newScale\",\n    \"newTranslate\",\n    \"newURL\",\n    \"newValue\",\n    \"newValueSpecifiedUnits\",\n    \"newVersion\",\n    \"newhome\",\n    \"next\",\n    \"nextElementSibling\",\n    \"nextHopProtocol\",\n    \"nextNode\",\n    \"nextPage\",\n    \"nextSibling\",\n    \"nickname\",\n    \"noHref\",\n    \"noModule\",\n    \"noResize\",\n    \"noShade\",\n    \"noValidate\",\n    \"noWrap\",\n    \"node\",\n    \"nodeName\",\n    \"nodeType\",\n    \"nodeValue\",\n    \"nonce\",\n    \"normalize\",\n    \"normalizedPathSegList\",\n    \"notationName\",\n    \"notations\",\n    \"note\",\n    \"noteGrainOn\",\n    \"noteOff\",\n    \"noteOn\",\n    \"notify\",\n    \"now\",\n    \"npnNegotiatedProtocol\",\n    \"numOctaves\",\n    \"number\",\n    \"numberOfChannels\",\n    \"numberOfInputs\",\n    \"numberOfItems\",\n    \"numberOfOutputs\",\n    \"numberValue\",\n    \"numberingSystem\",\n    \"numeric\",\n    \"oMatchesSelector\",\n    \"object\",\n    \"object-fit\",\n    \"object-position\",\n    \"objectFit\",\n    \"objectPosition\",\n    \"objectStore\",\n    \"objectStoreNames\",\n    \"observe\",\n    \"observedAttributes\",\n    \"of\",\n    \"offscreenBuffering\",\n    \"offset\",\n    \"offset-anchor\",\n    \"offset-block-end\",\n    \"offset-block-start\",\n    \"offset-distance\",\n    \"offset-inline-end\",\n    \"offset-inline-start\",\n    \"offset-path\",\n    \"offset-rotate\",\n    \"offsetAnchor\",\n    \"offsetBlockEnd\",\n    \"offsetBlockStart\",\n    \"offsetDistance\",\n    \"offsetHeight\",\n    \"offsetInlineEnd\",\n    \"offsetInlineStart\",\n    \"offsetLeft\",\n    \"offsetNode\",\n    \"offsetParent\",\n    \"offsetPath\",\n    \"offsetRotate\",\n    \"offsetTop\",\n    \"offsetWidth\",\n    \"offsetX\",\n    \"offsetY\",\n    \"ok\",\n    \"oldURL\",\n    \"oldValue\",\n    \"oldVersion\",\n    \"olderShadowRoot\",\n    \"onDownloadProgress\",\n    \"onInstallStageChanged\",\n    \"onLine\",\n    \"onabort\",\n    \"onabsolutedeviceorientation\",\n    \"onactivate\",\n    \"onactive\",\n    \"onaddsourcebuffer\",\n    \"onaddstream\",\n    \"onaddtrack\",\n    \"onafterprint\",\n    \"onafterscriptexecute\",\n    \"onafterupdate\",\n    \"onanimationcancel\",\n    \"onanimationend\",\n    \"onanimationiteration\",\n    \"onanimationstart\",\n    \"onappinstalled\",\n    \"onaudioend\",\n    \"onaudioprocess\",\n    \"onaudiostart\",\n    \"onautocomplete\",\n    \"onautocompleteerror\",\n    \"onauxclick\",\n    \"onbeforeactivate\",\n    \"onbeforecopy\",\n    \"onbeforecut\",\n    \"onbeforedeactivate\",\n    \"onbeforeeditfocus\",\n    \"onbeforeinput\",\n    \"onbeforeinstallprompt\",\n    \"onbeforeload\",\n    \"onbeforepaste\",\n    \"onbeforeprint\",\n    \"onbeforescriptexecute\",\n    \"onbeforeunload\",\n    \"onbeforeupdate\",\n    \"onbeforexrselect\",\n    \"onbegin\",\n    \"onblocked\",\n    \"onblur\",\n    \"onbounce\",\n    \"onboundary\",\n    \"onbufferedamountlow\",\n    \"oncached\",\n    \"oncancel\",\n    \"oncandidatewindowhide\",\n    \"oncandidatewindowshow\",\n    \"oncandidatewindowupdate\",\n    \"oncanplay\",\n    \"oncanplaythrough\",\n    \"once\",\n    \"oncellchange\",\n    \"onchange\",\n    \"oncharacteristicvaluechanged\",\n    \"onchargingchange\",\n    \"onchargingtimechange\",\n    \"onchecking\",\n    \"onclick\",\n    \"onclose\",\n    \"onclosing\",\n    \"oncompassneedscalibration\",\n    \"oncomplete\",\n    \"onconnect\",\n    \"onconnecting\",\n    \"onconnectionavailable\",\n    \"onconnectionstatechange\",\n    \"oncontactchange\",\n    \"oncontextmenu\",\n    \"oncontrollerchange\",\n    \"oncontrolselect\",\n    \"oncopy\",\n    \"oncuechange\",\n    \"oncut\",\n    \"ondataavailable\",\n    \"ondatachannel\",\n    \"ondatasetchanged\",\n    \"ondatasetcomplete\",\n    \"ondblclick\",\n    \"ondeactivate\",\n    \"ondevicechange\",\n    \"ondevicelight\",\n    \"ondevicemotion\",\n    \"ondeviceorientation\",\n    \"ondeviceorientationabsolute\",\n    \"ondeviceproximity\",\n    \"ondischargingtimechange\",\n    \"ondisconnect\",\n    \"ondisplay\",\n    \"ondownloading\",\n    \"ondrag\",\n    \"ondragend\",\n    \"ondragenter\",\n    \"ondragexit\",\n    \"ondragleave\",\n    \"ondragover\",\n    \"ondragstart\",\n    \"ondrop\",\n    \"ondurationchange\",\n    \"onemptied\",\n    \"onencrypted\",\n    \"onend\",\n    \"onended\",\n    \"onenter\",\n    \"onenterpictureinpicture\",\n    \"onerror\",\n    \"onerrorupdate\",\n    \"onexit\",\n    \"onfilterchange\",\n    \"onfinish\",\n    \"onfocus\",\n    \"onfocusin\",\n    \"onfocusout\",\n    \"onformdata\",\n    \"onfreeze\",\n    \"onfullscreenchange\",\n    \"onfullscreenerror\",\n    \"ongatheringstatechange\",\n    \"ongattserverdisconnected\",\n    \"ongesturechange\",\n    \"ongestureend\",\n    \"ongesturestart\",\n    \"ongotpointercapture\",\n    \"onhashchange\",\n    \"onhelp\",\n    \"onicecandidate\",\n    \"onicecandidateerror\",\n    \"oniceconnectionstatechange\",\n    \"onicegatheringstatechange\",\n    \"oninactive\",\n    \"oninput\",\n    \"oninputsourceschange\",\n    \"oninvalid\",\n    \"onkeydown\",\n    \"onkeypress\",\n    \"onkeystatuseschange\",\n    \"onkeyup\",\n    \"onlanguagechange\",\n    \"onlayoutcomplete\",\n    \"onleavepictureinpicture\",\n    \"onlevelchange\",\n    \"onload\",\n    \"onloadT\",\n    \"onloadeddata\",\n    \"onloadedmetadata\",\n    \"onloadend\",\n    \"onloading\",\n    \"onloadingdone\",\n    \"onloadingerror\",\n    \"onloadstart\",\n    \"onlosecapture\",\n    \"onlostpointercapture\",\n    \"only\",\n    \"onmark\",\n    \"onmessage\",\n    \"onmessageerror\",\n    \"onmidimessage\",\n    \"onmousedown\",\n    \"onmouseenter\",\n    \"onmouseleave\",\n    \"onmousemove\",\n    \"onmouseout\",\n    \"onmouseover\",\n    \"onmouseup\",\n    \"onmousewheel\",\n    \"onmove\",\n    \"onmoveend\",\n    \"onmovestart\",\n    \"onmozfullscreenchange\",\n    \"onmozfullscreenerror\",\n    \"onmozorientationchange\",\n    \"onmozpointerlockchange\",\n    \"onmozpointerlockerror\",\n    \"onmscontentzoom\",\n    \"onmsfullscreenchange\",\n    \"onmsfullscreenerror\",\n    \"onmsgesturechange\",\n    \"onmsgesturedoubletap\",\n    \"onmsgestureend\",\n    \"onmsgesturehold\",\n    \"onmsgesturestart\",\n    \"onmsgesturetap\",\n    \"onmsgotpointercapture\",\n    \"onmsinertiastart\",\n    \"onmslostpointercapture\",\n    \"onmsmanipulationstatechanged\",\n    \"onmsneedkey\",\n    \"onmsorientationchange\",\n    \"onmspointercancel\",\n    \"onmspointerdown\",\n    \"onmspointerenter\",\n    \"onmspointerhover\",\n    \"onmspointerleave\",\n    \"onmspointermove\",\n    \"onmspointerout\",\n    \"onmspointerover\",\n    \"onmspointerup\",\n    \"onmssitemodejumplistitemremoved\",\n    \"onmsthumbnailclick\",\n    \"onmute\",\n    \"onnegotiationneeded\",\n    \"onnomatch\",\n    \"onnoupdate\",\n    \"onobsolete\",\n    \"onoffline\",\n    \"ononline\",\n    \"onopen\",\n    \"onorientationchange\",\n    \"onoverconstrained\",\n    \"onpage\",\n    \"onpagechange\",\n    \"onpagehide\",\n    \"onpageshow\",\n    \"onpaste\",\n    \"onpause\",\n    \"onpayerdetailchange\",\n    \"onpaymentmethodchange\",\n    \"onplay\",\n    \"onplaying\",\n    \"onpluginstreamstart\",\n    \"onpointercancel\",\n    \"onpointerdown\",\n    \"onpointerenter\",\n    \"onpointerleave\",\n    \"onpointerlockchange\",\n    \"onpointerlockerror\",\n    \"onpointermove\",\n    \"onpointerout\",\n    \"onpointerover\",\n    \"onpointerrawupdate\",\n    \"onpointerup\",\n    \"onpopstate\",\n    \"onprocessorerror\",\n    \"onprogress\",\n    \"onpropertychange\",\n    \"onratechange\",\n    \"onreading\",\n    \"onreadystatechange\",\n    \"onrejectionhandled\",\n    \"onrelease\",\n    \"onremove\",\n    \"onremovesourcebuffer\",\n    \"onremovestream\",\n    \"onremovetrack\",\n    \"onrepeat\",\n    \"onreset\",\n    \"onresize\",\n    \"onresizeend\",\n    \"onresizestart\",\n    \"onresourcetimingbufferfull\",\n    \"onresult\",\n    \"onresume\",\n    \"onrowenter\",\n    \"onrowexit\",\n    \"onrowsdelete\",\n    \"onrowsinserted\",\n    \"onscroll\",\n    \"onsearch\",\n    \"onsecuritypolicyviolation\",\n    \"onseeked\",\n    \"onseeking\",\n    \"onselect\",\n    \"onselectedcandidatepairchange\",\n    \"onselectend\",\n    \"onselectionchange\",\n    \"onselectstart\",\n    \"onshippingaddresschange\",\n    \"onshippingoptionchange\",\n    \"onshow\",\n    \"onsignalingstatechange\",\n    \"onsoundend\",\n    \"onsoundstart\",\n    \"onsourceclose\",\n    \"onsourceclosed\",\n    \"onsourceended\",\n    \"onsourceopen\",\n    \"onspeechend\",\n    \"onspeechstart\",\n    \"onsqueeze\",\n    \"onsqueezeend\",\n    \"onsqueezestart\",\n    \"onstalled\",\n    \"onstart\",\n    \"onstatechange\",\n    \"onstop\",\n    \"onstorage\",\n    \"onstoragecommit\",\n    \"onsubmit\",\n    \"onsuccess\",\n    \"onsuspend\",\n    \"onterminate\",\n    \"ontextinput\",\n    \"ontimeout\",\n    \"ontimeupdate\",\n    \"ontoggle\",\n    \"ontonechange\",\n    \"ontouchcancel\",\n    \"ontouchend\",\n    \"ontouchmove\",\n    \"ontouchstart\",\n    \"ontrack\",\n    \"ontransitioncancel\",\n    \"ontransitionend\",\n    \"ontransitionrun\",\n    \"ontransitionstart\",\n    \"onunhandledrejection\",\n    \"onunload\",\n    \"onunmute\",\n    \"onupdate\",\n    \"onupdateend\",\n    \"onupdatefound\",\n    \"onupdateready\",\n    \"onupdatestart\",\n    \"onupgradeneeded\",\n    \"onuserproximity\",\n    \"onversionchange\",\n    \"onvisibilitychange\",\n    \"onvoiceschanged\",\n    \"onvolumechange\",\n    \"onvrdisplayactivate\",\n    \"onvrdisplayconnect\",\n    \"onvrdisplaydeactivate\",\n    \"onvrdisplaydisconnect\",\n    \"onvrdisplaypresentchange\",\n    \"onwaiting\",\n    \"onwaitingforkey\",\n    \"onwarning\",\n    \"onwebkitanimationend\",\n    \"onwebkitanimationiteration\",\n    \"onwebkitanimationstart\",\n    \"onwebkitcurrentplaybacktargetiswirelesschanged\",\n    \"onwebkitfullscreenchange\",\n    \"onwebkitfullscreenerror\",\n    \"onwebkitkeyadded\",\n    \"onwebkitkeyerror\",\n    \"onwebkitkeymessage\",\n    \"onwebkitmouseforcechanged\",\n    \"onwebkitmouseforcedown\",\n    \"onwebkitmouseforceup\",\n    \"onwebkitmouseforcewillbegin\",\n    \"onwebkitneedkey\",\n    \"onwebkitorientationchange\",\n    \"onwebkitplaybacktargetavailabilitychanged\",\n    \"onwebkitpointerlockchange\",\n    \"onwebkitpointerlockerror\",\n    \"onwebkitresourcetimingbufferfull\",\n    \"onwebkittransitionend\",\n    \"onwheel\",\n    \"onzoom\",\n    \"opacity\",\n    \"open\",\n    \"openCursor\",\n    \"openDatabase\",\n    \"openKeyCursor\",\n    \"opened\",\n    \"opener\",\n    \"opera\",\n    \"operationType\",\n    \"operator\",\n    \"opr\",\n    \"opsProfile\",\n    \"optimum\",\n    \"options\",\n    \"or\",\n    \"order\",\n    \"orderX\",\n    \"orderY\",\n    \"ordered\",\n    \"org\",\n    \"organization\",\n    \"orient\",\n    \"orientAngle\",\n    \"orientType\",\n    \"orientation\",\n    \"orientationX\",\n    \"orientationY\",\n    \"orientationZ\",\n    \"origin\",\n    \"originalPolicy\",\n    \"originalTarget\",\n    \"orphans\",\n    \"oscpu\",\n    \"outcome\",\n    \"outerHTML\",\n    \"outerHeight\",\n    \"outerText\",\n    \"outerWidth\",\n    \"outline\",\n    \"outline-color\",\n    \"outline-offset\",\n    \"outline-style\",\n    \"outline-width\",\n    \"outlineColor\",\n    \"outlineOffset\",\n    \"outlineStyle\",\n    \"outlineWidth\",\n    \"outputBuffer\",\n    \"outputLatency\",\n    \"outputs\",\n    \"overflow\",\n    \"overflow-anchor\",\n    \"overflow-block\",\n    \"overflow-inline\",\n    \"overflow-wrap\",\n    \"overflow-x\",\n    \"overflow-y\",\n    \"overflowAnchor\",\n    \"overflowBlock\",\n    \"overflowInline\",\n    \"overflowWrap\",\n    \"overflowX\",\n    \"overflowY\",\n    \"overrideMimeType\",\n    \"oversample\",\n    \"overscroll-behavior\",\n    \"overscroll-behavior-block\",\n    \"overscroll-behavior-inline\",\n    \"overscroll-behavior-x\",\n    \"overscroll-behavior-y\",\n    \"overscrollBehavior\",\n    \"overscrollBehaviorBlock\",\n    \"overscrollBehaviorInline\",\n    \"overscrollBehaviorX\",\n    \"overscrollBehaviorY\",\n    \"ownKeys\",\n    \"ownerDocument\",\n    \"ownerElement\",\n    \"ownerNode\",\n    \"ownerRule\",\n    \"ownerSVGElement\",\n    \"owningElement\",\n    \"p1\",\n    \"p2\",\n    \"p3\",\n    \"p4\",\n    \"packetSize\",\n    \"packets\",\n    \"pad\",\n    \"padEnd\",\n    \"padStart\",\n    \"padding\",\n    \"padding-block\",\n    \"padding-block-end\",\n    \"padding-block-start\",\n    \"padding-bottom\",\n    \"padding-inline\",\n    \"padding-inline-end\",\n    \"padding-inline-start\",\n    \"padding-left\",\n    \"padding-right\",\n    \"padding-top\",\n    \"paddingBlock\",\n    \"paddingBlockEnd\",\n    \"paddingBlockStart\",\n    \"paddingBottom\",\n    \"paddingInline\",\n    \"paddingInlineEnd\",\n    \"paddingInlineStart\",\n    \"paddingLeft\",\n    \"paddingRight\",\n    \"paddingTop\",\n    \"page\",\n    \"page-break-after\",\n    \"page-break-before\",\n    \"page-break-inside\",\n    \"pageBreakAfter\",\n    \"pageBreakBefore\",\n    \"pageBreakInside\",\n    \"pageCount\",\n    \"pageLeft\",\n    \"pageT\",\n    \"pageTop\",\n    \"pageX\",\n    \"pageXOffset\",\n    \"pageY\",\n    \"pageYOffset\",\n    \"pages\",\n    \"paint-order\",\n    \"paintOrder\",\n    \"paintRequests\",\n    \"paintType\",\n    \"paintWorklet\",\n    \"palette\",\n    \"pan\",\n    \"panningModel\",\n    \"parameters\",\n    \"parent\",\n    \"parentElement\",\n    \"parentNode\",\n    \"parentRule\",\n    \"parentStyleSheet\",\n    \"parentTextEdit\",\n    \"parentWindow\",\n    \"parse\",\n    \"parseAll\",\n    \"parseFloat\",\n    \"parseFromString\",\n    \"parseInt\",\n    \"part\",\n    \"participants\",\n    \"passive\",\n    \"password\",\n    \"pasteHTML\",\n    \"path\",\n    \"pathLength\",\n    \"pathSegList\",\n    \"pathSegType\",\n    \"pathSegTypeAsLetter\",\n    \"pathname\",\n    \"pattern\",\n    \"patternContentUnits\",\n    \"patternMismatch\",\n    \"patternTransform\",\n    \"patternUnits\",\n    \"pause\",\n    \"pauseAnimations\",\n    \"pauseOnExit\",\n    \"pauseTransformFeedback\",\n    \"paused\",\n    \"payerEmail\",\n    \"payerName\",\n    \"payerPhone\",\n    \"paymentManager\",\n    \"pc\",\n    \"peerIdentity\",\n    \"pending\",\n    \"pendingLocalDescription\",\n    \"pendingRemoteDescription\",\n    \"percent\",\n    \"performance\",\n    \"periodicSync\",\n    \"permission\",\n    \"permissionState\",\n    \"permissions\",\n    \"persist\",\n    \"persisted\",\n    \"personalbar\",\n    \"perspective\",\n    \"perspective-origin\",\n    \"perspectiveOrigin\",\n    \"perspectiveOriginX\",\n    \"perspectiveOriginY\",\n    \"phone\",\n    \"phoneticFamilyName\",\n    \"phoneticGivenName\",\n    \"photo\",\n    \"pictureInPictureElement\",\n    \"pictureInPictureEnabled\",\n    \"pictureInPictureWindow\",\n    \"ping\",\n    \"pipeThrough\",\n    \"pipeTo\",\n    \"pitch\",\n    \"pixelBottom\",\n    \"pixelDepth\",\n    \"pixelHeight\",\n    \"pixelLeft\",\n    \"pixelRight\",\n    \"pixelStorei\",\n    \"pixelTop\",\n    \"pixelUnitToMillimeterX\",\n    \"pixelUnitToMillimeterY\",\n    \"pixelWidth\",\n    \"place-content\",\n    \"place-items\",\n    \"place-self\",\n    \"placeContent\",\n    \"placeItems\",\n    \"placeSelf\",\n    \"placeholder\",\n    \"platform\",\n    \"platforms\",\n    \"play\",\n    \"playEffect\",\n    \"playState\",\n    \"playbackRate\",\n    \"playbackState\",\n    \"playbackTime\",\n    \"played\",\n    \"playoutDelayHint\",\n    \"playsInline\",\n    \"plugins\",\n    \"pluginspage\",\n    \"pname\",\n    \"pointer-events\",\n    \"pointerBeforeReferenceNode\",\n    \"pointerEnabled\",\n    \"pointerEvents\",\n    \"pointerId\",\n    \"pointerLockElement\",\n    \"pointerType\",\n    \"points\",\n    \"pointsAtX\",\n    \"pointsAtY\",\n    \"pointsAtZ\",\n    \"polygonOffset\",\n    \"pop\",\n    \"populateMatrix\",\n    \"popupWindowFeatures\",\n    \"popupWindowName\",\n    \"popupWindowURI\",\n    \"port\",\n    \"port1\",\n    \"port2\",\n    \"ports\",\n    \"posBottom\",\n    \"posHeight\",\n    \"posLeft\",\n    \"posRight\",\n    \"posTop\",\n    \"posWidth\",\n    \"pose\",\n    \"position\",\n    \"positionAlign\",\n    \"positionX\",\n    \"positionY\",\n    \"positionZ\",\n    \"postError\",\n    \"postMessage\",\n    \"postalCode\",\n    \"poster\",\n    \"pow\",\n    \"powerEfficient\",\n    \"powerOff\",\n    \"preMultiplySelf\",\n    \"precision\",\n    \"preferredStyleSheetSet\",\n    \"preferredStylesheetSet\",\n    \"prefix\",\n    \"preload\",\n    \"prepend\",\n    \"presentation\",\n    \"preserveAlpha\",\n    \"preserveAspectRatio\",\n    \"preserveAspectRatioString\",\n    \"pressed\",\n    \"pressure\",\n    \"prevValue\",\n    \"preventDefault\",\n    \"preventExtensions\",\n    \"preventSilentAccess\",\n    \"previousElementSibling\",\n    \"previousNode\",\n    \"previousPage\",\n    \"previousRect\",\n    \"previousScale\",\n    \"previousSibling\",\n    \"previousTranslate\",\n    \"primaryKey\",\n    \"primitiveType\",\n    \"primitiveUnits\",\n    \"principals\",\n    \"print\",\n    \"priority\",\n    \"privateKey\",\n    \"probablySupportsContext\",\n    \"process\",\n    \"processIceMessage\",\n    \"processingEnd\",\n    \"processingStart\",\n    \"product\",\n    \"productId\",\n    \"productName\",\n    \"productSub\",\n    \"profile\",\n    \"profileEnd\",\n    \"profiles\",\n    \"projectionMatrix\",\n    \"promise\",\n    \"prompt\",\n    \"properties\",\n    \"propertyIsEnumerable\",\n    \"propertyName\",\n    \"protocol\",\n    \"protocolLong\",\n    \"prototype\",\n    \"provider\",\n    \"pseudoClass\",\n    \"pseudoElement\",\n    \"pt\",\n    \"publicId\",\n    \"publicKey\",\n    \"published\",\n    \"pulse\",\n    \"push\",\n    \"pushManager\",\n    \"pushNotification\",\n    \"pushState\",\n    \"put\",\n    \"putImageData\",\n    \"px\",\n    \"quadraticCurveTo\",\n    \"qualifier\",\n    \"quaternion\",\n    \"query\",\n    \"queryCommandEnabled\",\n    \"queryCommandIndeterm\",\n    \"queryCommandState\",\n    \"queryCommandSupported\",\n    \"queryCommandText\",\n    \"queryCommandValue\",\n    \"querySelector\",\n    \"querySelectorAll\",\n    \"queryUsageAndQuota\",\n    \"queueMicrotask\",\n    \"quote\",\n    \"quotes\",\n    \"r\",\n    \"r1\",\n    \"r2\",\n    \"race\",\n    \"rad\",\n    \"radiogroup\",\n    \"radiusX\",\n    \"radiusY\",\n    \"random\",\n    \"range\",\n    \"rangeCount\",\n    \"rangeMax\",\n    \"rangeMin\",\n    \"rangeOffset\",\n    \"rangeOverflow\",\n    \"rangeParent\",\n    \"rangeUnderflow\",\n    \"rate\",\n    \"ratio\",\n    \"raw\",\n    \"rawId\",\n    \"read\",\n    \"readAsArrayBuffer\",\n    \"readAsBinaryString\",\n    \"readAsBlob\",\n    \"readAsDataURL\",\n    \"readAsText\",\n    \"readBuffer\",\n    \"readEntries\",\n    \"readOnly\",\n    \"readPixels\",\n    \"readReportRequested\",\n    \"readText\",\n    \"readTransaction\",\n    \"readValue\",\n    \"readable\",\n    \"ready\",\n    \"readyState\",\n    \"reason\",\n    \"reboot\",\n    \"receivedAlert\",\n    \"receivedTime\",\n    \"receiver\",\n    \"receivers\",\n    \"recipient\",\n    \"reconnect\",\n    \"record\",\n    \"recordEnd\",\n    \"recordNumber\",\n    \"recordsAvailable\",\n    \"recordset\",\n    \"rect\",\n    \"red\",\n    \"redEyeReduction\",\n    \"redirect\",\n    \"redirectCount\",\n    \"redirectEnd\",\n    \"redirectStart\",\n    \"redirected\",\n    \"reduce\",\n    \"reduceRight\",\n    \"reduction\",\n    \"refDistance\",\n    \"refX\",\n    \"refY\",\n    \"referenceNode\",\n    \"referenceSpace\",\n    \"referrer\",\n    \"referrerPolicy\",\n    \"refresh\",\n    \"region\",\n    \"regionAnchorX\",\n    \"regionAnchorY\",\n    \"regionId\",\n    \"regions\",\n    \"register\",\n    \"registerContentHandler\",\n    \"registerElement\",\n    \"registerProperty\",\n    \"registerProtocolHandler\",\n    \"reject\",\n    \"rel\",\n    \"relList\",\n    \"relatedAddress\",\n    \"relatedNode\",\n    \"relatedPort\",\n    \"relatedTarget\",\n    \"release\",\n    \"releaseCapture\",\n    \"releaseEvents\",\n    \"releaseInterface\",\n    \"releaseLock\",\n    \"releasePointerCapture\",\n    \"releaseShaderCompiler\",\n    \"reliable\",\n    \"reliableWrite\",\n    \"reload\",\n    \"rem\",\n    \"remainingSpace\",\n    \"remote\",\n    \"remoteDescription\",\n    \"remove\",\n    \"removeAllRanges\",\n    \"removeAttribute\",\n    \"removeAttributeNS\",\n    \"removeAttributeNode\",\n    \"removeBehavior\",\n    \"removeChild\",\n    \"removeCue\",\n    \"removeEventListener\",\n    \"removeFilter\",\n    \"removeImport\",\n    \"removeItem\",\n    \"removeListener\",\n    \"removeNamedItem\",\n    \"removeNamedItemNS\",\n    \"removeNode\",\n    \"removeParameter\",\n    \"removeProperty\",\n    \"removeRange\",\n    \"removeRegion\",\n    \"removeRule\",\n    \"removeRules\",\n    \"removeSiteSpecificTrackingException\",\n    \"removeSourceBuffer\",\n    \"removeStream\",\n    \"removeTrack\",\n    \"removeVariable\",\n    \"removeWakeLockListener\",\n    \"removeWebWideTrackingException\",\n    \"removed\",\n    \"removedNodes\",\n    \"renderHeight\",\n    \"renderState\",\n    \"renderTime\",\n    \"renderWidth\",\n    \"renderbufferStorage\",\n    \"renderbufferStorageMultisample\",\n    \"renderedBuffer\",\n    \"renderingMode\",\n    \"renotify\",\n    \"repeat\",\n    \"replace\",\n    \"replaceAdjacentText\",\n    \"replaceAll\",\n    \"replaceChild\",\n    \"replaceChildren\",\n    \"replaceData\",\n    \"replaceId\",\n    \"replaceItem\",\n    \"replaceNode\",\n    \"replaceState\",\n    \"replaceSync\",\n    \"replaceTrack\",\n    \"replaceWholeText\",\n    \"replaceWith\",\n    \"reportValidity\",\n    \"request\",\n    \"requestAnimationFrame\",\n    \"requestAutocomplete\",\n    \"requestData\",\n    \"requestDevice\",\n    \"requestFrame\",\n    \"requestFullscreen\",\n    \"requestHitTestSource\",\n    \"requestHitTestSourceForTransientInput\",\n    \"requestId\",\n    \"requestIdleCallback\",\n    \"requestMIDIAccess\",\n    \"requestMediaKeySystemAccess\",\n    \"requestPermission\",\n    \"requestPictureInPicture\",\n    \"requestPointerLock\",\n    \"requestPresent\",\n    \"requestQuota\",\n    \"requestReferenceSpace\",\n    \"requestSession\",\n    \"requestStart\",\n    \"requestStorageAccess\",\n    \"requestSubmit\",\n    \"requestTime\",\n    \"requestVideoFrameCallback\",\n    \"requestedLocale\",\n    \"requestingWindow\",\n    \"requireInteraction\",\n    \"required\",\n    \"requiredExtensions\",\n    \"requiredFeatures\",\n    \"reset\",\n    \"resetPose\",\n    \"resetTransform\",\n    \"resize\",\n    \"resizeBy\",\n    \"resizeTo\",\n    \"resolve\",\n    \"resolved\",\n    \"resolvedOptions\",\n    \"resource-history\",\n    \"resourcesFramesExpanded\",\n    \"response\",\n    \"responseBody\",\n    \"responseEnd\",\n    \"responseReady\",\n    \"responseStart\",\n    \"responseText\",\n    \"responseType\",\n    \"responseURL\",\n    \"responseXML\",\n    \"restartIce\",\n    \"restore\",\n    \"result\",\n    \"resultIndex\",\n    \"resultType\",\n    \"results\",\n    \"resume\",\n    \"resumeTransformFeedback\",\n    \"retry\",\n    \"returnValue\",\n    \"rev\",\n    \"reverse\",\n    \"reversed\",\n    \"revocable\",\n    \"revokeObjectURL\",\n    \"rgbColor\",\n    \"right\",\n    \"rightContext\",\n    \"rightDegrees\",\n    \"rightMargin\",\n    \"rightProjectionMatrix\",\n    \"rightViewMatrix\",\n    \"role\",\n    \"rolloffFactor\",\n    \"root\",\n    \"rootBounds\",\n    \"rootElement\",\n    \"rootMargin\",\n    \"rotate\",\n    \"rotateAxisAngle\",\n    \"rotateAxisAngleSelf\",\n    \"rotateFromVector\",\n    \"rotateFromVectorSelf\",\n    \"rotateSelf\",\n    \"rotation\",\n    \"rotationAngle\",\n    \"rotationRate\",\n    \"round\",\n    \"row-gap\",\n    \"rowGap\",\n    \"rowIndex\",\n    \"rowSpan\",\n    \"rows\",\n    \"rowsAffected\",\n    \"rtcpTransport\",\n    \"rtt\",\n    \"ruby-align\",\n    \"ruby-position\",\n    \"rubyAlign\",\n    \"rubyOverhang\",\n    \"rubyPosition\",\n    \"rules\",\n    \"runningState\",\n    \"runtime\",\n    \"runtimeStyle\",\n    \"rx\",\n    \"ry\",\n    \"s\",\n    \"safari\",\n    \"sample\",\n    \"sampleCoverage\",\n    \"sampleRate\",\n    \"samplerParameterf\",\n    \"samplerParameteri\",\n    \"sandbox\",\n    \"save\",\n    \"saveData\",\n    \"scale\",\n    \"scale3d\",\n    \"scale3dSelf\",\n    \"scaleNonUniform\",\n    \"scaleNonUniformSelf\",\n    \"scaleSelf\",\n    \"scheme\",\n    \"scissor\",\n    \"scope\",\n    \"scopeName\",\n    \"scoped\",\n    \"screen\",\n    \"screenBrightness\",\n    \"screenEnabled\",\n    \"screenLeft\",\n    \"screenPixelToMillimeterX\",\n    \"screenPixelToMillimeterY\",\n    \"screenTop\",\n    \"screenX\",\n    \"screenY\",\n    \"script\",\n    \"scriptURL\",\n    \"scripts\",\n    \"scroll\",\n    \"scroll-behavior\",\n    \"scroll-margin\",\n    \"scroll-margin-block\",\n    \"scroll-margin-block-end\",\n    \"scroll-margin-block-start\",\n    \"scroll-margin-bottom\",\n    \"scroll-margin-inline\",\n    \"scroll-margin-inline-end\",\n    \"scroll-margin-inline-start\",\n    \"scroll-margin-left\",\n    \"scroll-margin-right\",\n    \"scroll-margin-top\",\n    \"scroll-padding\",\n    \"scroll-padding-block\",\n    \"scroll-padding-block-end\",\n    \"scroll-padding-block-start\",\n    \"scroll-padding-bottom\",\n    \"scroll-padding-inline\",\n    \"scroll-padding-inline-end\",\n    \"scroll-padding-inline-start\",\n    \"scroll-padding-left\",\n    \"scroll-padding-right\",\n    \"scroll-padding-top\",\n    \"scroll-snap-align\",\n    \"scroll-snap-coordinate\",\n    \"scroll-snap-destination\",\n    \"scroll-snap-points-x\",\n    \"scroll-snap-points-y\",\n    \"scroll-snap-type\",\n    \"scroll-snap-type-x\",\n    \"scroll-snap-type-y\",\n    \"scrollAmount\",\n    \"scrollBehavior\",\n    \"scrollBy\",\n    \"scrollByLines\",\n    \"scrollByPages\",\n    \"scrollDelay\",\n    \"scrollHeight\",\n    \"scrollIntoView\",\n    \"scrollIntoViewIfNeeded\",\n    \"scrollLeft\",\n    \"scrollLeftMax\",\n    \"scrollMargin\",\n    \"scrollMarginBlock\",\n    \"scrollMarginBlockEnd\",\n    \"scrollMarginBlockStart\",\n    \"scrollMarginBottom\",\n    \"scrollMarginInline\",\n    \"scrollMarginInlineEnd\",\n    \"scrollMarginInlineStart\",\n    \"scrollMarginLeft\",\n    \"scrollMarginRight\",\n    \"scrollMarginTop\",\n    \"scrollMaxX\",\n    \"scrollMaxY\",\n    \"scrollPadding\",\n    \"scrollPaddingBlock\",\n    \"scrollPaddingBlockEnd\",\n    \"scrollPaddingBlockStart\",\n    \"scrollPaddingBottom\",\n    \"scrollPaddingInline\",\n    \"scrollPaddingInlineEnd\",\n    \"scrollPaddingInlineStart\",\n    \"scrollPaddingLeft\",\n    \"scrollPaddingRight\",\n    \"scrollPaddingTop\",\n    \"scrollRestoration\",\n    \"scrollSnapAlign\",\n    \"scrollSnapCoordinate\",\n    \"scrollSnapDestination\",\n    \"scrollSnapMargin\",\n    \"scrollSnapMarginBottom\",\n    \"scrollSnapMarginLeft\",\n    \"scrollSnapMarginRight\",\n    \"scrollSnapMarginTop\",\n    \"scrollSnapPointsX\",\n    \"scrollSnapPointsY\",\n    \"scrollSnapStop\",\n    \"scrollSnapType\",\n    \"scrollSnapTypeX\",\n    \"scrollSnapTypeY\",\n    \"scrollTo\",\n    \"scrollTop\",\n    \"scrollTopMax\",\n    \"scrollWidth\",\n    \"scrollX\",\n    \"scrollY\",\n    \"scrollbar-color\",\n    \"scrollbar-width\",\n    \"scrollbar3dLightColor\",\n    \"scrollbarArrowColor\",\n    \"scrollbarBaseColor\",\n    \"scrollbarColor\",\n    \"scrollbarDarkShadowColor\",\n    \"scrollbarFaceColor\",\n    \"scrollbarHighlightColor\",\n    \"scrollbarShadowColor\",\n    \"scrollbarTrackColor\",\n    \"scrollbarWidth\",\n    \"scrollbars\",\n    \"scrolling\",\n    \"scrollingElement\",\n    \"sctp\",\n    \"sctpCauseCode\",\n    \"sdp\",\n    \"sdpLineNumber\",\n    \"sdpMLineIndex\",\n    \"sdpMid\",\n    \"seal\",\n    \"search\",\n    \"searchBox\",\n    \"searchBoxJavaBridge_\",\n    \"searchParams\",\n    \"second\",\n    \"sectionRowIndex\",\n    \"secureConnectionStart\",\n    \"security\",\n    \"seed\",\n    \"seekToNextFrame\",\n    \"seekable\",\n    \"seeking\",\n    \"select\",\n    \"selectAllChildren\",\n    \"selectAlternateInterface\",\n    \"selectConfiguration\",\n    \"selectNode\",\n    \"selectNodeContents\",\n    \"selectNodes\",\n    \"selectSingleNode\",\n    \"selectSubString\",\n    \"selected\",\n    \"selectedIndex\",\n    \"selectedOption\",\n    \"selectedOptions\",\n    \"selectedStyleSheetSet\",\n    \"selectedStylesheetSet\",\n    \"selection\",\n    \"selectionDirection\",\n    \"selectionEnd\",\n    \"selectionStart\",\n    \"selector\",\n    \"selectorText\",\n    \"self\",\n    \"send\",\n    \"sendAsBinary\",\n    \"sendBeacon\",\n    \"sendMessage\",\n    \"sender\",\n    \"sensitivity\",\n    \"sentAlert\",\n    \"sentTimestamp\",\n    \"separator\",\n    \"serialNumber\",\n    \"serializeToString\",\n    \"serverTiming\",\n    \"service\",\n    \"serviceWorker\",\n    \"session\",\n    \"sessionId\",\n    \"sessionStorage\",\n    \"set\",\n    \"setActionHandler\",\n    \"setActive\",\n    \"setAlpha\",\n    \"setAppBadge\",\n    \"setAttribute\",\n    \"setAttributeNS\",\n    \"setAttributeNode\",\n    \"setAttributeNodeNS\",\n    \"setBaseAndExtent\",\n    \"setBigInt64\",\n    \"setBigUint64\",\n    \"setBingCurrentSearchDefault\",\n    \"setCapture\",\n    \"setCodecPreferences\",\n    \"setColor\",\n    \"setCompositeOperation\",\n    \"setConfiguration\",\n    \"setCurrentTime\",\n    \"setCustomValidity\",\n    \"setData\",\n    \"setDate\",\n    \"setDirection\",\n    \"setDragImage\",\n    \"setEnd\",\n    \"setEndAfter\",\n    \"setEndBefore\",\n    \"setEndPoint\",\n    \"setFillColor\",\n    \"setFilterRes\",\n    \"setFloat32\",\n    \"setFloat64\",\n    \"setFloatValue\",\n    \"setFormValue\",\n    \"setFullYear\",\n    \"setHeaderValue\",\n    \"setHours\",\n    \"setIdentityProvider\",\n    \"setImmediate\",\n    \"setInt16\",\n    \"setInt32\",\n    \"setInt8\",\n    \"setInterval\",\n    \"setItem\",\n    \"setKeyframes\",\n    \"setLineCap\",\n    \"setLineDash\",\n    \"setLineJoin\",\n    \"setLineWidth\",\n    \"setLiveSeekableRange\",\n    \"setLocalDescription\",\n    \"setMatrix\",\n    \"setMatrixValue\",\n    \"setMediaKeys\",\n    \"setMilliseconds\",\n    \"setMinutes\",\n    \"setMiterLimit\",\n    \"setMonth\",\n    \"setNamedItem\",\n    \"setNamedItemNS\",\n    \"setNonUserCodeExceptions\",\n    \"setOrientToAngle\",\n    \"setOrientToAuto\",\n    \"setOrientation\",\n    \"setOverrideHistoryNavigationMode\",\n    \"setPaint\",\n    \"setParameter\",\n    \"setParameters\",\n    \"setPeriodicWave\",\n    \"setPointerCapture\",\n    \"setPosition\",\n    \"setPositionState\",\n    \"setPreference\",\n    \"setProperty\",\n    \"setPrototypeOf\",\n    \"setRGBColor\",\n    \"setRGBColorICCColor\",\n    \"setRadius\",\n    \"setRangeText\",\n    \"setRemoteDescription\",\n    \"setRequestHeader\",\n    \"setResizable\",\n    \"setResourceTimingBufferSize\",\n    \"setRotate\",\n    \"setScale\",\n    \"setSeconds\",\n    \"setSelectionRange\",\n    \"setServerCertificate\",\n    \"setShadow\",\n    \"setSinkId\",\n    \"setSkewX\",\n    \"setSkewY\",\n    \"setStart\",\n    \"setStartAfter\",\n    \"setStartBefore\",\n    \"setStdDeviation\",\n    \"setStreams\",\n    \"setStringValue\",\n    \"setStrokeColor\",\n    \"setSuggestResult\",\n    \"setTargetAtTime\",\n    \"setTargetValueAtTime\",\n    \"setTime\",\n    \"setTimeout\",\n    \"setTransform\",\n    \"setTranslate\",\n    \"setUTCDate\",\n    \"setUTCFullYear\",\n    \"setUTCHours\",\n    \"setUTCMilliseconds\",\n    \"setUTCMinutes\",\n    \"setUTCMonth\",\n    \"setUTCSeconds\",\n    \"setUint16\",\n    \"setUint32\",\n    \"setUint8\",\n    \"setUri\",\n    \"setValidity\",\n    \"setValueAtTime\",\n    \"setValueCurveAtTime\",\n    \"setVariable\",\n    \"setVelocity\",\n    \"setVersion\",\n    \"setYear\",\n    \"settingName\",\n    \"settingValue\",\n    \"sex\",\n    \"shaderSource\",\n    \"shadowBlur\",\n    \"shadowColor\",\n    \"shadowOffsetX\",\n    \"shadowOffsetY\",\n    \"shadowRoot\",\n    \"shape\",\n    \"shape-image-threshold\",\n    \"shape-margin\",\n    \"shape-outside\",\n    \"shape-rendering\",\n    \"shapeImageThreshold\",\n    \"shapeMargin\",\n    \"shapeOutside\",\n    \"shapeRendering\",\n    \"sheet\",\n    \"shift\",\n    \"shiftKey\",\n    \"shiftLeft\",\n    \"shippingAddress\",\n    \"shippingOption\",\n    \"shippingType\",\n    \"show\",\n    \"showHelp\",\n    \"showModal\",\n    \"showModalDialog\",\n    \"showModelessDialog\",\n    \"showNotification\",\n    \"sidebar\",\n    \"sign\",\n    \"signal\",\n    \"signalingState\",\n    \"signature\",\n    \"silent\",\n    \"sin\",\n    \"singleNodeValue\",\n    \"sinh\",\n    \"sinkId\",\n    \"sittingToStandingTransform\",\n    \"size\",\n    \"sizeToContent\",\n    \"sizeX\",\n    \"sizeZ\",\n    \"sizes\",\n    \"skewX\",\n    \"skewXSelf\",\n    \"skewY\",\n    \"skewYSelf\",\n    \"slice\",\n    \"slope\",\n    \"slot\",\n    \"small\",\n    \"smil\",\n    \"smooth\",\n    \"smoothingTimeConstant\",\n    \"snapToLines\",\n    \"snapshotItem\",\n    \"snapshotLength\",\n    \"some\",\n    \"sort\",\n    \"sortingCode\",\n    \"source\",\n    \"sourceBuffer\",\n    \"sourceBuffers\",\n    \"sourceCapabilities\",\n    \"sourceFile\",\n    \"sourceIndex\",\n    \"sourceURL\",\n    \"sources\",\n    \"spacing\",\n    \"span\",\n    \"speak\",\n    \"speakAs\",\n    \"speaking\",\n    \"species\",\n    \"specified\",\n    \"specularConstant\",\n    \"specularExponent\",\n    \"speechSynthesis\",\n    \"speed\",\n    \"speedOfSound\",\n    \"spellcheck\",\n    \"splice\",\n    \"split\",\n    \"splitText\",\n    \"spreadMethod\",\n    \"sqrt\",\n    \"src\",\n    \"srcElement\",\n    \"srcFilter\",\n    \"srcObject\",\n    \"srcUrn\",\n    \"srcdoc\",\n    \"srclang\",\n    \"srcset\",\n    \"stack\",\n    \"stackTraceLimit\",\n    \"stacktrace\",\n    \"stageParameters\",\n    \"standalone\",\n    \"standby\",\n    \"start\",\n    \"startContainer\",\n    \"startE\",\n    \"startIce\",\n    \"startLoadTime\",\n    \"startMessages\",\n    \"startNotifications\",\n    \"startOffset\",\n    \"startRendering\",\n    \"startSoftwareUpdate\",\n    \"startTime\",\n    \"startsWith\",\n    \"state\",\n    \"status\",\n    \"statusCode\",\n    \"statusMessage\",\n    \"statusText\",\n    \"statusbar\",\n    \"stdDeviationX\",\n    \"stdDeviationY\",\n    \"stencilFunc\",\n    \"stencilFuncSeparate\",\n    \"stencilMask\",\n    \"stencilMaskSeparate\",\n    \"stencilOp\",\n    \"stencilOpSeparate\",\n    \"step\",\n    \"stepDown\",\n    \"stepMismatch\",\n    \"stepUp\",\n    \"sticky\",\n    \"stitchTiles\",\n    \"stop\",\n    \"stop-color\",\n    \"stop-opacity\",\n    \"stopColor\",\n    \"stopImmediatePropagation\",\n    \"stopNotifications\",\n    \"stopOpacity\",\n    \"stopPropagation\",\n    \"stopped\",\n    \"storage\",\n    \"storageArea\",\n    \"storageName\",\n    \"storageStatus\",\n    \"store\",\n    \"storeSiteSpecificTrackingException\",\n    \"storeWebWideTrackingException\",\n    \"stpVersion\",\n    \"stream\",\n    \"streams\",\n    \"strength\",\n    \"stretch\",\n    \"strike\",\n    \"stringValue\",\n    \"stringify\",\n    \"stroke\",\n    \"stroke-dasharray\",\n    \"stroke-dashoffset\",\n    \"stroke-linecap\",\n    \"stroke-linejoin\",\n    \"stroke-miterlimit\",\n    \"stroke-opacity\",\n    \"stroke-width\",\n    \"strokeColor\",\n    \"strokeDasharray\",\n    \"strokeDashoffset\",\n    \"strokeLinecap\",\n    \"strokeLinejoin\",\n    \"strokeMiterlimit\",\n    \"strokeOpacity\",\n    \"strokeRect\",\n    \"strokeStyle\",\n    \"strokeText\",\n    \"strokeWidth\",\n    \"style\",\n    \"styleFloat\",\n    \"styleMap\",\n    \"styleMedia\",\n    \"styleSheet\",\n    \"styleSheetSets\",\n    \"styleSheets\",\n    \"sub\",\n    \"subarray\",\n    \"subject\",\n    \"submit\",\n    \"submitFrame\",\n    \"submitter\",\n    \"subscribe\",\n    \"substr\",\n    \"substring\",\n    \"substringData\",\n    \"subtle\",\n    \"subtree\",\n    \"suffix\",\n    \"suffixes\",\n    \"summary\",\n    \"sup\",\n    \"supported\",\n    \"supportedContentEncodings\",\n    \"supportedEntryTypes\",\n    \"supportedLocalesOf\",\n    \"supports\",\n    \"supportsSession\",\n    \"surfaceScale\",\n    \"surroundContents\",\n    \"suspend\",\n    \"suspendRedraw\",\n    \"swapCache\",\n    \"swapNode\",\n    \"sweepFlag\",\n    \"symbols\",\n    \"sync\",\n    \"sysexEnabled\",\n    \"system\",\n    \"systemCode\",\n    \"systemId\",\n    \"systemLanguage\",\n    \"systemXDPI\",\n    \"systemYDPI\",\n    \"tBodies\",\n    \"tFoot\",\n    \"tHead\",\n    \"tabIndex\",\n    \"tabSize\",\n    \"table\",\n    \"table-layout\",\n    \"tableLayout\",\n    \"tableValues\",\n    \"tag\",\n    \"tagName\",\n    \"tagUrn\",\n    \"tags\",\n    \"taintEnabled\",\n    \"takeHeapSnapshot\",\n    \"takePhoto\",\n    \"takeRecords\",\n    \"tan\",\n    \"tangentialPressure\",\n    \"tanh\",\n    \"target\",\n    \"targetElement\",\n    \"targetRayMode\",\n    \"targetRaySpace\",\n    \"targetTouches\",\n    \"targetX\",\n    \"targetY\",\n    \"tcpType\",\n    \"tee\",\n    \"tel\",\n    \"terminate\",\n    \"test\",\n    \"texImage2D\",\n    \"texImage3D\",\n    \"texParameterf\",\n    \"texParameteri\",\n    \"texStorage2D\",\n    \"texStorage3D\",\n    \"texSubImage2D\",\n    \"texSubImage3D\",\n    \"text\",\n    \"text-align\",\n    \"text-align-last\",\n    \"text-anchor\",\n    \"text-combine-upright\",\n    \"text-decoration\",\n    \"text-decoration-color\",\n    \"text-decoration-line\",\n    \"text-decoration-skip-ink\",\n    \"text-decoration-style\",\n    \"text-decoration-thickness\",\n    \"text-emphasis\",\n    \"text-emphasis-color\",\n    \"text-emphasis-position\",\n    \"text-emphasis-style\",\n    \"text-indent\",\n    \"text-justify\",\n    \"text-orientation\",\n    \"text-overflow\",\n    \"text-rendering\",\n    \"text-shadow\",\n    \"text-transform\",\n    \"text-underline-offset\",\n    \"text-underline-position\",\n    \"text/pdf\",\n    \"textAlign\",\n    \"textAlignLast\",\n    \"textAnchor\",\n    \"textAutospace\",\n    \"textBaseline\",\n    \"textCombineUpright\",\n    \"textContent\",\n    \"textDecoration\",\n    \"textDecorationBlink\",\n    \"textDecorationColor\",\n    \"textDecorationLine\",\n    \"textDecorationLineThrough\",\n    \"textDecorationNone\",\n    \"textDecorationOverline\",\n    \"textDecorationSkipInk\",\n    \"textDecorationStyle\",\n    \"textDecorationThickness\",\n    \"textDecorationUnderline\",\n    \"textEmphasis\",\n    \"textEmphasisColor\",\n    \"textEmphasisPosition\",\n    \"textEmphasisStyle\",\n    \"textIndent\",\n    \"textJustify\",\n    \"textJustifyTrim\",\n    \"textKashida\",\n    \"textKashidaSpace\",\n    \"textLength\",\n    \"textOrientation\",\n    \"textOverflow\",\n    \"textRendering\",\n    \"textShadow\",\n    \"textSizeAdjust\",\n    \"textTracks\",\n    \"textTransform\",\n    \"textUnderlineOffset\",\n    \"textUnderlinePosition\",\n    \"then\",\n    \"threadId\",\n    \"threshold\",\n    \"thresholds\",\n    \"tiltX\",\n    \"tiltY\",\n    \"time\",\n    \"timeEnd\",\n    \"timeLog\",\n    \"timeOrigin\",\n    \"timeRemaining\",\n    \"timeStamp\",\n    \"timeZone\",\n    \"timeZoneName\",\n    \"timecode\",\n    \"timeline\",\n    \"timelineEnd\",\n    \"timelineTime\",\n    \"timeout\",\n    \"timestamp\",\n    \"timestampOffset\",\n    \"timing\",\n    \"title\",\n    \"to\",\n    \"toArray\",\n    \"toBlob\",\n    \"toDataURL\",\n    \"toDateString\",\n    \"toElement\",\n    \"toExponential\",\n    \"toFixed\",\n    \"toFloat32Array\",\n    \"toFloat64Array\",\n    \"toGMTString\",\n    \"toISOString\",\n    \"toJSON\",\n    \"toLocaleDateString\",\n    \"toLocaleFormat\",\n    \"toLocaleLowerCase\",\n    \"toLocaleString\",\n    \"toLocaleTimeString\",\n    \"toLocaleUpperCase\",\n    \"toLowerCase\",\n    \"toMatrix\",\n    \"toMethod\",\n    \"toPrecision\",\n    \"toPrimitive\",\n    \"toSdp\",\n    \"toSource\",\n    \"toStaticHTML\",\n    \"toString\",\n    \"toStringTag\",\n    \"toSum\",\n    \"toTimeString\",\n    \"toUTCString\",\n    \"toUpperCase\",\n    \"toggle\",\n    \"toggleAttribute\",\n    \"toggleLongPressEnabled\",\n    \"tone\",\n    \"toneBuffer\",\n    \"tooLong\",\n    \"tooShort\",\n    \"toolbar\",\n    \"top\",\n    \"topMargin\",\n    \"total\",\n    \"totalFrameDelay\",\n    \"totalJSHeapSize\",\n    \"totalSize\",\n    \"totalVideoFrames\",\n    \"touch-action\",\n    \"touchAction\",\n    \"touched\",\n    \"touches\",\n    \"trace\",\n    \"track\",\n    \"trackVisibility\",\n    \"tran\",\n    \"transaction\",\n    \"transactions\",\n    \"transceiver\",\n    \"transferControlToOffscreen\",\n    \"transferFromImageBitmap\",\n    \"transferImageBitmap\",\n    \"transferIn\",\n    \"transferOut\",\n    \"transferSize\",\n    \"transferToImageBitmap\",\n    \"transform\",\n    \"transform-box\",\n    \"transform-origin\",\n    \"transform-style\",\n    \"transformBox\",\n    \"transformFeedbackVaryings\",\n    \"transformOrigin\",\n    \"transformOriginX\",\n    \"transformOriginY\",\n    \"transformOriginZ\",\n    \"transformPoint\",\n    \"transformString\",\n    \"transformStyle\",\n    \"transformToDocument\",\n    \"transformToFragment\",\n    \"transition\",\n    \"transition-delay\",\n    \"transition-duration\",\n    \"transition-property\",\n    \"transition-timing-function\",\n    \"transitionDelay\",\n    \"transitionDuration\",\n    \"transitionProperty\",\n    \"transitionTimingFunction\",\n    \"translate\",\n    \"translateSelf\",\n    \"translationX\",\n    \"translationY\",\n    \"transport\",\n    \"trim\",\n    \"trimEnd\",\n    \"trimLeft\",\n    \"trimRight\",\n    \"trimStart\",\n    \"trueSpeed\",\n    \"trunc\",\n    \"truncate\",\n    \"trustedTypes\",\n    \"turn\",\n    \"twist\",\n    \"type\",\n    \"typeDetail\",\n    \"typeMismatch\",\n    \"typeMustMatch\",\n    \"types\",\n    \"tz\",\n    \"u2f\",\n    \"ubound\",\n    \"undefined\",\n    \"unescape\",\n    \"uneval\",\n    \"unicode\",\n    \"unicode-bidi\",\n    \"unicodeBidi\",\n    \"unicodeRange\",\n    \"uniform1f\",\n    \"uniform1fv\",\n    \"uniform1i\",\n    \"uniform1iv\",\n    \"uniform1ui\",\n    \"uniform1uiv\",\n    \"uniform2f\",\n    \"uniform2fv\",\n    \"uniform2i\",\n    \"uniform2iv\",\n    \"uniform2ui\",\n    \"uniform2uiv\",\n    \"uniform3f\",\n    \"uniform3fv\",\n    \"uniform3i\",\n    \"uniform3iv\",\n    \"uniform3ui\",\n    \"uniform3uiv\",\n    \"uniform4f\",\n    \"uniform4fv\",\n    \"uniform4i\",\n    \"uniform4iv\",\n    \"uniform4ui\",\n    \"uniform4uiv\",\n    \"uniformBlockBinding\",\n    \"uniformMatrix2fv\",\n    \"uniformMatrix2x3fv\",\n    \"uniformMatrix2x4fv\",\n    \"uniformMatrix3fv\",\n    \"uniformMatrix3x2fv\",\n    \"uniformMatrix3x4fv\",\n    \"uniformMatrix4fv\",\n    \"uniformMatrix4x2fv\",\n    \"uniformMatrix4x3fv\",\n    \"unique\",\n    \"uniqueID\",\n    \"uniqueNumber\",\n    \"unit\",\n    \"unitType\",\n    \"units\",\n    \"unloadEventEnd\",\n    \"unloadEventStart\",\n    \"unlock\",\n    \"unmount\",\n    \"unobserve\",\n    \"unpause\",\n    \"unpauseAnimations\",\n    \"unreadCount\",\n    \"unregister\",\n    \"unregisterContentHandler\",\n    \"unregisterProtocolHandler\",\n    \"unscopables\",\n    \"unselectable\",\n    \"unshift\",\n    \"unsubscribe\",\n    \"unsuspendRedraw\",\n    \"unsuspendRedrawAll\",\n    \"unwatch\",\n    \"unwrapKey\",\n    \"upDegrees\",\n    \"upX\",\n    \"upY\",\n    \"upZ\",\n    \"update\",\n    \"updateCommands\",\n    \"updateEnabled\",\n    \"updateIce\",\n    \"updateInterval\",\n    \"updatePlaybackRate\",\n    \"updateRenderState\",\n    \"updateSettings\",\n    \"updateTiming\",\n    \"updateViaCache\",\n    \"updateWith\",\n    \"updated\",\n    \"updating\",\n    \"upgrade\",\n    \"upload\",\n    \"uploadTotal\",\n    \"uploaded\",\n    \"upper\",\n    \"upperBound\",\n    \"upperOpen\",\n    \"uri\",\n    \"url\",\n    \"urn\",\n    \"urns\",\n    \"usage\",\n    \"usages\",\n    \"usb\",\n    \"usbVersionMajor\",\n    \"usbVersionMinor\",\n    \"usbVersionSubminor\",\n    \"useCurrentView\",\n    \"useGrouping\",\n    \"useMap\",\n    \"useProgram\",\n    \"usedJSHeapSize\",\n    \"usedSpace\",\n    \"user-select\",\n    \"userActivation\",\n    \"userAgent\",\n    \"userChoice\",\n    \"userHandle\",\n    \"userHint\",\n    \"userLanguage\",\n    \"userProfile\",\n    \"userSelect\",\n    \"userVisibleOnly\",\n    \"userZoom\",\n    \"username\",\n    \"usernameFragment\",\n    \"utterance\",\n    \"uuid\",\n    \"v8BreakIterator\",\n    \"v8Parse\",\n    \"vAlign\",\n    \"vLink\",\n    \"valid\",\n    \"validate\",\n    \"validateProgram\",\n    \"validationMessage\",\n    \"validity\",\n    \"value\",\n    \"valueAsDate\",\n    \"valueAsNumber\",\n    \"valueAsString\",\n    \"valueInSpecifiedUnits\",\n    \"valueMissing\",\n    \"valueOf\",\n    \"valueText\",\n    \"valueType\",\n    \"values\",\n    \"variable\",\n    \"variant\",\n    \"vector-effect\",\n    \"vectorEffect\",\n    \"velocityAngular\",\n    \"velocityExpansion\",\n    \"velocityX\",\n    \"velocityY\",\n    \"vendor\",\n    \"vendorId\",\n    \"vendorSub\",\n    \"verify\",\n    \"version\",\n    \"vertexAttrib1f\",\n    \"vertexAttrib1fv\",\n    \"vertexAttrib2f\",\n    \"vertexAttrib2fv\",\n    \"vertexAttrib3f\",\n    \"vertexAttrib3fv\",\n    \"vertexAttrib4f\",\n    \"vertexAttrib4fv\",\n    \"vertexAttribDivisor\",\n    \"vertexAttribDivisorANGLE\",\n    \"vertexAttribI4i\",\n    \"vertexAttribI4iv\",\n    \"vertexAttribI4ui\",\n    \"vertexAttribI4uiv\",\n    \"vertexAttribIPointer\",\n    \"vertexAttribPointer\",\n    \"vertical\",\n    \"vertical-align\",\n    \"verticalAlign\",\n    \"verticalOverflow\",\n    \"vh\",\n    \"vibrate\",\n    \"vibrationActuator\",\n    \"video/x-ms-asf\",\n    \"video/x-ms-asf-plugin\",\n    \"video/x-ms-wm\",\n    \"video/x-ms-wmv\",\n    \"video/x-ms-wvx\",\n    \"videoBitsPerSecond\",\n    \"videoHeight\",\n    \"videoTracks\",\n    \"videoWidth\",\n    \"view\",\n    \"viewBox\",\n    \"viewBoxString\",\n    \"viewTarget\",\n    \"viewTargetString\",\n    \"viewport\",\n    \"viewportAnchorX\",\n    \"viewportAnchorY\",\n    \"viewportElement\",\n    \"views\",\n    \"violatedDirective\",\n    \"visibility\",\n    \"visibilityState\",\n    \"visible\",\n    \"visualViewport\",\n    \"vlinkColor\",\n    \"vmax\",\n    \"vmin\",\n    \"voice\",\n    \"voiceURI\",\n    \"volume\",\n    \"vrml\",\n    \"vspace\",\n    \"vw\",\n    \"w\",\n    \"wait\",\n    \"waitSync\",\n    \"waiting\",\n    \"wake\",\n    \"wakeLock\",\n    \"wand\",\n    \"warn\",\n    \"wasAlternateProtocolAvailable\",\n    \"wasClean\",\n    \"wasDiscarded\",\n    \"wasFetchedViaSpdy\",\n    \"wasNpnNegotiated\",\n    \"watch\",\n    \"watchAvailability\",\n    \"watchPosition\",\n    \"webdriver\",\n    \"webkitAddKey\",\n    \"webkitAlignContent\",\n    \"webkitAlignItems\",\n    \"webkitAlignSelf\",\n    \"webkitAnimation\",\n    \"webkitAnimationDelay\",\n    \"webkitAnimationDirection\",\n    \"webkitAnimationDuration\",\n    \"webkitAnimationFillMode\",\n    \"webkitAnimationIterationCount\",\n    \"webkitAnimationName\",\n    \"webkitAnimationPlayState\",\n    \"webkitAnimationTimingFunction\",\n    \"webkitAppRegion\",\n    \"webkitAppearance\",\n    \"webkitAspectRatio\",\n    \"webkitAudioContext\",\n    \"webkitAudioDecodedByteCount\",\n    \"webkitAudioPannerNode\",\n    \"webkitBackdropFilter\",\n    \"webkitBackfaceVisibility\",\n    \"webkitBackground\",\n    \"webkitBackgroundAttachment\",\n    \"webkitBackgroundClip\",\n    \"webkitBackgroundColor\",\n    \"webkitBackgroundComposite\",\n    \"webkitBackgroundImage\",\n    \"webkitBackgroundOrigin\",\n    \"webkitBackgroundPosition\",\n    \"webkitBackgroundPositionX\",\n    \"webkitBackgroundPositionY\",\n    \"webkitBackgroundRepeat\",\n    \"webkitBackgroundSize\",\n    \"webkitBackingStorePixelRatio\",\n    \"webkitBorderAfter\",\n    \"webkitBorderAfterColor\",\n    \"webkitBorderAfterStyle\",\n    \"webkitBorderAfterWidth\",\n    \"webkitBorderBefore\",\n    \"webkitBorderBeforeColor\",\n    \"webkitBorderBeforeStyle\",\n    \"webkitBorderBeforeWidth\",\n    \"webkitBorderBottomLeftRadius\",\n    \"webkitBorderBottomRightRadius\",\n    \"webkitBorderEnd\",\n    \"webkitBorderEndColor\",\n    \"webkitBorderEndStyle\",\n    \"webkitBorderEndWidth\",\n    \"webkitBorderFit\",\n    \"webkitBorderHorizontalSpacing\",\n    \"webkitBorderImage\",\n    \"webkitBorderImageOutset\",\n    \"webkitBorderImageRepeat\",\n    \"webkitBorderImageSlice\",\n    \"webkitBorderImageSource\",\n    \"webkitBorderImageWidth\",\n    \"webkitBorderRadius\",\n    \"webkitBorderStart\",\n    \"webkitBorderStartColor\",\n    \"webkitBorderStartStyle\",\n    \"webkitBorderStartWidth\",\n    \"webkitBorderTopLeftRadius\",\n    \"webkitBorderTopRightRadius\",\n    \"webkitBorderVerticalSpacing\",\n    \"webkitBoxAlign\",\n    \"webkitBoxDecorationBreak\",\n    \"webkitBoxDirection\",\n    \"webkitBoxFlex\",\n    \"webkitBoxFlexGroup\",\n    \"webkitBoxLines\",\n    \"webkitBoxOrdinalGroup\",\n    \"webkitBoxOrient\",\n    \"webkitBoxPack\",\n    \"webkitBoxReflect\",\n    \"webkitBoxShadow\",\n    \"webkitBoxSizing\",\n    \"webkitCancelAnimationFrame\",\n    \"webkitCancelFullScreen\",\n    \"webkitCancelKeyRequest\",\n    \"webkitCancelRequestAnimationFrame\",\n    \"webkitClearResourceTimings\",\n    \"webkitClipPath\",\n    \"webkitClosedCaptionsVisible\",\n    \"webkitColumnAxis\",\n    \"webkitColumnBreakAfter\",\n    \"webkitColumnBreakBefore\",\n    \"webkitColumnBreakInside\",\n    \"webkitColumnCount\",\n    \"webkitColumnGap\",\n    \"webkitColumnProgression\",\n    \"webkitColumnRule\",\n    \"webkitColumnRuleColor\",\n    \"webkitColumnRuleStyle\",\n    \"webkitColumnRuleWidth\",\n    \"webkitColumnSpan\",\n    \"webkitColumnWidth\",\n    \"webkitColumns\",\n    \"webkitConvertPointFromNodeToPage\",\n    \"webkitConvertPointFromPageToNode\",\n    \"webkitCreateShadowRoot\",\n    \"webkitCurrentFullScreenElement\",\n    \"webkitCurrentPlaybackTargetIsWireless\",\n    \"webkitCursorVisibility\",\n    \"webkitDashboardRegion\",\n    \"webkitDecodedFrameCount\",\n    \"webkitDirectionInvertedFromDevice\",\n    \"webkitDisplayingFullscreen\",\n    \"webkitDroppedFrameCount\",\n    \"webkitEnterFullScreen\",\n    \"webkitEnterFullscreen\",\n    \"webkitEntries\",\n    \"webkitExitFullScreen\",\n    \"webkitExitFullscreen\",\n    \"webkitExitPointerLock\",\n    \"webkitFilter\",\n    \"webkitFlex\",\n    \"webkitFlexBasis\",\n    \"webkitFlexDirection\",\n    \"webkitFlexFlow\",\n    \"webkitFlexGrow\",\n    \"webkitFlexShrink\",\n    \"webkitFlexWrap\",\n    \"webkitFontFeatureSettings\",\n    \"webkitFontKerning\",\n    \"webkitFontSizeDelta\",\n    \"webkitFontSmoothing\",\n    \"webkitForce\",\n    \"webkitFullScreenKeyboardInputAllowed\",\n    \"webkitFullscreenElement\",\n    \"webkitFullscreenEnabled\",\n    \"webkitGenerateKeyRequest\",\n    \"webkitGetAsEntry\",\n    \"webkitGetDatabaseNames\",\n    \"webkitGetEntries\",\n    \"webkitGetEntriesByName\",\n    \"webkitGetEntriesByType\",\n    \"webkitGetFlowByName\",\n    \"webkitGetGamepads\",\n    \"webkitGetImageDataHD\",\n    \"webkitGetNamedFlows\",\n    \"webkitGetRegionFlowRanges\",\n    \"webkitGetUserMedia\",\n    \"webkitHasClosedCaptions\",\n    \"webkitHidden\",\n    \"webkitHighlight\",\n    \"webkitHyphenateCharacter\",\n    \"webkitHyphenateLimitAfter\",\n    \"webkitHyphenateLimitBefore\",\n    \"webkitHyphenateLimitLines\",\n    \"webkitHyphens\",\n    \"webkitIDBCursor\",\n    \"webkitIDBDatabase\",\n    \"webkitIDBDatabaseError\",\n    \"webkitIDBDatabaseException\",\n    \"webkitIDBFactory\",\n    \"webkitIDBIndex\",\n    \"webkitIDBKeyRange\",\n    \"webkitIDBObjectStore\",\n    \"webkitIDBRequest\",\n    \"webkitIDBTransaction\",\n    \"webkitImageSmoothingEnabled\",\n    \"webkitIndexedDB\",\n    \"webkitInitMessageEvent\",\n    \"webkitInitialLetter\",\n    \"webkitIsFullScreen\",\n    \"webkitJustifyContent\",\n    \"webkitKeys\",\n    \"webkitLineAlign\",\n    \"webkitLineBoxContain\",\n    \"webkitLineBreak\",\n    \"webkitLineClamp\",\n    \"webkitLineDash\",\n    \"webkitLineDashOffset\",\n    \"webkitLineGrid\",\n    \"webkitLineSnap\",\n    \"webkitLocale\",\n    \"webkitLockOrientation\",\n    \"webkitLogicalHeight\",\n    \"webkitLogicalWidth\",\n    \"webkitMarginAfter\",\n    \"webkitMarginAfterCollapse\",\n    \"webkitMarginBefore\",\n    \"webkitMarginBeforeCollapse\",\n    \"webkitMarginBottomCollapse\",\n    \"webkitMarginCollapse\",\n    \"webkitMarginEnd\",\n    \"webkitMarginStart\",\n    \"webkitMarginTopCollapse\",\n    \"webkitMarquee\",\n    \"webkitMarqueeDirection\",\n    \"webkitMarqueeIncrement\",\n    \"webkitMarqueeRepetition\",\n    \"webkitMarqueeSpeed\",\n    \"webkitMarqueeStyle\",\n    \"webkitMask\",\n    \"webkitMaskBoxImage\",\n    \"webkitMaskBoxImageOutset\",\n    \"webkitMaskBoxImageRepeat\",\n    \"webkitMaskBoxImageSlice\",\n    \"webkitMaskBoxImageSource\",\n    \"webkitMaskBoxImageWidth\",\n    \"webkitMaskClip\",\n    \"webkitMaskComposite\",\n    \"webkitMaskImage\",\n    \"webkitMaskOrigin\",\n    \"webkitMaskPosition\",\n    \"webkitMaskPositionX\",\n    \"webkitMaskPositionY\",\n    \"webkitMaskRepeat\",\n    \"webkitMaskRepeatX\",\n    \"webkitMaskRepeatY\",\n    \"webkitMaskSize\",\n    \"webkitMaskSourceType\",\n    \"webkitMatchesSelector\",\n    \"webkitMaxLogicalHeight\",\n    \"webkitMaxLogicalWidth\",\n    \"webkitMediaStream\",\n    \"webkitMinLogicalHeight\",\n    \"webkitMinLogicalWidth\",\n    \"webkitNbspMode\",\n    \"webkitNotifications\",\n    \"webkitOfflineAudioContext\",\n    \"webkitOpacity\",\n    \"webkitOrder\",\n    \"webkitOrientation\",\n    \"webkitPaddingAfter\",\n    \"webkitPaddingBefore\",\n    \"webkitPaddingEnd\",\n    \"webkitPaddingStart\",\n    \"webkitPeerConnection00\",\n    \"webkitPersistentStorage\",\n    \"webkitPerspective\",\n    \"webkitPerspectiveOrigin\",\n    \"webkitPerspectiveOriginX\",\n    \"webkitPerspectiveOriginY\",\n    \"webkitPointerLockElement\",\n    \"webkitPostMessage\",\n    \"webkitPreservesPitch\",\n    \"webkitPrintColorAdjust\",\n    \"webkitPutImageDataHD\",\n    \"webkitRTCPeerConnection\",\n    \"webkitRegionOverset\",\n    \"webkitRelativePath\",\n    \"webkitRequestAnimationFrame\",\n    \"webkitRequestFileSystem\",\n    \"webkitRequestFullScreen\",\n    \"webkitRequestFullscreen\",\n    \"webkitRequestPointerLock\",\n    \"webkitResolveLocalFileSystemURL\",\n    \"webkitRtlOrdering\",\n    \"webkitRubyPosition\",\n    \"webkitSetMediaKeys\",\n    \"webkitSetResourceTimingBufferSize\",\n    \"webkitShadowRoot\",\n    \"webkitShapeImageThreshold\",\n    \"webkitShapeMargin\",\n    \"webkitShapeOutside\",\n    \"webkitShowPlaybackTargetPicker\",\n    \"webkitSlice\",\n    \"webkitSpeechGrammar\",\n    \"webkitSpeechGrammarList\",\n    \"webkitSpeechRecognition\",\n    \"webkitSpeechRecognitionError\",\n    \"webkitSpeechRecognitionEvent\",\n    \"webkitStorageInfo\",\n    \"webkitSupportsFullscreen\",\n    \"webkitSvgShadow\",\n    \"webkitTapHighlightColor\",\n    \"webkitTemporaryStorage\",\n    \"webkitTextCombine\",\n    \"webkitTextDecoration\",\n    \"webkitTextDecorationColor\",\n    \"webkitTextDecorationLine\",\n    \"webkitTextDecorationSkip\",\n    \"webkitTextDecorationStyle\",\n    \"webkitTextDecorationsInEffect\",\n    \"webkitTextEmphasis\",\n    \"webkitTextEmphasisColor\",\n    \"webkitTextEmphasisPosition\",\n    \"webkitTextEmphasisStyle\",\n    \"webkitTextFillColor\",\n    \"webkitTextOrientation\",\n    \"webkitTextSecurity\",\n    \"webkitTextSizeAdjust\",\n    \"webkitTextStroke\",\n    \"webkitTextStrokeColor\",\n    \"webkitTextStrokeWidth\",\n    \"webkitTextUnderlinePosition\",\n    \"webkitTextZoom\",\n    \"webkitTransform\",\n    \"webkitTransformOrigin\",\n    \"webkitTransformOriginX\",\n    \"webkitTransformOriginY\",\n    \"webkitTransformOriginZ\",\n    \"webkitTransformStyle\",\n    \"webkitTransition\",\n    \"webkitTransitionDelay\",\n    \"webkitTransitionDuration\",\n    \"webkitTransitionProperty\",\n    \"webkitTransitionTimingFunction\",\n    \"webkitURL\",\n    \"webkitUnlockOrientation\",\n    \"webkitUserDrag\",\n    \"webkitUserModify\",\n    \"webkitUserSelect\",\n    \"webkitVideoDecodedByteCount\",\n    \"webkitVisibilityState\",\n    \"webkitWirelessVideoPlaybackDisabled\",\n    \"webkitWritingMode\",\n    \"webkitdirectory\",\n    \"webkitdropzone\",\n    \"webstore\",\n    \"weekday\",\n    \"weight\",\n    \"whatToShow\",\n    \"wheelDelta\",\n    \"wheelDeltaX\",\n    \"wheelDeltaY\",\n    \"whenDefined\",\n    \"which\",\n    \"white-space\",\n    \"whiteSpace\",\n    \"wholeText\",\n    \"widows\",\n    \"width\",\n    \"will-change\",\n    \"willChange\",\n    \"willValidate\",\n    \"window\",\n    \"withCredentials\",\n    \"word-break\",\n    \"word-spacing\",\n    \"word-wrap\",\n    \"wordBreak\",\n    \"wordSpacing\",\n    \"wordWrap\",\n    \"workerStart\",\n    \"wrap\",\n    \"wrapKey\",\n    \"writable\",\n    \"writableAuxiliaries\",\n    \"write\",\n    \"writeText\",\n    \"writeValue\",\n    \"writeWithoutResponse\",\n    \"writeln\",\n    \"writing-mode\",\n    \"writingMode\",\n    \"x\",\n    \"x1\",\n    \"x2\",\n    \"xChannelSelector\",\n    \"xmlEncoding\",\n    \"xmlStandalone\",\n    \"xmlVersion\",\n    \"xmlbase\",\n    \"xmllang\",\n    \"xmlspace\",\n    \"xor\",\n    \"xr\",\n    \"y\",\n    \"y1\",\n    \"y2\",\n    \"yChannelSelector\",\n    \"yandex\",\n    \"year\",\n    \"z\",\n    \"z-index\",\n    \"zIndex\",\n    \"zoom\",\n    \"zoomAndPan\",\n    \"zoomRectScreen\"\n]\n"
  },
  {
    "path": "tools/exports.js",
    "content": "exports[\"Dictionary\"] = Dictionary;\nexports[\"is_statement\"] = is_statement;\nexports[\"List\"] = List;\nexports[\"minify\"] = minify;\nexports[\"parse\"] = parse;\nexports[\"push_uniq\"] = push_uniq;\nexports[\"TreeTransformer\"] = TreeTransformer;\nexports[\"TreeWalker\"] = TreeWalker;\n"
  },
  {
    "path": "tools/node.js",
    "content": "var fs = require(\"fs\");\n\nexports.FILES = [\n    require.resolve(\"../lib/utils.js\"),\n    require.resolve(\"../lib/ast.js\"),\n    require.resolve(\"../lib/transform.js\"),\n    require.resolve(\"../lib/parse.js\"),\n    require.resolve(\"../lib/scope.js\"),\n    require.resolve(\"../lib/compress.js\"),\n    require.resolve(\"../lib/output.js\"),\n    require.resolve(\"../lib/sourcemap.js\"),\n    require.resolve(\"../lib/mozilla-ast.js\"),\n    require.resolve(\"../lib/propmangle.js\"),\n    require.resolve(\"../lib/minify.js\"),\n    require.resolve(\"./exports.js\"),\n];\n\nnew Function(\"domprops\", \"exports\", function() {\n    var code = exports.FILES.map(function(file) {\n        return fs.readFileSync(file, \"utf8\");\n    });\n    code.push(\"exports.describe_ast = \" + describe_ast.toString());\n    return code.join(\"\\n\\n\");\n}())(require(\"./domprops.json\"), exports);\n\nfunction to_comment(value) {\n    if (typeof value != \"string\") value = JSON.stringify(value, function(key, value) {\n        return typeof value == \"function\" ? \"<[ \" + value + \" ]>\" : value;\n    }, 2);\n    return \"// \" + value.replace(/\\n/g, \"\\n// \");\n}\n\nif (+process.env[\"UGLIFY_BUG_REPORT\"]) exports.minify = function(files, options) {\n    if (typeof options == \"undefined\") options = \"<<undefined>>\";\n    var code = [\n        \"// UGLIFY_BUG_REPORT\",\n        to_comment(options),\n    ];\n    if (typeof files == \"string\") {\n        code.push(\"\");\n        code.push(\"//-------------------------------------------------------------\")\n        code.push(\"// INPUT CODE\", files);\n    } else for (var name in files) {\n        code.push(\"\");\n        code.push(\"//-------------------------------------------------------------\")\n        code.push(to_comment(name), files[name]);\n    }\n    if (options.sourceMap && options.sourceMap.url) {\n        code.push(\"\");\n        code.push(\"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9\");\n    }\n    var result = { code: code.join(\"\\n\") };\n    if (options.sourceMap) result.map = '{\"version\":3,\"sources\":[],\"names\":[],\"mappings\":\"\"}';\n    return result;\n};\n\nfunction describe_ast() {\n    var out = OutputStream({ beautify: true });\n    doitem(AST_Node);\n    return out.get() + \"\\n\";\n\n    function doitem(ctor) {\n        out.print(\"AST_\" + ctor.TYPE);\n        var props = ctor.SELF_PROPS.filter(function(prop) {\n            return !/^\\$/.test(prop);\n        });\n        if (props.length > 0) {\n            out.space();\n            out.with_parens(function() {\n                props.forEach(function(prop, i) {\n                    if (i) out.space();\n                    out.print(prop);\n                });\n            });\n        }\n        if (ctor.documentation) {\n            out.space();\n            out.print_string(ctor.documentation);\n        }\n        if (ctor.SUBCLASSES.length > 0) {\n            out.space();\n            out.with_block(function() {\n                ctor.SUBCLASSES.sort(function(a, b) {\n                    return a.TYPE < b.TYPE ? -1 : 1;\n                }).forEach(function(ctor, i) {\n                    out.indent();\n                    doitem(ctor);\n                    out.newline();\n                });\n            });\n        }\n    }\n}\n\nfunction infer_options(options) {\n    var result = exports.minify(\"\", options);\n    return result.error && result.error.defs;\n}\n\nexports.default_options = function(component) {\n    if (component) {\n        var options = { module: false };\n        options[component] = { 0: 0 };\n        return infer_options(options);\n    }\n    var defs = infer_options({ 0: 0 });\n    Object.keys(defs).forEach(function(component) {\n        var options = { module: false };\n        options[component] = { 0: 0 };\n        if (options = infer_options(options)) {\n            defs[component] = options;\n        }\n    });\n    return defs;\n};\n"
  },
  {
    "path": "tools/tty.js",
    "content": "// workaround for tty output truncation on Node.js\ntry {\n    // prevent buffer overflow and other asynchronous bugs\n    process.stdout._handle.setBlocking(true);\n    process.stderr._handle.setBlocking(true);\n} catch (e) {\n    // ensure output buffers are flushed before process termination\n    var exit = process.exit;\n    if (\"bufferSize\" in process.stdout) process.exit = function() {\n        var args = [].slice.call(arguments);\n        process.once(\"uncaughtException\", function() {\n            (function callback() {\n                if (process.stdout.bufferSize || process.stderr.bufferSize) {\n                    setTimeout(callback, 1);\n                } else {\n                    exit.apply(process, args);\n                }\n            })();\n        });\n        throw exit;\n    };\n}\n"
  }
]