├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── LICENSE.BSD ├── README.md ├── benchmark ├── LICENSE ├── Readme.md ├── asts.js ├── asts │ ├── backbone-0.5.3-ast.json │ ├── ext-core-3.0.0-ast.json │ ├── ext-core-3.1.0-ast.json │ ├── jquery-1.6.4-ast.json │ ├── jquery-1.7.1-ast.json │ ├── jquery.mobile-1.0-ast.json │ ├── mootools-1.3.2-ast.json │ ├── mootools-1.4.1-ast.json │ ├── prototype-1.6.1-ast.json │ ├── prototype-1.7.0.0-ast.json │ └── underscore-1.2.3-ast.json ├── index.js ├── old.js ├── package.json ├── trace_cycle.js ├── v8_trace └── v8_trace_reports │ ├── deoptimizations.log │ ├── never_optimized.log │ └── not_inlined.log ├── bin ├── escodegen.js └── esgenerate.js ├── escodegen.js ├── gulpfile.js ├── package.json ├── test ├── 3rdparty │ ├── Tokenizer.js │ ├── XMLHttpRequest.js │ ├── ZeParser.js │ ├── backbone-0.5.3.js │ ├── benchmark.js │ ├── esprima-1.0.0-dev.js │ ├── esprima-2.7.1.js │ ├── esprima-harmony.original.js │ ├── esprima-harmony.patched.js │ ├── ext-core-3.0.0.js │ ├── ext-core-3.1.0.js │ ├── jquery-1.6.4.js │ ├── jquery-1.7.1.js │ ├── jquery.mobile-1.0.js │ ├── jsdefs.js │ ├── jslex.js │ ├── jsparse.js │ ├── mootools-1.3.2.js │ ├── mootools-1.4.1.js │ ├── parse-js.js │ ├── platform.js │ ├── prototype-1.6.1.js │ ├── prototype-1.7.0.0.js │ └── underscore-1.2.3.js ├── api.js ├── ast.js ├── comment.js ├── comment │ ├── 2-space-multi-comment.expected.js │ ├── 2-space-multi-comment.js │ ├── block-line-comment.expected.js │ ├── block-line-comment.js │ ├── comment-only.expected.js │ ├── comment-only.js │ ├── computed-property-comments-2.expected.js │ ├── computed-property-comments-2.js │ ├── computed-property-comments.expected.js │ ├── computed-property-comments.js │ ├── do-while-line-comment.expected.js │ ├── do-while-line-comment.js │ ├── empty-line-comment.expected.js │ ├── empty-line-comment.js │ ├── empty.expected.js │ ├── empty.js │ ├── function-block-line-comment.expected.js │ ├── function-block-line-comment.js │ ├── if-block-line-comment.expected.js │ ├── if-block-line-comment.js │ ├── if-empty-line-comment.expected.js │ ├── if-empty-line-comment.js │ ├── if-line-comment.expected.js │ ├── if-line-comment.js │ ├── object_comments.expected.js │ ├── object_comments.js │ ├── return-no-argument.expected.js │ ├── return-no-argument.js │ ├── simple-a-lot-of-line-comment.expected.js │ ├── simple-a-lot-of-line-comment.js │ ├── simple-a-lot-of-multi-comment.expected.js │ ├── simple-a-lot-of-multi-comment.js │ ├── simple-line-comment.expected.js │ ├── simple-line-comment.js │ ├── simple-multi-comment.expected.js │ ├── simple-multi-comment.js │ ├── simple-statement-comment.expected.js │ ├── simple-statement-comment.js │ ├── try-block-line-comment.expected.js │ ├── try-block-line-comment.js │ ├── variable-declarator-line-comment.expected.js │ ├── variable-declarator-line-comment.js │ ├── variable-declarator-multi-comment.expected.js │ ├── variable-declarator-multi-comment.js │ ├── variable-declarator-trailing-comment.expected.js │ └── variable-declarator-trailing-comment.js ├── compare-acorn-es2019.js ├── compare-acorn-es2019 │ ├── optional-catch-binding.expected.js │ ├── optional-catch-binding.expected.min.js │ └── optional-catch-binding.js ├── compare-acorn-es2020.js ├── compare-acorn-es2020 │ ├── bigint.expected.js │ ├── bigint.expected.min.js │ ├── bigint.js │ ├── nullish-coalescing.expected.js │ ├── nullish-coalescing.expected.min.js │ ├── nullish-coalescing.js │ ├── optional-chaining-2.expected.js │ ├── optional-chaining-2.expected.min.js │ ├── optional-chaining-2.js │ ├── optional-chaining.expected.js │ ├── optional-chaining.expected.min.js │ └── optional-chaining.js ├── compare-acorn-es2021.js ├── compare-acorn-es2021 │ ├── logical-assignments.expected.js │ ├── logical-assignments.expected.min.js │ └── logical-assignments.js ├── compare-acorn-es6.js ├── compare-acorn-es6 │ ├── assignment-pattern.expected.js │ ├── assignment-pattern.expected.min.js │ ├── assignment-pattern.js │ ├── class-declaration.expected.js │ ├── class-declaration.expected.min.js │ └── class-declaration.js ├── compare-acorn-es7.js ├── compare-acorn-es7 │ ├── exponentiation-precedence.expected.js │ └── exponentiation-precedence.js ├── compare-esprima2.js ├── compare-esprima2 │ ├── export-declaration.expected.js │ ├── export-declaration.expected.min.js │ ├── export-declaration.js │ ├── export-default-declaration.expected.js │ ├── export-default-declaration.expected.min.js │ ├── export-default-declaration.js │ ├── exports.expected.js │ ├── exports.expected.min.js │ ├── exports.js │ ├── import-with-default.expected.js │ ├── import-with-default.expected.min.js │ ├── import-with-default.js │ ├── imports.expected.js │ ├── imports.expected.min.js │ └── imports.js ├── compare-fixed-harmony.js ├── compare-fixed-harmony │ ├── spread-element.expected.js │ ├── spread-element.expected.min.js │ └── spread-element.js ├── compare-harmony.js ├── compare-harmony │ ├── arrow-function.expected.js │ ├── arrow-function.expected.min.js │ ├── arrow-function.js │ ├── class-declaration.expected.js │ ├── class-declaration.expected.min.js │ ├── class-declaration.js │ ├── class-expression.expected.js │ ├── class-expression.expected.min.js │ ├── class-expression.js │ ├── computed-property.expected.js │ ├── computed-property.expected.min.js │ ├── computed-property.js │ ├── default-parameter.expected.js │ ├── default-parameter.expected.min.js │ ├── default-parameter.js │ ├── destructuring-assignment.expected.js │ ├── destructuring-assignment.expected.min.js │ ├── destructuring-assignment.js │ ├── for-of-statement.expected.js │ ├── for-of-statement.expected.min.js │ ├── for-of-statement.js │ ├── one-assignment-property.expected.js │ ├── one-assignment-property.expected.min.js │ ├── one-assignment-property.js │ ├── spread-element.expected.js │ ├── spread-element.expected.min.js │ ├── spread-element.js │ ├── templates-escape.expected.js │ ├── templates-escape.expected.min.js │ ├── templates-escape.js │ ├── templates.expected.js │ ├── templates.expected.min.js │ ├── templates.js │ ├── yield-precedence.expected.js │ ├── yield-precedence.expected.min.js │ └── yield-precedence.js ├── compare.js ├── compare │ ├── binary-precedence.expected.js │ ├── binary-precedence.js │ ├── bitwise-precedence.expected.js │ ├── bitwise-precedence.js │ ├── floating-point.expected.js │ ├── floating-point.js │ ├── for-in-no-in.expected.js │ ├── for-in-no-in.js │ ├── new-precedence.expected.js │ ├── new-precedence.js │ ├── one-property-with-line-terminator.expected.js │ ├── one-property-with-line-terminator.js │ ├── unary-op.expected.js │ ├── unary-op.js │ ├── unnecessary-parenthesized-in-2.expected.js │ ├── unnecessary-parenthesized-in-2.js │ ├── unnecessary-parenthesized-in.expected.js │ ├── unnecessary-parenthesized-in.js │ ├── variable-declaration.expected.js │ └── variable-declaration.js ├── directive.js ├── harmony-esprima2.js ├── harmony.js ├── identity.js ├── loader.js ├── options.js ├── preserve-blank-lines.js ├── preserve-blank-lines │ ├── block-comments.expected.js │ ├── block-comments.js │ ├── comment-at-start-of-function.expected.js │ ├── comment-at-start-of-function.js │ ├── comments.expected.js │ ├── comments.js │ ├── functions.expected.js │ ├── functions.js │ ├── multiple-comments.expected.js │ ├── multiple-comments.js │ ├── trailing-comment-in-function.expected.js │ ├── trailing-comment-in-function.js │ ├── trailing-comment-in-program.expected.js │ ├── trailing-comment-in-program.js │ ├── variables.expected.js │ └── variables.js ├── source-map.js ├── test.js └── verbatim.js └── tools ├── entry-point.js ├── release.js └── rules └── push-with-multiple-arguments.js /.gitattributes: -------------------------------------------------------------------------------- 1 | test/3rdparty/**/* -crlf -diff 2 | # don't collapse diffs of test expectations 3 | test/compare-*/*.expected.min.js -linguist-generated 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Emacs 2 | *~ 3 | \#*\# 4 | 5 | # Node modules 6 | node_modules/ 7 | 8 | # Cover 9 | .coverage_data/ 10 | cover_html/ 11 | 12 | npm-debug.log 13 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | npm-debug.log 2 | .DS_Store 3 | .vimrc.local 4 | t.js 5 | esprima.js 6 | escodegen.browser.js 7 | .travis.yml 8 | .npmignore 9 | /tmp/ 10 | /.git/ 11 | /node_modules/ 12 | /tools/ 13 | /test/ 14 | /cover_html/ 15 | /.coverage_data/ 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "6" 5 | - "8" 6 | - "10" 7 | -------------------------------------------------------------------------------- /LICENSE.BSD: -------------------------------------------------------------------------------- 1 | Copyright (C) 2012 Yusuke Suzuki (twitter: @Constellation) and other contributors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 16 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Escodegen 2 | [![npm version](https://badge.fury.io/js/escodegen.svg)](http://badge.fury.io/js/escodegen) 3 | [![Build Status](https://secure.travis-ci.org/estools/escodegen.svg)](http://travis-ci.org/estools/escodegen) 4 | [![Dependency Status](https://david-dm.org/estools/escodegen.svg)](https://david-dm.org/estools/escodegen) 5 | [![devDependency Status](https://david-dm.org/estools/escodegen/dev-status.svg)](https://david-dm.org/estools/escodegen#info=devDependencies) 6 | 7 | Escodegen ([escodegen](http://github.com/estools/escodegen)) is an 8 | [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm) 9 | (also popularly known as [JavaScript](http://en.wikipedia.org/wiki/JavaScript)) 10 | code generator from [Mozilla's Parser API](https://developer.mozilla.org/en/SpiderMonkey/Parser_API) 11 | AST. See the [online generator](https://estools.github.io/escodegen/demo/index.html) 12 | for a demo. 13 | 14 | 15 | ### Install 16 | 17 | Escodegen can be used in a web browser: 18 | 19 | 20 | 21 | escodegen.browser.js can be found in tagged revisions on GitHub. 22 | 23 | Or in a Node.js application via npm: 24 | 25 | npm install escodegen 26 | 27 | ### Usage 28 | 29 | A simple example: the program 30 | 31 | escodegen.generate({ 32 | type: 'BinaryExpression', 33 | operator: '+', 34 | left: { type: 'Literal', value: 40 }, 35 | right: { type: 'Literal', value: 2 } 36 | }); 37 | 38 | produces the string `'40 + 2'`. 39 | 40 | See the [API page](https://github.com/estools/escodegen/wiki/API) for 41 | options. To run the tests, execute `npm test` in the root directory. 42 | 43 | ### Building browser bundle / minified browser bundle 44 | 45 | At first, execute `npm install` to install the all dev dependencies. 46 | After that, 47 | 48 | npm run-script build 49 | 50 | will generate `escodegen.browser.js`, which can be used in browser environments. 51 | 52 | And, 53 | 54 | npm run-script build-min 55 | 56 | will generate the minified file `escodegen.browser.min.js`. 57 | 58 | ### License 59 | 60 | #### Escodegen 61 | 62 | Copyright (C) 2012 [Yusuke Suzuki](http://github.com/Constellation) 63 | (twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors. 64 | 65 | Redistribution and use in source and binary forms, with or without 66 | modification, are permitted provided that the following conditions are met: 67 | 68 | * Redistributions of source code must retain the above copyright 69 | notice, this list of conditions and the following disclaimer. 70 | 71 | * Redistributions in binary form must reproduce the above copyright 72 | notice, this list of conditions and the following disclaimer in the 73 | documentation and/or other materials provided with the distribution. 74 | 75 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 76 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 77 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 78 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 79 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 80 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 81 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 82 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 83 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 84 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 85 | -------------------------------------------------------------------------------- /benchmark/LICENSE: -------------------------------------------------------------------------------- 1 | Redistribution and use in source and binary forms, with or without 2 | modification, are permitted provided that the following conditions are met: 3 | 4 | * Redistributions of source code must retain the above copyright 5 | notice, this list of conditions and the following disclaimer. 6 | * Redistributions in binary form must reproduce the above copyright 7 | notice, this list of conditions and the following disclaimer in the 8 | documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 11 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 14 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 15 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 16 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 17 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 19 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | -------------------------------------------------------------------------------- /benchmark/Readme.md: -------------------------------------------------------------------------------- 1 | # esotope benchmark 2 | 3 | This benchmark compares esotope and [escodegen](https://github.com/Constellation/escodegen) performance. 4 | 5 | ## Usage 6 | ``` 7 | $ cd benchmark/ 8 | $ npm install && npm test 9 | ``` 10 | 11 | ## Results 12 | **Machine used:** Intel Core i7-2700K @ 3.50GHz, 8 GB RAM, Windows 8 64-bit, node 64-bit 13 | 14 | With node v0.10.32: 15 | ``` 16 | esotope x 13.93 ops/sec ±3.45% (40 runs sampled) 17 | escodegen x 6.61 ops/sec ±0.83% (21 runs sampled) 18 | Fastest is esotope 19 | esotope is x2.11 times faster vs escodegen. 20 | ``` 21 | 22 | With node v0.11.14 (with newer v8 version): 23 | ``` 24 | esotope x 17.57 ops/sec ±0.60% (48 runs sampled) 25 | escodegen x 3.81 ops/sec ±3.94% (14 runs sampled) 26 | Fastest is esotope 27 | esotope is x4.61 times faster vs escodegen. 28 | ``` -------------------------------------------------------------------------------- /benchmark/asts.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'), 3 | esprima = require('esprima'); 4 | 5 | var FILES_PATH = path.join(__dirname, './asts'); 6 | 7 | var FILES = [ 8 | 'jQuery 1.7.1', 9 | 'jQuery 1.6.4', 10 | 'jQuery.Mobile 1.0', 11 | 'Prototype 1.7.0.0', 12 | 'Prototype 1.6.1', 13 | 'Ext Core 3.1.0', 14 | 'Ext Core 3.0.0', 15 | 'MooTools 1.4.1', 16 | 'MooTools 1.3.2', 17 | 'Backbone 0.5.3', 18 | 'Underscore 1.2.3' 19 | ]; 20 | 21 | function slug(name) { 22 | return name.toLowerCase().replace(/\s/g, '-'); 23 | } 24 | 25 | module.exports = FILES.map(function (file) { 26 | var astJson = fs.readFileSync(FILES_PATH + '/' + slug(file) + '-ast.json'); 27 | 28 | return JSON.parse(astJson); 29 | }); 30 | -------------------------------------------------------------------------------- /benchmark/index.js: -------------------------------------------------------------------------------- 1 | var Benchmark = require('benchmark'), 2 | escodegen = require('../'), 3 | old = require('./old.js'), 4 | esotope = require('esotope'), 5 | asts = require('./asts'); 6 | 7 | 8 | function cycle(codegen) { 9 | for (var i = 0; i < asts.length; i++) 10 | codegen.generate(asts[i]); 11 | } 12 | 13 | new Benchmark.Suite() 14 | .add('esotope', function () { 15 | cycle(esotope); 16 | }) 17 | 18 | .add('escodegen', function () { 19 | cycle(escodegen); 20 | }) 21 | 22 | .add('old', function () { 23 | cycle(old); 24 | }) 25 | 26 | .on('start', function () { 27 | console.log('Benchmarking...') 28 | }) 29 | 30 | .on('cycle', function (event) { 31 | console.log(event.target.toString()); 32 | }) 33 | 34 | .on('complete', function () { 35 | console.log('Fastest is ' + this.filter('fastest').pluck('name')); 36 | 37 | console.log('esotope is x' + (this[0].hz / this[1].hz).toFixed(2) + ' times faster vs escodegen.'); 38 | }) 39 | 40 | .run(); 41 | -------------------------------------------------------------------------------- /benchmark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark", 3 | "version": "0.1.0", 4 | "description": "Regression benchmarking. Compare speed with upstream npm version", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node index" 8 | }, 9 | "author": "Ivan Nikulin ", 10 | "license": "MIT", 11 | "dependencies": { 12 | "benchmark": "~1.0.0", 13 | "esotope": "*" 14 | }, 15 | "optionalDependencies": { 16 | "microtime": "~0.4.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /benchmark/trace_cycle.js: -------------------------------------------------------------------------------- 1 | var asts = require('./asts'), 2 | escodegen = require('../'); 3 | 4 | for (var j = 0; j < 50; j++) { 5 | for (var i = 0; i < asts.length; i++) 6 | escodegen.generate(asts[0]); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /benchmark/v8_trace: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | OUT_DIR="v8_trace_reports" 4 | 5 | rm -rf "$OUT_DIR" 6 | mkdir -p "$OUT_DIR" 7 | 8 | echo "Here we go..." 9 | 10 | LOG=$(node --trace-opt --trace-inlining --trace-deopt trace_cycle) 11 | 12 | echo "$LOG" | grep "disabled optimization for" > "$OUT_DIR/never_optimized.log" 13 | echo "$LOG" | grep "Did not inline" > "$OUT_DIR/not_inlined.log" 14 | echo "$LOG" | grep "DEOPT" > "$OUT_DIR/deoptimizations.log" 15 | 16 | echo "Done" 17 | 18 | 19 | -------------------------------------------------------------------------------- /benchmark/v8_trace_reports/deoptimizations.log: -------------------------------------------------------------------------------- 1 | [deoptimizing (DEOPT soft): begin 0x3d11a125 escapeString (opt #25) @21, FP to SP delta: 80] 2 | [deoptimizing (DEOPT soft): begin 0x3d11a289 generateLogicalOrBinaryExpression (opt #26) @80, FP to SP delta: 176] 3 | [deoptimizing (DEOPT soft): begin 0x3d11a149 join (opt #14) @18, FP to SP delta: 64] 4 | [deoptimizing (DEOPT lazy): begin 0x3d11a289 generateLogicalOrBinaryExpression (opt #26) @15, FP to SP delta: 176] 5 | [deoptimizing (DEOPT lazy): begin 0x3d11a289 generateLogicalOrBinaryExpression (opt #26) @74, FP to SP delta: 176] 6 | [deoptimizing (DEOPT soft): begin 0x3d11e9bd generateExpressionStatement (opt #17) @22, FP to SP delta: 52] 7 | [deoptimizing (DEOPT lazy): begin 0x3d11e9bd generateExpressionStatement (opt #17) @10, FP to SP delta: 52] 8 | [deoptimizing (DEOPT soft): begin 0x3d11a125 escapeString (opt #31) @19, FP to SP delta: 84] 9 | -------------------------------------------------------------------------------- /benchmark/v8_trace_reports/never_optimized.log: -------------------------------------------------------------------------------- 1 | [disabled optimization for 14D2E491 , reason: Call to a JavaScript runtime function] 2 | [disabled optimization for 14D2EF65 , reason: Call to a JavaScript runtime function] 3 | [disabled optimization for 14D312AD , reason: Inlined runtime function: ClassOf] 4 | [disabled optimization for 14D2EFF1 , reason: Call to a JavaScript runtime function] 5 | -------------------------------------------------------------------------------- /benchmark/v8_trace_reports/not_inlined.log: -------------------------------------------------------------------------------- 1 | Did not inline generateFunctionParams called from generateFunctionBody (target text too big). 2 | Did not inline escapeString called from generateLiteral (target text too big). 3 | Did not inline generateNumber called from generateLiteral (target text too big). 4 | Did not inline generateRegExp called from generateLiteral (target text too big). 5 | Did not inline escapeAllowedCharacter called from escapeString (target text too big). 6 | Did not inline isIdentifierCh called from join (cumulative AST node limit reached). 7 | Did not inline isWhitespace called from join (cumulative AST node limit reached). 8 | Did not inline isWhitespace called from join (cumulative AST node limit reached). 9 | Did not inline join called from generateIfStatement (cumulative AST node limit reached). 10 | Did not inline escapeAllowedCharacter called from escapeString (target text too big). 11 | Did not inline escapeAllowedCharacter called from escapeString (target text too big). 12 | Did not inline isIdentifierCh called from join (cumulative AST node limit reached). 13 | Did not inline isWhitespace called from join (cumulative AST node limit reached). 14 | Did not inline isWhitespace called from join (cumulative AST node limit reached). 15 | Did not inline generateForStatementIterator called from generateForInStatement (target text too big). 16 | Did not inline generateFunctionParams called from generateFunctionBody (target text too big). 17 | Did not inline exprToJs called from generateForStatementIterator (cumulative AST node limit reached). 18 | Did not inline join called from generateForStatementIterator (cumulative AST node limit reached). 19 | Did not inline adoptionPrefix called from generateForStatementIterator (cumulative AST node limit reached). 20 | Did not inline adoptionSuffix called from generateTryStatementHandlers (cumulative AST node limit reached). 21 | Did not inline adoptionPrefix called from generateTryStatement (cumulative AST node limit reached). 22 | Did not inline join called from generateTryStatement (cumulative AST node limit reached). 23 | Did not inline stmtToJs called from generateTryStatement (cumulative AST node limit reached). 24 | Did not inline getDefaultOptions called from generate (target text too big). 25 | -------------------------------------------------------------------------------- /bin/escodegen.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | Copyright (C) 2012 Yusuke Suzuki 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | /*jslint sloppy:true node:true */ 27 | 28 | var fs = require('fs'), 29 | path = require('path'), 30 | root = path.join(path.dirname(fs.realpathSync(__filename)), '..'), 31 | esprima = require('esprima'), 32 | escodegen = require(root), 33 | optionator = require('optionator')({ 34 | prepend: 'Usage: escodegen [options] file...', 35 | options: [ 36 | { 37 | option: 'config', 38 | alias: 'c', 39 | type: 'String', 40 | description: 'configuration json for escodegen' 41 | } 42 | ] 43 | }), 44 | args = optionator.parse(process.argv), 45 | files = args._, 46 | options, 47 | esprimaOptions = { 48 | raw: true, 49 | tokens: true, 50 | range: true, 51 | comment: true 52 | }; 53 | 54 | if (files.length === 0) { 55 | console.log(optionator.generateHelp()); 56 | process.exit(1); 57 | } 58 | 59 | if (args.config) { 60 | try { 61 | options = JSON.parse(fs.readFileSync(args.config, 'utf-8')); 62 | } catch (err) { 63 | console.error('Error parsing config: ', err); 64 | } 65 | } 66 | 67 | files.forEach(function (filename) { 68 | var content = fs.readFileSync(filename, 'utf-8'), 69 | syntax = esprima.parse(content, esprimaOptions); 70 | 71 | if (options.comment) { 72 | escodegen.attachComments(syntax, syntax.comments, syntax.tokens); 73 | } 74 | 75 | console.log(escodegen.generate(syntax, options)); 76 | }); 77 | /* vim: set sw=4 ts=4 et tw=80 : */ 78 | -------------------------------------------------------------------------------- /bin/esgenerate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | Copyright (C) 2012 Yusuke Suzuki 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | /*jslint sloppy:true node:true */ 27 | 28 | var fs = require('fs'), 29 | path = require('path'), 30 | root = path.join(path.dirname(fs.realpathSync(__filename)), '..'), 31 | escodegen = require(root), 32 | optionator = require('optionator')({ 33 | prepend: 'Usage: esgenerate [options] file.json ...', 34 | options: [ 35 | { 36 | option: 'config', 37 | alias: 'c', 38 | type: 'String', 39 | description: 'configuration json for escodegen' 40 | } 41 | ] 42 | }), 43 | args = optionator.parse(process.argv), 44 | files = args._, 45 | options; 46 | 47 | if (files.length === 0) { 48 | console.log(optionator.generateHelp()); 49 | process.exit(1); 50 | } 51 | 52 | if (args.config) { 53 | try { 54 | options = JSON.parse(fs.readFileSync(args.config, 'utf-8')) 55 | } catch (err) { 56 | console.error('Error parsing config: ', err); 57 | } 58 | } 59 | 60 | files.forEach(function (filename) { 61 | var content = fs.readFileSync(filename, 'utf-8'); 62 | console.log(escodegen.generate(JSON.parse(content), options)); 63 | }); 64 | /* vim: set sw=4 ts=4 et tw=80 : */ 65 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Yusuke Suzuki 3 | Copyright (C) 2019-2020 Apple Inc. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | 'use strict'; 27 | 28 | var gulp = require('gulp'); 29 | var mocha = require('gulp-mocha'); 30 | var eslint = require('gulp-eslint'); 31 | 32 | var TEST = [ 'test/*.js' ]; 33 | 34 | var LINT = [ 35 | 'gulpfile.js', 36 | 'escodegen.js' 37 | ]; 38 | 39 | var ESLINT_OPTION = { 40 | 'rulesPaths': [ 'tools/rules/' ], 41 | 'rules': { 42 | // 'push-with-multiple-arguments': 2, 43 | 'quotes': 0, 44 | 'eqeqeq': 0, 45 | 'no-use-before-define': 0, 46 | 'dot-notation': 0, 47 | 'no-shadow': 0, 48 | 'no-unused-vars': [ 49 | 2, 50 | { 51 | 'vars': 'all', 52 | 'args': 'none' 53 | } 54 | ], 55 | 'no-multi-spaces': 0, 56 | 'new-cap': [ 57 | 2, 58 | { 59 | 'capIsNew': false 60 | } 61 | ] 62 | }, 63 | 'env': { 64 | 'node': true 65 | } 66 | }; 67 | 68 | gulp.task('test', gulp.series(function () { 69 | return gulp.src(TEST) 70 | .pipe(mocha({ 71 | reporter: 'spec', 72 | timeout: 100000 // 100s 73 | })); 74 | })); 75 | 76 | gulp.task('lint', gulp.series(function () { 77 | return gulp.src(LINT) 78 | .pipe(eslint(ESLINT_OPTION)) 79 | .pipe(eslint.formatEach('stylish', process.stderr)) 80 | .pipe(eslint.failOnError()); 81 | })); 82 | 83 | gulp.task('travis', gulp.series([ 'lint', 'test' ])); 84 | gulp.task('default', gulp.series([ 'travis' ])); 85 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "escodegen", 3 | "description": "ECMAScript code generator", 4 | "homepage": "http://github.com/estools/escodegen", 5 | "main": "escodegen.js", 6 | "bin": { 7 | "esgenerate": "./bin/esgenerate.js", 8 | "escodegen": "./bin/escodegen.js" 9 | }, 10 | "files": [ 11 | "LICENSE.BSD", 12 | "README.md", 13 | "bin", 14 | "escodegen.js", 15 | "package.json" 16 | ], 17 | "version": "2.1.0", 18 | "engines": { 19 | "node": ">=6.0" 20 | }, 21 | "maintainers": [ 22 | { 23 | "name": "Yusuke Suzuki", 24 | "email": "utatane.tea@gmail.com", 25 | "web": "http://github.com/Constellation" 26 | } 27 | ], 28 | "repository": { 29 | "type": "git", 30 | "url": "http://github.com/estools/escodegen.git" 31 | }, 32 | "dependencies": { 33 | "estraverse": "^5.2.0", 34 | "esutils": "^2.0.2", 35 | "esprima": "^4.0.1" 36 | }, 37 | "optionalDependencies": { 38 | "source-map": "~0.6.1" 39 | }, 40 | "devDependencies": { 41 | "acorn": "^8.0.4", 42 | "bluebird": "^3.4.7", 43 | "bower-registry-client": "^1.0.0", 44 | "chai": "^4.2.0", 45 | "chai-exclude": "^2.0.2", 46 | "commonjs-everywhere": "^0.9.7", 47 | "gulp": "^4.0.2", 48 | "gulp-eslint": "^6.0.0", 49 | "gulp-mocha": "^7.0.2", 50 | "minimist": "^1.2.5", 51 | "optionator": "^0.9.1", 52 | "semver": "^7.3.4" 53 | }, 54 | "license": "BSD-2-Clause", 55 | "scripts": { 56 | "test": "gulp travis", 57 | "unit-test": "gulp test", 58 | "lint": "gulp lint", 59 | "release": "node tools/release.js", 60 | "build-min": "./node_modules/.bin/cjsify -ma path: tools/entry-point.js > escodegen.browser.min.js", 61 | "build": "./node_modules/.bin/cjsify -a path: tools/entry-point.js > escodegen.browser.js" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test/api.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var esprima = require('./3rdparty/esprima-1.0.0-dev'), 28 | escodegen = require('./loader'), 29 | chai = require('chai'), 30 | expect = chai.expect, 31 | fixtures; 32 | 33 | function slug(name) { 34 | return name.toLowerCase().replace(/\s/g, '-'); 35 | } 36 | 37 | function adjustRegexLiteral(key, value) { 38 | if (key === 'value' && value instanceof RegExp) { 39 | value = value.toString(); 40 | } 41 | return value; 42 | } 43 | 44 | fixtures = { 45 | 'generate with no options': { 46 | call: 'generate', 47 | args: [{ 48 | type: 'Program', 49 | body: [{ 50 | type: 'BlockStatement', 51 | body: [{ 52 | type: 'ExpressionStatement', 53 | expression: { 54 | type: 'Identifier', 55 | name: 'test' 56 | } 57 | }] 58 | }] 59 | }], 60 | result: '{\n test;\n}' 61 | }, 62 | 'generate with indent 2': { 63 | call: 'generate', 64 | args: [{ 65 | type: 'Program', 66 | body: [{ 67 | type: 'BlockStatement', 68 | body: [{ 69 | type: 'ExpressionStatement', 70 | expression: { 71 | type: 'Identifier', 72 | name: 'test' 73 | } 74 | }] 75 | }] 76 | }, { 77 | format: { 78 | indent: { 79 | style: ' ' 80 | } 81 | } 82 | }], 83 | result: '{\n test;\n}' 84 | }, 85 | 'generate with base 2': { 86 | call: 'generate', 87 | args: [{ 88 | type: 'Program', 89 | body: [{ 90 | type: 'BlockStatement', 91 | body: [{ 92 | type: 'ExpressionStatement', 93 | expression: { 94 | type: 'Identifier', 95 | name: 'test' 96 | } 97 | }] 98 | }] 99 | }, { 100 | format: { 101 | indent: { 102 | base: 2 103 | } 104 | } 105 | }], 106 | result: ' {\n test;\n }' 107 | }, 108 | 'generate with base 2 + indent 2': { 109 | call: 'generate', 110 | args: [{ 111 | type: 'Program', 112 | body: [{ 113 | type: 'BlockStatement', 114 | body: [{ 115 | type: 'ExpressionStatement', 116 | expression: { 117 | type: 'Identifier', 118 | name: 'test' 119 | } 120 | }] 121 | }] 122 | }, { 123 | format: { 124 | indent: { 125 | style: ' ', 126 | base: 2 127 | } 128 | } 129 | }], 130 | result: ' {\n test;\n }' 131 | }, 132 | 133 | // obsolete api 134 | 'obsolete generate with base 2': { 135 | call: 'generate', 136 | args: [{ 137 | type: 'Program', 138 | body: [{ 139 | type: 'BlockStatement', 140 | body: [{ 141 | type: 'ExpressionStatement', 142 | expression: { 143 | type: 'Identifier', 144 | name: 'test' 145 | } 146 | }] 147 | }] 148 | }, { 149 | base: ' ' 150 | }], 151 | result: ' {\n test;\n }' 152 | }, 153 | 154 | 'obsolete generate with indent 2': { 155 | call: 'generate', 156 | args: [{ 157 | type: 'Program', 158 | body: [{ 159 | type: 'BlockStatement', 160 | body: [{ 161 | type: 'ExpressionStatement', 162 | expression: { 163 | type: 'Identifier', 164 | name: 'test' 165 | } 166 | }] 167 | }] 168 | }, { 169 | indent: ' ', 170 | }], 171 | result: '{\n test;\n}' 172 | }, 173 | 174 | 'obsolete generate with base 2 + indent 2': { 175 | call: 'generate', 176 | args: [{ 177 | type: 'Program', 178 | body: [{ 179 | type: 'BlockStatement', 180 | body: [{ 181 | type: 'ExpressionStatement', 182 | expression: { 183 | type: 'Identifier', 184 | name: 'test' 185 | } 186 | }] 187 | }] 188 | }, { 189 | indent: ' ', 190 | base: ' ' 191 | }], 192 | result: ' {\n test;\n }' 193 | } 194 | }; 195 | 196 | function testAPI(code, result) { 197 | var expected, res, actual; 198 | expected = JSON.stringify(result.result, null, 4); 199 | if (typeof result.property !== 'undefined') { 200 | res = escodegen[result.property]; 201 | } else { 202 | res = escodegen[result.call].apply(escodegen, result.args); 203 | } 204 | actual = JSON.stringify(res, adjustRegexLiteral, 4); 205 | expect(actual).to.be.equal(expected); 206 | } 207 | 208 | describe('API test', function () { 209 | Object.keys(fixtures).forEach(function(key) { 210 | it(key, function () { 211 | testAPI(key, fixtures[key]); 212 | }); 213 | }); 214 | }); 215 | /* vim: set sw=4 ts=4 et tw=80 : */ 216 | -------------------------------------------------------------------------------- /test/ast.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var data, 28 | esprima = require('./3rdparty/esprima-1.0.0-dev'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | data = { 34 | 'RegExp string': [ 35 | { 36 | type: 'Program', 37 | body: [{ 38 | type: 'ExpressionStatement', 39 | expression: { 40 | type: 'Literal', 41 | value: new RegExp('///') 42 | }, 43 | }], 44 | expected: '/\\/\\/\\//;' 45 | }, 46 | { 47 | type: 'Program', 48 | body: [{ 49 | type: 'ExpressionStatement', 50 | expression: { 51 | type: 'Literal', 52 | value: new RegExp('///', 'i') 53 | }, 54 | }], 55 | expected: '/\\/\\/\\//i;' 56 | }, 57 | { 58 | type: 'Program', 59 | body: [{ 60 | type: 'ExpressionStatement', 61 | expression: { 62 | type: 'Literal', 63 | value: new RegExp('\n', 'i') 64 | }, 65 | }], 66 | expected: '/\\n/i;' 67 | }, 68 | { 69 | type: 'Program', 70 | body: [{ 71 | type: 'ExpressionStatement', 72 | expression: { 73 | type: 'Literal', 74 | value: new RegExp('\r', 'i') 75 | }, 76 | }], 77 | expected: '/\\r/i;' 78 | }, 79 | { 80 | type: 'Program', 81 | body: [{ 82 | type: 'ExpressionStatement', 83 | expression: { 84 | type: 'Literal', 85 | value: new RegExp('\u2028', 'i') 86 | }, 87 | }], 88 | expected: '/\\u2028/i;' 89 | }, 90 | { 91 | type: 'Program', 92 | body: [{ 93 | type: 'ExpressionStatement', 94 | expression: { 95 | type: 'Literal', 96 | value: new RegExp('\u2029', 'i') 97 | }, 98 | }], 99 | expected: '/\\u2029/i;' 100 | }, 101 | { 102 | type: 'Program', 103 | body: [{ 104 | type: 'ExpressionStatement', 105 | expression: { 106 | type: 'Literal', 107 | value: new RegExp('\\\\', 'i') 108 | }, 109 | }], 110 | expected: '/\\\\/i;' 111 | }, 112 | { 113 | type: 'Program', 114 | body: [{ 115 | type: 'ExpressionStatement', 116 | expression: { 117 | type: 'Literal', 118 | value: new RegExp('\\\u2028', 'i') 119 | }, 120 | }], 121 | expected: '/\\u2028/i;' 122 | }, 123 | { 124 | type: 'Program', 125 | body: [{ 126 | type: 'ExpressionStatement', 127 | expression: { 128 | type: 'Literal', 129 | value: new RegExp('\\\\u2028', 'i') 130 | }, 131 | }], 132 | expected: '/\\\\u2028/i;' 133 | }, 134 | { 135 | type: 'Program', 136 | body: [{ 137 | type: 'ExpressionStatement', 138 | expression: { 139 | type: 'Literal', 140 | value: { 141 | toString: function() { return new RegExp('', 'i').toString(); }, 142 | source: '' 143 | } 144 | }, 145 | }], 146 | expected: '/(?:)/i;' 147 | }, 148 | { 149 | type: 'Program', 150 | body: [{ 151 | type: 'ExpressionStatement', 152 | expression: { 153 | type: 'MemberExpression', 154 | computed: false, 155 | object: { 156 | type: 'Literal', 157 | value: 1, 158 | raw: '1' 159 | }, 160 | property: { 161 | type: 'Identifier', 162 | name: 'a' 163 | } 164 | } 165 | }], 166 | expected: '1 .a;' 167 | }, 168 | ] 169 | }; 170 | 171 | function runTest(ast, expected) { 172 | var actual, options; 173 | 174 | options = { 175 | indent: ' ', 176 | parse: esprima.parse 177 | }; 178 | 179 | actual = escodegen.generate(ast, options); 180 | expect(actual).to.be.equal(expected); 181 | } 182 | 183 | describe('AST', function () { 184 | Object.keys(data).forEach(function (category) { 185 | it(category + ' test', function () { 186 | data[category].forEach(function (ast) { 187 | runTest(ast, ast.expected); 188 | }); 189 | }); 190 | }); 191 | }); 192 | /* vim: set sw=4 ts=4 et tw=80 : */ 193 | -------------------------------------------------------------------------------- /test/comment.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | esprima = require('./3rdparty/esprima-harmony.original'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | function test(code, expected) { 34 | var tree, actual, options, StringObject; 35 | 36 | // alias, so that JSLint does not complain. 37 | StringObject = String; 38 | 39 | options = { 40 | comment: true, 41 | range: true, 42 | loc: false, 43 | tokens: true, 44 | raw: false 45 | }; 46 | 47 | tree = esprima.parse(code, options); 48 | tree = escodegen.attachComments(tree, tree.comments, tree.tokens); 49 | 50 | // for UNIX text comment 51 | actual = escodegen.generate(tree, { 52 | comment: true, 53 | format: { 54 | indent: { 55 | adjustMultilineComment: true 56 | } 57 | } 58 | }).replace(/[\n\r]$/, '') + '\n'; 59 | expect(actual).to.be.equal(expected); 60 | } 61 | 62 | describe('comment test', function () { 63 | fs.readdirSync(__dirname + '/comment').sort().forEach(function(file) { 64 | var code, expected, p; 65 | if (/\.js$/.test(file) && !/expected\.js$/.test(file)) { 66 | it(file, function () { 67 | p = file.replace(/\.js$/, '.expected.js'); 68 | code = fs.readFileSync(__dirname + '/comment/' + file, 'utf-8'); 69 | expected = fs.readFileSync(__dirname + '/comment/' + p, 'utf-8'); 70 | test(code, expected); 71 | }); 72 | } 73 | }); 74 | }); 75 | /* vim: set sw=4 ts=4 et tw=80 : */ 76 | -------------------------------------------------------------------------------- /test/comment/2-space-multi-comment.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | /* 3 | * this is comment 4 | */ 5 | var i = 20; 6 | } 7 | -------------------------------------------------------------------------------- /test/comment/2-space-multi-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | /* 3 | * this is comment 4 | */ 5 | var i = 20; 6 | } 7 | -------------------------------------------------------------------------------- /test/comment/block-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | // Leading to block 2 | { 3 | print('hello'); 4 | } 5 | -------------------------------------------------------------------------------- /test/comment/block-line-comment.js: -------------------------------------------------------------------------------- 1 | // Leading to block 2 | { 3 | print('hello'); 4 | } 5 | -------------------------------------------------------------------------------- /test/comment/comment-only.expected.js: -------------------------------------------------------------------------------- 1 | // from #23 2 | /**/ 3 | /* 4 | */ 5 | -------------------------------------------------------------------------------- /test/comment/comment-only.js: -------------------------------------------------------------------------------- 1 | // from #23 2 | /**/ 3 | /* 4 | */ 5 | -------------------------------------------------------------------------------- /test/comment/computed-property-comments-2.expected.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Before bracket init 4 | */ 5 | ['a']: '1', 6 | [/* 7 | * Inside bracket init 8 | */ 9 | 'b']: '2' 10 | }, ok = 42; 11 | -------------------------------------------------------------------------------- /test/comment/computed-property-comments-2.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Before bracket init 4 | */ 5 | ['a']:'1', 6 | [/* 7 | * Inside bracket init 8 | */ 9 | 'b']:'2' 10 | }, ok = 42; 11 | -------------------------------------------------------------------------------- /test/comment/computed-property-comments.expected.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Before bracket init 4 | */ 5 | ['a']: '1', 6 | [/* 7 | * Inside bracket init 8 | */ 9 | 'b']: '2', 10 | ['c' /* 11 | * After bracket key 12 | */]: '3', 13 | // Before bracket, line comment 14 | ['d']: '4', 15 | [// Inside bracket, line comment 16 | 'e']: '5', 17 | ['f' // After bracket, line comment 18 | ]: '6' 19 | }; 20 | -------------------------------------------------------------------------------- /test/comment/computed-property-comments.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Before bracket init 4 | */ 5 | ['a']:'1', 6 | 7 | [/* 8 | * Inside bracket init 9 | */ 10 | 'b']:'2', 11 | 12 | ['c' 13 | /* 14 | * After bracket key 15 | */]:'3', 16 | 17 | // Before bracket, line comment 18 | [ 19 | 'd']:'4', 20 | 21 | [ 22 | // Inside bracket, line comment 23 | 'e']:'5', 24 | 25 | ['f' 26 | // After bracket, line comment 27 | ]:'6' 28 | }; 29 | -------------------------------------------------------------------------------- /test/comment/do-while-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | do { 2 | } // LINE 3 | while (true); 4 | -------------------------------------------------------------------------------- /test/comment/do-while-line-comment.js: -------------------------------------------------------------------------------- 1 | do { 2 | } // LINE 3 | while (true); 4 | -------------------------------------------------------------------------------- /test/comment/empty-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | // Leading to EmptyStatement 3 | ; // Trailing to EmptyStatement 4 | } 5 | -------------------------------------------------------------------------------- /test/comment/empty-line-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | // Leading to EmptyStatement 3 | ; 4 | // Trailing to EmptyStatement 5 | } 6 | -------------------------------------------------------------------------------- /test/comment/empty.expected.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/comment/empty.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /test/comment/function-block-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | !function () { 2 | } // 3 | , 42; 4 | !{ 5 | get 42() { 6 | } // 7 | , 8 | foo: 42 9 | }; 10 | (function () { 11 | } // 12 | ); 13 | -------------------------------------------------------------------------------- /test/comment/function-block-line-comment.js: -------------------------------------------------------------------------------- 1 | !function(){}// 2 | ,42; 3 | !{get 42(){}// 4 | ,foo:42}; 5 | (function(){}// 6 | ) 7 | -------------------------------------------------------------------------------- /test/comment/if-block-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | if (cond) 2 | // Leading to if-block 3 | { 4 | print('hello'); 5 | } // Trailing to if-block 6 | -------------------------------------------------------------------------------- /test/comment/if-block-line-comment.js: -------------------------------------------------------------------------------- 1 | if (cond) 2 | // Leading to if-block 3 | { 4 | print('hello'); 5 | } // Trailing to if-block 6 | -------------------------------------------------------------------------------- /test/comment/if-empty-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | if (cond) 2 | // Leading to EmptyStatement 3 | ; // Trailing to EmptyStatement 4 | -------------------------------------------------------------------------------- /test/comment/if-empty-line-comment.js: -------------------------------------------------------------------------------- 1 | if (cond) 2 | // Leading to EmptyStatement 3 | ; // Trailing to EmptyStatement 4 | -------------------------------------------------------------------------------- /test/comment/if-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | // Leading if statement 3 | if (cond) { 4 | print('hello'); 5 | } // Trailing if-block statement 6 | } 7 | -------------------------------------------------------------------------------- /test/comment/if-line-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | // Leading if statement 3 | if (cond) {print('hello') } 4 | // Trailing if-block statement 5 | } 6 | -------------------------------------------------------------------------------- /test/comment/object_comments.expected.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Test 2 4 | */ 5 | a: '1', 6 | /* 7 | * Test 1 8 | */ 9 | b: '2', 10 | // Test 3 11 | c: '3' 12 | }; 13 | -------------------------------------------------------------------------------- /test/comment/object_comments.js: -------------------------------------------------------------------------------- 1 | var test = { 2 | /** 3 | * Test 2 4 | */ 5 | a:'1', 6 | /* 7 | * Test 1 8 | */ 9 | b:'2', 10 | // Test 3 11 | c:'3' 12 | }; -------------------------------------------------------------------------------- /test/comment/return-no-argument.expected.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | return; // comment 3 | }()); 4 | -------------------------------------------------------------------------------- /test/comment/return-no-argument.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | return; // comment 3 | }()); 4 | -------------------------------------------------------------------------------- /test/comment/simple-a-lot-of-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Yusuke Suzuki 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above copyright 9 | // notice, this list of conditions and the following disclaimer in the 10 | // documentation and/or other materials provided with the distribution. 11 | // 12 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 16 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | function test() { 23 | } // Copyright (C) 2012 Yusuke Suzuki 24 | // 25 | // Redistribution and use in source and binary forms, with or without 26 | // modification, are permitted provided that the following conditions are met: 27 | // 28 | // * Redistributions of source code must retain the above copyright 29 | // notice, this list of conditions and the following disclaimer. 30 | // * Redistributions in binary form must reproduce the above copyright 31 | // notice, this list of conditions and the following disclaimer in the 32 | // documentation and/or other materials provided with the distribution. 33 | // 34 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 35 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 38 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 39 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 40 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 41 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 42 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 43 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | -------------------------------------------------------------------------------- /test/comment/simple-a-lot-of-line-comment.js: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Yusuke Suzuki 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are met: 5 | // 6 | // * Redistributions of source code must retain the above copyright 7 | // notice, this list of conditions and the following disclaimer. 8 | // * Redistributions in binary form must reproduce the above copyright 9 | // notice, this list of conditions and the following disclaimer in the 10 | // documentation and/or other materials provided with the distribution. 11 | // 12 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 16 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | 23 | 24 | function test() { 25 | } 26 | 27 | 28 | 29 | // Copyright (C) 2012 Yusuke Suzuki 30 | // 31 | // Redistribution and use in source and binary forms, with or without 32 | // modification, are permitted provided that the following conditions are met: 33 | // 34 | // * Redistributions of source code must retain the above copyright 35 | // notice, this list of conditions and the following disclaimer. 36 | // * Redistributions in binary form must reproduce the above copyright 37 | // notice, this list of conditions and the following disclaimer in the 38 | // documentation and/or other materials provided with the distribution. 39 | // 40 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 41 | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 | // ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 44 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 45 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 47 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 48 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 49 | // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 50 | -------------------------------------------------------------------------------- /test/comment/simple-a-lot-of-multi-comment.expected.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | function test() { 25 | } /* 26 | Copyright (C) 2012 Yusuke Suzuki 27 | 28 | Redistribution and use in source and binary forms, with or without 29 | modification, are permitted provided that the following conditions are met: 30 | 31 | * Redistributions of source code must retain the above copyright 32 | notice, this list of conditions and the following disclaimer. 33 | * Redistributions in binary form must reproduce the above copyright 34 | notice, this list of conditions and the following disclaimer in the 35 | documentation and/or other materials provided with the distribution. 36 | 37 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 38 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 41 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 46 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | */ 48 | -------------------------------------------------------------------------------- /test/comment/simple-a-lot-of-multi-comment.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 26 | 27 | 28 | function test() { } 29 | 30 | 31 | 32 | 33 | 34 | /* 35 | Copyright (C) 2012 Yusuke Suzuki 36 | 37 | Redistribution and use in source and binary forms, with or without 38 | modification, are permitted provided that the following conditions are met: 39 | 40 | * Redistributions of source code must retain the above copyright 41 | notice, this list of conditions and the following disclaimer. 42 | * Redistributions in binary form must reproduce the above copyright 43 | notice, this list of conditions and the following disclaimer in the 44 | documentation and/or other materials provided with the distribution. 45 | 46 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 47 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 50 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 51 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 52 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 53 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 | */ 57 | -------------------------------------------------------------------------------- /test/comment/simple-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | // Leading 2 | var i = 20; // Trailing 3 | -------------------------------------------------------------------------------- /test/comment/simple-line-comment.js: -------------------------------------------------------------------------------- 1 | // Leading 2 | var i = 20; 3 | // Trailing 4 | -------------------------------------------------------------------------------- /test/comment/simple-multi-comment.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | /* 3 | * Leading comment 4 | */ 5 | /* 6 | * 7 | * Leading comment 2 8 | * 9 | */ 10 | var i = 20; /* 11 | * Trailing comment 12 | */ 13 | /* 14 | * 15 | * Trailing comment 2 16 | * 17 | */ 18 | } 19 | -------------------------------------------------------------------------------- /test/comment/simple-multi-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | /* 3 | * Leading comment 4 | */ 5 | 6 | /* 7 | * 8 | * Leading comment 2 9 | * 10 | */ 11 | 12 | var i = 20; 13 | /* 14 | * Trailing comment 15 | */ 16 | 17 | /* 18 | * 19 | * Trailing comment 2 20 | * 21 | */ 22 | } 23 | -------------------------------------------------------------------------------- /test/comment/simple-statement-comment.expected.js: -------------------------------------------------------------------------------- 1 | ; // Trailing 2 | -------------------------------------------------------------------------------- /test/comment/simple-statement-comment.js: -------------------------------------------------------------------------------- 1 | ; // Trailing 2 | -------------------------------------------------------------------------------- /test/comment/try-block-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | try { 2 | } // 3 | finally { 4 | } 5 | try { 6 | } catch (e) { 7 | } finally { 8 | } 9 | { 10 | try { 11 | } catch (e) { 12 | } finally { 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/comment/try-block-line-comment.js: -------------------------------------------------------------------------------- 1 | try{}// 2 | finally{} 3 | 4 | try{} 5 | catch(e){}// 6 | finally{} 7 | 8 | { 9 | try{} 10 | catch(e){}// 11 | finally{} 12 | } 13 | -------------------------------------------------------------------------------- /test/comment/variable-declarator-line-comment.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | var 3 | // Leading to VariableDeclarator 4 | // Leading to VariableDeclarator 5 | i = 20, 6 | // Leading to VariableDeclarator 7 | // Leading to VariableDeclarator 8 | j = 20; 9 | } 10 | -------------------------------------------------------------------------------- /test/comment/variable-declarator-line-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | var 3 | // Leading to VariableDeclarator 4 | // Leading to VariableDeclarator 5 | i = 20, 6 | // Leading to VariableDeclarator 7 | // Leading to VariableDeclarator 8 | j = 20; 9 | } 10 | -------------------------------------------------------------------------------- /test/comment/variable-declarator-multi-comment.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | var 3 | /* 4 | * Leading to VariableDeclarator 5 | * Leading to VariableDeclarator 6 | */ 7 | i = 20, 8 | /* 9 | * Leading to VariableDeclarator 10 | * Leading to VariableDeclarator 11 | */ 12 | j = 20; 13 | } 14 | -------------------------------------------------------------------------------- /test/comment/variable-declarator-multi-comment.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | var 3 | /* 4 | * Leading to VariableDeclarator 5 | * Leading to VariableDeclarator 6 | */ 7 | i = 20, 8 | /* 9 | * Leading to VariableDeclarator 10 | * Leading to VariableDeclarator 11 | */ 12 | j = 20; 13 | } 14 | -------------------------------------------------------------------------------- /test/comment/variable-declarator-trailing-comment.expected.js: -------------------------------------------------------------------------------- 1 | { 2 | var t = 20; /* 3 | * This is trailing comment 4 | */ 5 | } 6 | { 7 | var tt = 20; /* 8 | * This is trailing comment 9 | */ 10 | } 11 | { 12 | { 13 | var t = 20; /* 14 | * This is trailing comment 15 | */ 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/comment/variable-declarator-trailing-comment.js: -------------------------------------------------------------------------------- 1 | { 2 | var t = 20; /* 3 | * This is trailing comment 4 | */ 5 | } 6 | 7 | { 8 | var tt = 20; /* 9 | * This is trailing comment 10 | */ 11 | } 12 | {{ 13 | var t = 20; /* 14 | * This is trailing comment 15 | */ 16 | }} 17 | -------------------------------------------------------------------------------- /test/compare-acorn-es2019.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | acorn = require('acorn'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | function test(code, expected) { 34 | var tree, actual, options, StringObject; 35 | 36 | // alias, so that JSLint does not complain. 37 | StringObject = String; 38 | 39 | options = { 40 | ranges: true, 41 | locations: false, 42 | ecmaVersion: 10 43 | }; 44 | 45 | tree = acorn.parse(code, options); 46 | 47 | // for UNIX text comment 48 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 49 | expect(actual).to.be.equal(expected); 50 | } 51 | 52 | function testMin(code, expected) { 53 | var tree, actual, options, StringObject; 54 | 55 | // alias, so that JSLint does not complain. 56 | StringObject = String; 57 | 58 | options = { 59 | ranges: true, 60 | locations: false, 61 | ecmaVersion: 10 62 | }; 63 | 64 | tree = acorn.parse(code, options); 65 | 66 | // for UNIX text comment 67 | actual = escodegen.generate(tree, { 68 | format: escodegen.FORMAT_MINIFY, 69 | raw: false 70 | }).replace(/[\n\r]$/, '') + '\n'; 71 | expect(actual).to.be.equal(expected); 72 | } 73 | 74 | describe('compare acorn es2019 test', function () { 75 | fs.readdirSync(__dirname + '/compare-acorn-es2019').sort().forEach(function(file) { 76 | var code, expected, exp, min; 77 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 78 | it(file, function () { 79 | exp = file.replace(/\.js$/, '.expected.js'); 80 | min = file.replace(/\.js$/, '.expected.min.js'); 81 | code = fs.readFileSync(__dirname + '/compare-acorn-es2019/' + file, 'utf-8'); 82 | expected = fs.readFileSync(__dirname + '/compare-acorn-es2019/' + exp, 'utf-8'); 83 | test(code, expected); 84 | if (fs.existsSync(__dirname + '/compare-acorn-es2019/' + min)) { 85 | expected = fs.readFileSync(__dirname + '/compare-acorn-es2019/' + min, 'utf-8'); 86 | testMin(code, expected); 87 | } 88 | }); 89 | } 90 | }); 91 | }); 92 | /* vim: set sw=4 ts=4 et tw=80 : */ 93 | -------------------------------------------------------------------------------- /test/compare-acorn-es2019/optional-catch-binding.expected.js: -------------------------------------------------------------------------------- 1 | try { 2 | } catch { 3 | } 4 | -------------------------------------------------------------------------------- /test/compare-acorn-es2019/optional-catch-binding.expected.min.js: -------------------------------------------------------------------------------- 1 | try{}catch{} 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es2019/optional-catch-binding.js: -------------------------------------------------------------------------------- 1 | try { 2 | } catch { 3 | } 4 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | acorn = require('acorn'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | chaiExclude = require('chai-exclude'), 32 | expect = chai.expect; 33 | 34 | chai.use(chaiExclude); 35 | 36 | function test(code, expected) { 37 | var tree, actual, actualTree, options; 38 | 39 | options = { 40 | ranges: false, 41 | locations: false, 42 | ecmaVersion: 11 43 | }; 44 | 45 | tree = acorn.parse(code, options); 46 | 47 | // for UNIX text comment 48 | actual = escodegen.generate(tree); 49 | actualTree = acorn.parse(actual, options); 50 | 51 | expect(actual).to.be.equal(expected); 52 | expect(tree).excludingEvery(['start', 'end', 'raw']).to.deep.equal(actualTree); 53 | } 54 | 55 | function testMin(code, expected) { 56 | var tree, actual, actualTree, options; 57 | 58 | options = { 59 | ranges: false, 60 | locations: false, 61 | ecmaVersion: 11 62 | }; 63 | 64 | tree = acorn.parse(code, options); 65 | 66 | // for UNIX text comment 67 | actual = escodegen.generate(tree, { 68 | format: escodegen.FORMAT_MINIFY, 69 | raw: false 70 | }).replace(/[\n\r]$/, '') + '\n'; 71 | actualTree = acorn.parse(actual, options); 72 | 73 | expect(actual).to.be.equal(expected); 74 | expect(tree).excludingEvery(['start', 'end', 'raw']).to.deep.equal(actualTree); 75 | } 76 | 77 | describe('compare acorn es2020 test', function () { 78 | fs.readdirSync(__dirname + '/compare-acorn-es2020').sort().forEach(function(file) { 79 | var code, expected, exp, min; 80 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 81 | it(file, function () { 82 | exp = file.replace(/\.js$/, '.expected.js'); 83 | min = file.replace(/\.js$/, '.expected.min.js'); 84 | code = fs.readFileSync(__dirname + '/compare-acorn-es2020/' + file, 'utf-8'); 85 | expected = fs.readFileSync(__dirname + '/compare-acorn-es2020/' + exp, 'utf-8'); 86 | test(code, expected); 87 | if (fs.existsSync(__dirname + '/compare-acorn-es2020/' + min)) { 88 | expected = fs.readFileSync(__dirname + '/compare-acorn-es2020/' + min, 'utf-8'); 89 | testMin(code, expected); 90 | } 91 | }); 92 | } 93 | }); 94 | }); 95 | /* vim: set sw=4 ts=4 et tw=80 : */ 96 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/bigint.expected.js: -------------------------------------------------------------------------------- 1 | 2000n + 30; 2 | 20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n + 30; 3 | -20000000000000000000000000000n; -------------------------------------------------------------------------------- /test/compare-acorn-es2020/bigint.expected.min.js: -------------------------------------------------------------------------------- 1 | 2000n+30;20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n+30;-20000000000000000000000000000n 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/bigint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Apple Inc. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice, this list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright 10 | * notice, this list of conditions and the following disclaimer in the 11 | * documentation and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 | * THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | 2000n + 30; 27 | 20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000n + 30; 28 | -20000000000000000000000000000n; 29 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/nullish-coalescing.expected.js: -------------------------------------------------------------------------------- 1 | function testBasicCases() { 2 | shouldBe(undefined ?? 3, 3); 3 | shouldBe(null ?? 3, 3); 4 | shouldBe(true ?? 3, true); 5 | shouldBe(false ?? 3, false); 6 | shouldBe(0 ?? 3, 0); 7 | shouldBe(1 ?? 3, 1); 8 | shouldBe('' ?? 3, ''); 9 | shouldBe('hi' ?? 3, 'hi'); 10 | shouldBe(({} ?? 3) instanceof Object, true); 11 | shouldBe(({ x: 'hi' } ?? 3).x, 'hi'); 12 | shouldBe(([] ?? 3) instanceof Array, true); 13 | shouldBe((['hi'] ?? 3)[0], 'hi'); 14 | shouldBe((makeMasquerader() ?? 3) == null, true); 15 | } 16 | noInline(testBasicCases); 17 | for (let i = 0; i < 100000; i++) 18 | testBasicCases(); 19 | shouldBe(1 | null ?? 3, 1); 20 | shouldBe(1 ^ null ?? 3, 1); 21 | shouldBe(1 & null ?? 3, 0); 22 | shouldBe(3 == null ?? 3, false); 23 | shouldBe(3 != null ?? 3, true); 24 | shouldBe(3 === null ?? 3, false); 25 | shouldBe(3 !== null ?? 3, true); 26 | shouldBe(1 < null ?? 3, false); 27 | shouldBe(1 > null ?? 3, true); 28 | shouldBe(1 <= null ?? 3, false); 29 | shouldBe(1 >= null ?? 3, true); 30 | shouldBe(1 << null ?? 3, 1); 31 | shouldBe(1 >> null ?? 3, 1); 32 | shouldBe(1 >>> null ?? 3, 1); 33 | shouldBe(1 + null ?? 3, 1); 34 | shouldBe(1 - null ?? 3, 1); 35 | shouldBe(1 * null ?? 3, 0); 36 | shouldBe(1 / null ?? 3, Infinity); 37 | shouldBe(isNaN(1 % null ?? 3), true); 38 | shouldBe(1 ** null ?? 3, 1); 39 | const obj = { 40 | count: 0, 41 | get x() { 42 | this.count++; 43 | return 'x'; 44 | } 45 | }; 46 | false ?? obj.x; 47 | shouldBe(obj.count, 0); 48 | null ?? obj.x; 49 | shouldBe(obj.count, 1); 50 | obj.x ?? obj.x; 51 | shouldBe(obj.count, 2); 52 | (0 || 1) ?? 2; 53 | 0 || (1 ?? 2); 54 | (0 && 1) ?? 2; 55 | 0 && (1 ?? 2); 56 | (0 ?? 1) || 2; 57 | 0 ?? (1 || 2); 58 | (0 ?? 1) && 2; 59 | 0 ?? (1 && 2); 60 | 0 || 1 && 2 | 3 ^ 4 & 5 == 6 != 7 === 8 !== 9 < 0 > 1 <= 2 >= 3 << 4 >> 5 >>> 6 + 7 - 8 * 9 / 0 % 1 ** 2; -------------------------------------------------------------------------------- /test/compare-acorn-es2020/nullish-coalescing.expected.min.js: -------------------------------------------------------------------------------- 1 | function testBasicCases(){shouldBe(undefined??3,3);shouldBe(null??3,3);shouldBe(true??3,true);shouldBe(false??3,false);shouldBe(0??3,0);shouldBe(1??3,1);shouldBe(''??3,'');shouldBe('hi'??3,'hi');shouldBe(({}??3)instanceof Object,true);shouldBe(({x:'hi'}??3).x,'hi');shouldBe(([]??3)instanceof Array,true);shouldBe((['hi']??3)[0],'hi');shouldBe((makeMasquerader()??3)==null,true)}noInline(testBasicCases);for(let i=0;i<1e5;i++)testBasicCases();shouldBe(1|null??3,1);shouldBe(1^null??3,1);shouldBe(1&null??3,0);shouldBe(3==null??3,false);shouldBe(3!=null??3,true);shouldBe(3===null??3,false);shouldBe(3!==null??3,true);shouldBe(1null??3,true);shouldBe(1<=null??3,false);shouldBe(1>=null??3,true);shouldBe(1<>null??3,1);shouldBe(1>>>null??3,1);shouldBe(1+null??3,1);shouldBe(1-null??3,1);shouldBe(1*null??3,0);shouldBe(1/null??3,Infinity);shouldBe(isNaN(1%null??3),true);shouldBe(1**null??3,1);const obj={count:0,get x(){this.count++;return'x'}};false??obj.x;shouldBe(obj.count,0);null??obj.x;shouldBe(obj.count,1);obj.x??obj.x;shouldBe(obj.count,2);(0||1)??2;0||(1??2);(0&&1)??2;0&&(1??2);(0??1)||2;0??(1||2);(0??1)&&2;0??(1&&2);0||1&&2|3^4&5==6!=7===8!==9<0>1<=2>=3<<4>>5>>>6+7-8*9/0%1**2 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/nullish-coalescing.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Sony Interactive Entertainment Inc. 3 | * Copyright (C) 2020 Apple Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 | * THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | function testBasicCases() { 28 | shouldBe(undefined ?? 3, 3); 29 | shouldBe(null ?? 3, 3); 30 | shouldBe(true ?? 3, true); 31 | shouldBe(false ?? 3, false); 32 | shouldBe(0 ?? 3, 0); 33 | shouldBe(1 ?? 3, 1); 34 | shouldBe('' ?? 3, ''); 35 | shouldBe('hi' ?? 3, 'hi'); 36 | shouldBe(({} ?? 3) instanceof Object, true); 37 | shouldBe(({ x: 'hi' } ?? 3).x, 'hi'); 38 | shouldBe(([] ?? 3) instanceof Array, true); 39 | shouldBe((['hi'] ?? 3)[0], 'hi'); 40 | shouldBe((makeMasquerader() ?? 3) == null, true); 41 | } 42 | noInline(testBasicCases); 43 | 44 | for (let i = 0; i < 1e5; i++) 45 | testBasicCases(); 46 | 47 | shouldBe(1 | null ?? 3, 1); 48 | shouldBe(1 ^ null ?? 3, 1); 49 | shouldBe(1 & null ?? 3, 0); 50 | shouldBe(3 == null ?? 3, false); 51 | shouldBe(3 != null ?? 3, true); 52 | shouldBe(3 === null ?? 3, false); 53 | shouldBe(3 !== null ?? 3, true); 54 | shouldBe(1 < null ?? 3, false); 55 | shouldBe(1 > null ?? 3, true); 56 | shouldBe(1 <= null ?? 3, false); 57 | shouldBe(1 >= null ?? 3, true); 58 | shouldBe(1 << null ?? 3, 1); 59 | shouldBe(1 >> null ?? 3, 1); 60 | shouldBe(1 >>> null ?? 3, 1); 61 | shouldBe(1 + null ?? 3, 1); 62 | shouldBe(1 - null ?? 3, 1); 63 | shouldBe(1 * null ?? 3, 0); 64 | shouldBe(1 / null ?? 3, Infinity); 65 | shouldBe(isNaN(1 % null ?? 3), true); 66 | shouldBe(1 ** null ?? 3, 1); 67 | 68 | const obj = { 69 | count: 0, 70 | get x() { this.count++; return 'x'; } 71 | }; 72 | false ?? obj.x; 73 | shouldBe(obj.count, 0); 74 | null ?? obj.x; 75 | shouldBe(obj.count, 1); 76 | obj.x ?? obj.x; 77 | shouldBe(obj.count, 2); 78 | 79 | (0 || 1) ?? 2; 80 | 0 || (1 ?? 2); 81 | (0 && 1) ?? 2; 82 | 0 && (1 ?? 2); 83 | (0 ?? 1) || 2; 84 | 0 ?? (1 || 2); 85 | (0 ?? 1) && 2; 86 | 0 ?? (1 && 2); 87 | 88 | 0 || 1 && 2 | 3 ^ 4 & 5 == 6 != 7 === 8 !== 9 < 0 > 1 <= 2 >= 3 << 4 >> 5 >>> 6 + 7 - 8 * 9 / 0 % 1 ** 2 89 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/optional-chaining-2.expected.js: -------------------------------------------------------------------------------- 1 | obj?.aaa?.bbb; 2 | obj?.aaa.bbb; 3 | (obj?.aaa)?.bbb; 4 | (obj?.aaa).bbb; 5 | obj.aaa.bbb; 6 | obj.aaa?.bbb; 7 | func?.()?.bbb; 8 | func?.().bbb; 9 | (func?.())?.bbb; 10 | (func?.()).bbb; 11 | obj?.aaa?.(); 12 | obj?.aaa(); 13 | (obj?.aaa)?.(); 14 | (obj?.aaa)(); 15 | (obj?.aaa?.bbb.ccc?.ddd)?.eee; 16 | ((obj?.aaa?.bbb.ccc)?.ddd)?.eee; 17 | function testBasicSuccessCases() { 18 | shouldBe(undefined?.valueOf(), undefined); 19 | shouldBe(null?.valueOf(), undefined); 20 | shouldBe(true?.valueOf(), true); 21 | shouldBe(false?.valueOf(), false); 22 | shouldBe(0?.valueOf(), 0); 23 | shouldBe(1?.valueOf(), 1); 24 | shouldBe(''?.valueOf(), ''); 25 | shouldBe('hi'?.valueOf(), 'hi'); 26 | shouldBe({}?.constructor, Object); 27 | shouldBe({ x: 'hi' }?.x, 'hi'); 28 | shouldBe([]?.length, 0); 29 | shouldBe(['hi']?.length, 1); 30 | shouldBe(masquerader?.foo, 3); 31 | shouldBe(undefined?.['valueOf'](), undefined); 32 | shouldBe(null?.['valueOf'](), undefined); 33 | shouldBe(true?.['valueOf'](), true); 34 | shouldBe(false?.['valueOf'](), false); 35 | shouldBe(0?.['valueOf'](), 0); 36 | shouldBe(1?.['valueOf'](), 1); 37 | shouldBe(''?.['valueOf'](), ''); 38 | shouldBe('hi'?.['valueOf'](), 'hi'); 39 | shouldBe({}?.['constructor'], Object); 40 | shouldBe({ x: 'hi' }?.['x'], 'hi'); 41 | shouldBe([]?.['length'], 0); 42 | shouldBe(['hi']?.[0], 'hi'); 43 | shouldBe(masquerader?.['foo'], 3); 44 | shouldBe(undefined?.(), undefined); 45 | shouldBe(null?.(), undefined); 46 | shouldBe((() => 3)?.(), 3); 47 | } 48 | noInline(testBasicSuccessCases); 49 | function testBasicFailureCases() { 50 | shouldThrowTypeError(() => true?.(), 'true is not a function'); 51 | shouldThrowTypeError(() => false?.(), 'false is not a function'); 52 | shouldThrowTypeError(() => 0?.(), '0 is not a function'); 53 | shouldThrowTypeError(() => 1?.(), '1 is not a function'); 54 | shouldThrowTypeError(() => ''?.(), '\'\' is not a function'); 55 | shouldThrowTypeError(() => 'hi'?.(), '\'hi\' is not a function'); 56 | shouldThrowTypeError(() => ({}?.()), '({}) is not a function'); 57 | shouldThrowTypeError(() => ({ x: 'hi' }?.()), '({ x: \'hi\' }) is not a function'); 58 | shouldThrowTypeError(() => []?.(), '[] is not a function'); 59 | shouldThrowTypeError(() => ['hi']?.(), '[\'hi\'] is not a function'); 60 | shouldThrowTypeError(() => masquerader?.(), 'masquerader is not a function'); 61 | } 62 | noInline(testBasicFailureCases); 63 | for (let i = 0; i < 100000; i++) 64 | testBasicSuccessCases(); 65 | for (let i = 0; i < 100; i++) 66 | testBasicFailureCases(); 67 | shouldThrowTypeError(() => ({}?.i()), '({})?.i is not a function'); 68 | shouldBe({}.i?.(), undefined); 69 | shouldBe({}?.i?.(), undefined); 70 | shouldThrowTypeError(() => ({}?.['i']()), '({})?.[\'i\'] is not a function'); 71 | shouldBe({}['i']?.(), undefined); 72 | shouldBe({}?.['i']?.(), undefined); 73 | shouldThrowTypeError(() => ({}?.a['b']), 'undefined is not an object'); 74 | shouldBe({}?.a?.['b'], undefined); 75 | shouldBe(null?.a['b']().c, undefined); 76 | shouldThrowTypeError(() => ({}?.['a'].b), 'undefined is not an object'); 77 | shouldBe({}?.['a']?.b, undefined); 78 | shouldBe(null?.['a'].b()['c'], undefined); 79 | shouldThrowTypeError(() => (() => { 80 | })?.()(), '(() => {})?.() is not a function'); 81 | shouldBe((() => { 82 | })?.()?.(), undefined); 83 | shouldBe(null?.()().a['b'], undefined); 84 | const o0 = { 85 | a: { 86 | b() { 87 | return this._b.bind(this); 88 | }, 89 | _b() { 90 | return this.__b; 91 | }, 92 | __b: { c: 42 } 93 | } 94 | }; 95 | shouldBe(o0?.a?.['b']?.()?.()?.c, 42); 96 | shouldBe(o0?.i?.['j']?.()?.()?.k, undefined); 97 | shouldBe((o0.a?._b)?.().c, 42); 98 | shouldBe((o0.a?._b)().c, 42); 99 | shouldBe({ undefined: 3 }?.[null?.a], 3); 100 | shouldBe((() => 3)?.(null?.a), 3); 101 | const o1 = { 102 | count: 0, 103 | get x() { 104 | this.count++; 105 | return () => { 106 | }; 107 | } 108 | }; 109 | o1.x?.y; 110 | shouldBe(o1.count, 1); 111 | o1.x?.['y']; 112 | shouldBe(o1.count, 2); 113 | o1.x?.(); 114 | shouldBe(o1.count, 3); 115 | null?.(o1.x); 116 | shouldBe(o1.count, 3); 117 | shouldBe(delete undefined?.foo, true); 118 | shouldBe(delete null?.foo, true); 119 | shouldBe(delete undefined?.['foo'], true); 120 | shouldBe(delete null?.['foo'], true); 121 | shouldBe(delete undefined?.(), true); 122 | shouldBe(delete null?.(), true); 123 | const o2 = { 124 | x: 0, 125 | y: 0, 126 | z() { 127 | } 128 | }; 129 | shouldBe(delete o2?.x, true); 130 | shouldBe(o2.x, undefined); 131 | shouldBe(delete o2?.x, true); 132 | shouldBe(delete o2?.['y'], true); 133 | shouldBe(o2.y, undefined); 134 | shouldBe(delete o2?.['y'], true); 135 | shouldBe(delete o2.z?.(), true); 136 | function greet(name) { 137 | return `hey, ${ name }${ this.suffix ?? '.' }`; 138 | } 139 | shouldBe(eval?.('greet("world")'), 'hey, world.'); 140 | shouldBe(greet?.call({ suffix: '!' }, 'world'), 'hey, world!'); 141 | shouldBe(greet.call?.({ suffix: '!' }, 'world'), 'hey, world!'); 142 | shouldBe(null?.call({ suffix: '!' }, 'world'), undefined); 143 | shouldBe({}.call?.({ suffix: '!' }, 'world'), undefined); 144 | shouldBe(greet?.apply({ suffix: '?' }, ['world']), 'hey, world?'); 145 | shouldBe(greet.apply?.({ suffix: '?' }, ['world']), 'hey, world?'); 146 | shouldBe(null?.apply({ suffix: '?' }, ['world']), undefined); 147 | shouldBe({}.apply?.({ suffix: '?' }, ['world']), undefined); 148 | shouldBe(false ? 0.4 : 5, 5); -------------------------------------------------------------------------------- /test/compare-acorn-es2020/optional-chaining-2.expected.min.js: -------------------------------------------------------------------------------- 1 | obj?.aaa?.bbb;obj?.aaa.bbb;(obj?.aaa)?.bbb;(obj?.aaa).bbb;obj.aaa.bbb;obj.aaa?.bbb;func?.()?.bbb;func?.().bbb;(func?.())?.bbb;(func?.()).bbb;obj?.aaa?.();obj?.aaa();(obj?.aaa)?.();(obj?.aaa)();(obj?.aaa?.bbb.ccc?.ddd)?.eee;((obj?.aaa?.bbb.ccc)?.ddd)?.eee;function testBasicSuccessCases(){shouldBe(undefined?.valueOf(),undefined);shouldBe(null?.valueOf(),undefined);shouldBe(true?.valueOf(),true);shouldBe(false?.valueOf(),false);shouldBe(0?.valueOf(),0);shouldBe(1?.valueOf(),1);shouldBe(''?.valueOf(),'');shouldBe('hi'?.valueOf(),'hi');shouldBe({}?.constructor,Object);shouldBe({x:'hi'}?.x,'hi');shouldBe([]?.length,0);shouldBe(['hi']?.length,1);shouldBe(masquerader?.foo,3);shouldBe(undefined?.['valueOf'](),undefined);shouldBe(null?.['valueOf'](),undefined);shouldBe(true?.['valueOf'](),true);shouldBe(false?.['valueOf'](),false);shouldBe(0?.['valueOf'](),0);shouldBe(1?.['valueOf'](),1);shouldBe(''?.['valueOf'](),'');shouldBe('hi'?.['valueOf'](),'hi');shouldBe({}?.['constructor'],Object);shouldBe({x:'hi'}?.['x'],'hi');shouldBe([]?.['length'],0);shouldBe(['hi']?.[0],'hi');shouldBe(masquerader?.['foo'],3);shouldBe(undefined?.(),undefined);shouldBe(null?.(),undefined);shouldBe((()=>3)?.(),3)}noInline(testBasicSuccessCases);function testBasicFailureCases(){shouldThrowTypeError(()=>true?.(),'true is not a function');shouldThrowTypeError(()=>false?.(),'false is not a function');shouldThrowTypeError(()=>0?.(),'0 is not a function');shouldThrowTypeError(()=>1?.(),'1 is not a function');shouldThrowTypeError(()=>''?.(),"'' is not a function");shouldThrowTypeError(()=>'hi'?.(),"'hi' is not a function");shouldThrowTypeError(()=>({}?.()),'({}) is not a function');shouldThrowTypeError(()=>({x:'hi'}?.()),"({ x: 'hi' }) is not a function");shouldThrowTypeError(()=>[]?.(),'[] is not a function');shouldThrowTypeError(()=>['hi']?.(),"['hi'] is not a function");shouldThrowTypeError(()=>masquerader?.(),'masquerader is not a function')}noInline(testBasicFailureCases);for(let i=0;i<1e5;i++)testBasicSuccessCases();for(let i=0;i<100;i++)testBasicFailureCases();shouldThrowTypeError(()=>({}?.i()),'({})?.i is not a function');shouldBe({}.i?.(),undefined);shouldBe({}?.i?.(),undefined);shouldThrowTypeError(()=>({}?.['i']()),"({})?.['i'] is not a function");shouldBe({}['i']?.(),undefined);shouldBe({}?.['i']?.(),undefined);shouldThrowTypeError(()=>({}?.a['b']),'undefined is not an object');shouldBe({}?.a?.['b'],undefined);shouldBe(null?.a['b']().c,undefined);shouldThrowTypeError(()=>({}?.['a'].b),'undefined is not an object');shouldBe({}?.['a']?.b,undefined);shouldBe(null?.['a'].b()['c'],undefined);shouldThrowTypeError(()=>(()=>{})?.()(),'(() => {})?.() is not a function');shouldBe((()=>{})?.()?.(),undefined);shouldBe(null?.()().a['b'],undefined);const o0={a:{b(){return this._b.bind(this)},_b(){return this.__b},__b:{c:42}}};shouldBe(o0?.a?.['b']?.()?.()?.c,42);shouldBe(o0?.i?.['j']?.()?.()?.k,undefined);shouldBe((o0.a?._b)?.().c,42);shouldBe((o0.a?._b)().c,42);shouldBe({undefined:3}?.[null?.a],3);shouldBe((()=>3)?.(null?.a),3);const o1={count:0,get x(){this.count++;return()=>{}}};o1.x?.y;shouldBe(o1.count,1);o1.x?.['y'];shouldBe(o1.count,2);o1.x?.();shouldBe(o1.count,3);null?.(o1.x);shouldBe(o1.count,3);shouldBe(delete undefined?.foo,true);shouldBe(delete null?.foo,true);shouldBe(delete undefined?.['foo'],true);shouldBe(delete null?.['foo'],true);shouldBe(delete undefined?.(),true);shouldBe(delete null?.(),true);const o2={x:0,y:0,z(){}};shouldBe(delete o2?.x,true);shouldBe(o2.x,undefined);shouldBe(delete o2?.x,true);shouldBe(delete o2?.['y'],true);shouldBe(o2.y,undefined);shouldBe(delete o2?.['y'],true);shouldBe(delete o2.z?.(),true);function greet(name){return`hey, ${name}${this.suffix??'.'}`}shouldBe(eval?.('greet("world")'),'hey, world.');shouldBe(greet?.call({suffix:'!'},'world'),'hey, world!');shouldBe(greet.call?.({suffix:'!'},'world'),'hey, world!');shouldBe(null?.call({suffix:'!'},'world'),undefined);shouldBe({}.call?.({suffix:'!'},'world'),undefined);shouldBe(greet?.apply({suffix:'?'},['world']),'hey, world?');shouldBe(greet.apply?.({suffix:'?'},['world']),'hey, world?');shouldBe(null?.apply({suffix:'?'},['world']),undefined);shouldBe({}.apply?.({suffix:'?'},['world']),undefined);shouldBe(false?.4:5,5) 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/optional-chaining-2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Sony Interactive Entertainment Inc. 3 | * Copyright (C) 2020 Apple Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 | * THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | obj?.aaa?.bbb; 28 | obj?.aaa.bbb; 29 | (obj?.aaa)?.bbb; 30 | (obj?.aaa).bbb; 31 | obj.aaa.bbb; 32 | obj.aaa?.bbb; 33 | func?.()?.bbb; 34 | func?.().bbb; 35 | (func?.())?.bbb; 36 | (func?.()).bbb; 37 | obj?.aaa?.(); 38 | obj?.aaa(); 39 | (obj?.aaa)?.(); 40 | (obj?.aaa)(); 41 | (obj?.aaa?.bbb.ccc?.ddd)?.eee; 42 | ((obj?.aaa?.bbb.ccc)?.ddd)?.eee; 43 | 44 | function testBasicSuccessCases() { 45 | shouldBe(undefined?.valueOf(), undefined); 46 | shouldBe(null?.valueOf(), undefined); 47 | shouldBe(true?.valueOf(), true); 48 | shouldBe(false?.valueOf(), false); 49 | shouldBe(0?.valueOf(), 0); 50 | shouldBe(1?.valueOf(), 1); 51 | shouldBe(''?.valueOf(), ''); 52 | shouldBe('hi'?.valueOf(), 'hi'); 53 | shouldBe(({})?.constructor, Object); 54 | shouldBe(({ x: 'hi' })?.x, 'hi'); 55 | shouldBe([]?.length, 0); 56 | shouldBe(['hi']?.length, 1); 57 | shouldBe(masquerader?.foo, 3); 58 | 59 | shouldBe(undefined?.['valueOf'](), undefined); 60 | shouldBe(null?.['valueOf'](), undefined); 61 | shouldBe(true?.['valueOf'](), true); 62 | shouldBe(false?.['valueOf'](), false); 63 | shouldBe(0?.['valueOf'](), 0); 64 | shouldBe(1?.['valueOf'](), 1); 65 | shouldBe(''?.['valueOf'](), ''); 66 | shouldBe('hi'?.['valueOf'](), 'hi'); 67 | shouldBe(({})?.['constructor'], Object); 68 | shouldBe(({ x: 'hi' })?.['x'], 'hi'); 69 | shouldBe([]?.['length'], 0); 70 | shouldBe(['hi']?.[0], 'hi'); 71 | shouldBe(masquerader?.['foo'], 3); 72 | 73 | shouldBe(undefined?.(), undefined); 74 | shouldBe(null?.(), undefined); 75 | shouldBe((() => 3)?.(), 3); 76 | } 77 | noInline(testBasicSuccessCases); 78 | 79 | function testBasicFailureCases() { 80 | shouldThrowTypeError(() => true?.(), 'true is not a function'); 81 | shouldThrowTypeError(() => false?.(), 'false is not a function'); 82 | shouldThrowTypeError(() => 0?.(), '0 is not a function'); 83 | shouldThrowTypeError(() => 1?.(), '1 is not a function'); 84 | shouldThrowTypeError(() => ''?.(), '\'\' is not a function'); 85 | shouldThrowTypeError(() => 'hi'?.(), '\'hi\' is not a function'); 86 | shouldThrowTypeError(() => ({})?.(), '({}) is not a function'); 87 | shouldThrowTypeError(() => ({ x: 'hi' })?.(), '({ x: \'hi\' }) is not a function'); 88 | shouldThrowTypeError(() => []?.(), '[] is not a function'); 89 | shouldThrowTypeError(() => ['hi']?.(), '[\'hi\'] is not a function'); 90 | shouldThrowTypeError(() => masquerader?.(), 'masquerader is not a function'); 91 | } 92 | noInline(testBasicFailureCases); 93 | 94 | for (let i = 0; i < 1e5; i++) 95 | testBasicSuccessCases(); 96 | 97 | for (let i = 0; i < 100; i++) 98 | testBasicFailureCases(); 99 | 100 | shouldThrowTypeError(() => ({})?.i(), '({})?.i is not a function'); 101 | shouldBe(({}).i?.(), undefined); 102 | shouldBe(({})?.i?.(), undefined); 103 | shouldThrowTypeError(() => ({})?.['i'](), '({})?.[\'i\'] is not a function'); 104 | shouldBe(({})['i']?.(), undefined); 105 | shouldBe(({})?.['i']?.(), undefined); 106 | 107 | shouldThrowTypeError(() => ({})?.a['b'], 'undefined is not an object'); 108 | shouldBe(({})?.a?.['b'], undefined); 109 | shouldBe(null?.a['b']().c, undefined); 110 | shouldThrowTypeError(() => ({})?.['a'].b, 'undefined is not an object'); 111 | shouldBe(({})?.['a']?.b, undefined); 112 | shouldBe(null?.['a'].b()['c'], undefined); 113 | shouldThrowTypeError(() => (() => {})?.()(), '(() => {})?.() is not a function'); 114 | shouldBe((() => {})?.()?.(), undefined); 115 | shouldBe(null?.()().a['b'], undefined); 116 | 117 | const o0 = { a: { b() { return this._b.bind(this); }, _b() { return this.__b; }, __b: { c: 42 } } }; 118 | shouldBe(o0?.a?.['b']?.()?.()?.c, 42); 119 | shouldBe(o0?.i?.['j']?.()?.()?.k, undefined); 120 | shouldBe((o0.a?._b)?.().c, 42); 121 | shouldBe((o0.a?._b)().c, 42); 122 | 123 | shouldBe(({ undefined: 3 })?.[null?.a], 3); 124 | shouldBe((() => 3)?.(null?.a), 3); 125 | 126 | const o1 = { count: 0, get x() { this.count++; return () => {}; } }; 127 | o1.x?.y; 128 | shouldBe(o1.count, 1); 129 | o1.x?.['y']; 130 | shouldBe(o1.count, 2); 131 | o1.x?.(); 132 | shouldBe(o1.count, 3); 133 | null?.(o1.x); 134 | shouldBe(o1.count, 3); 135 | 136 | shouldBe(delete undefined?.foo, true); 137 | shouldBe(delete null?.foo, true); 138 | shouldBe(delete undefined?.['foo'], true); 139 | shouldBe(delete null?.['foo'], true); 140 | shouldBe(delete undefined?.(), true); 141 | shouldBe(delete null?.(), true); 142 | 143 | const o2 = { x: 0, y: 0, z() {} }; 144 | shouldBe(delete o2?.x, true); 145 | shouldBe(o2.x, undefined); 146 | shouldBe(delete o2?.x, true); 147 | shouldBe(delete o2?.['y'], true); 148 | shouldBe(o2.y, undefined); 149 | shouldBe(delete o2?.['y'], true); 150 | shouldBe(delete o2.z?.(), true); 151 | 152 | function greet(name) { return `hey, ${name}${this.suffix ?? '.'}`; } 153 | shouldBe(eval?.('greet("world")'), 'hey, world.'); 154 | shouldBe(greet?.call({ suffix: '!' }, 'world'), 'hey, world!'); 155 | shouldBe(greet.call?.({ suffix: '!' }, 'world'), 'hey, world!'); 156 | shouldBe(null?.call({ suffix: '!' }, 'world'), undefined); 157 | shouldBe(({}).call?.({ suffix: '!' }, 'world'), undefined); 158 | shouldBe(greet?.apply({ suffix: '?' }, ['world']), 'hey, world?'); 159 | shouldBe(greet.apply?.({ suffix: '?' }, ['world']), 'hey, world?'); 160 | shouldBe(null?.apply({ suffix: '?' }, ['world']), undefined); 161 | shouldBe(({}).apply?.({ suffix: '?' }, ['world']), undefined); 162 | 163 | // NOT an optional chain 164 | shouldBe(false?.4:5, 5); 165 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/optional-chaining.expected.js: -------------------------------------------------------------------------------- 1 | obj.aaa.bbb; 2 | obj.aaa?.bbb; 3 | obj?.aaa.bbb; 4 | obj?.aaa?.bbb; 5 | obj.aaa.bbb; 6 | obj.aaa?.bbb; 7 | (obj?.aaa).bbb; 8 | (obj?.aaa)?.bbb; 9 | (obj?.aaa).bbb.ccc.ddd; 10 | ((obj?.aaa).bbb?.ccc).ddd; 11 | (obj?.aaa)?.bbb; 12 | obj[aaa][bbb]; 13 | obj[aaa]?.[bbb]; 14 | obj?.[aaa][bbb]; 15 | obj?.[aaa]?.[bbb]; 16 | obj[aaa][bbb]; 17 | obj[aaa]?.[bbb]; 18 | (obj?.[aaa])[bbb]; 19 | (obj?.[aaa])?.[bbb]; 20 | obj[aaa][bbb][ccc][ddd]; 21 | ((obj?.[aaa])[bbb]?.[ccc])[ddd]; 22 | 1?.a; 23 | obj()(); 24 | obj()?.(); 25 | obj?.()(); 26 | obj?.()?.(); 27 | obj()(); 28 | obj()?.(); 29 | (obj?.())(); 30 | (obj?.())?.(); 31 | obj()()()(); 32 | ((obj?.())()?.())(); 33 | (a?.b)(); 34 | a?.b(); 35 | a?.b?.(); 36 | (a?.b)?.(); 37 | a?.().b; 38 | (a?.()).b; 39 | a?.b.c(); 40 | (a?.b.c)(); 41 | a.b?.().c; 42 | (a.b?.()).c; 43 | (a.b?.())?.c; 44 | new (a?.b().c)(); 45 | new (a?.b())(); 46 | new (a?.b().c)(); 47 | new (a?.b())(); -------------------------------------------------------------------------------- /test/compare-acorn-es2020/optional-chaining.expected.min.js: -------------------------------------------------------------------------------- 1 | obj.aaa.bbb;obj.aaa?.bbb;obj?.aaa.bbb;obj?.aaa?.bbb;obj.aaa.bbb;obj.aaa?.bbb;(obj?.aaa).bbb;(obj?.aaa)?.bbb;(obj?.aaa).bbb.ccc.ddd;((obj?.aaa).bbb?.ccc).ddd;(obj?.aaa)?.bbb;obj[aaa][bbb];obj[aaa]?.[bbb];obj?.[aaa][bbb];obj?.[aaa]?.[bbb];obj[aaa][bbb];obj[aaa]?.[bbb];(obj?.[aaa])[bbb];(obj?.[aaa])?.[bbb];obj[aaa][bbb][ccc][ddd];((obj?.[aaa])[bbb]?.[ccc])[ddd];1?.a;obj()();obj()?.();obj?.()();obj?.()?.();obj()();obj()?.();(obj?.())();(obj?.())?.();obj()()()();((obj?.())()?.())();(a?.b)();a?.b();a?.b?.();(a?.b)?.();a?.().b;(a?.()).b;a?.b.c();(a?.b.c)();a.b?.().c;(a.b?.()).c;(a.b?.())?.c;new(a?.b().c);new(a?.b());new(a?.b().c);new(a?.b()) 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es2020/optional-chaining.js: -------------------------------------------------------------------------------- 1 | obj.aaa.bbb; 2 | obj.aaa?.bbb; 3 | obj?.aaa.bbb; 4 | obj?.aaa?.bbb; 5 | (obj.aaa).bbb; 6 | (obj.aaa)?.bbb; 7 | (obj?.aaa).bbb; 8 | (obj?.aaa)?.bbb; 9 | ((obj?.aaa).bbb.ccc).ddd; 10 | ((obj?.aaa).bbb?.ccc).ddd; 11 | (obj?.aaa)?.bbb; 12 | obj[aaa][bbb]; 13 | obj[aaa]?.[bbb]; 14 | obj?.[aaa][bbb]; 15 | obj?.[aaa]?.[bbb]; 16 | (obj[aaa])[bbb]; 17 | (obj[aaa])?.[bbb]; 18 | (obj?.[aaa])[bbb]; 19 | (obj?.[aaa])?.[bbb]; 20 | ((obj[aaa])[bbb][ccc])[ddd]; 21 | ((obj?.[aaa])[bbb]?.[ccc])[ddd]; 22 | 1?.a; 23 | obj()(); 24 | obj()?.(); 25 | obj?.()(); 26 | obj?.()?.(); 27 | (obj())(); 28 | (obj())?.(); 29 | (obj?.())(); 30 | (obj?.())?.(); 31 | ((obj())()())(); 32 | ((obj?.())()?.())(); 33 | (a?.b)(); 34 | a?.b(); 35 | a?.b?.(); 36 | (a?.b)?.(); 37 | a?.().b; 38 | (a?.()).b; 39 | a?.b.c(); 40 | (a?.b.c)(); 41 | a.b?.().c; 42 | (a.b?.()).c; 43 | (a.b?.())?.c; 44 | new (a?.b().c); 45 | new (a?.b()); 46 | new (a?.b().c)(); 47 | new (a?.b())(); 48 | -------------------------------------------------------------------------------- /test/compare-acorn-es2021.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | Copyright (C) 2020 Apple Inc. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | 'use strict'; 27 | 28 | var fs = require('fs'), 29 | acorn = require('acorn'), 30 | escodegen = require('./loader'), 31 | chai = require('chai'), 32 | chaiExclude = require('chai-exclude'), 33 | expect = chai.expect; 34 | 35 | chai.use(chaiExclude); 36 | 37 | function test(code, expected) { 38 | var tree, actual, actualTree, options; 39 | 40 | options = { 41 | ranges: false, 42 | locations: false, 43 | ecmaVersion: 12 44 | }; 45 | 46 | tree = acorn.parse(code, options); 47 | 48 | // for UNIX text comment 49 | actual = escodegen.generate(tree); 50 | actualTree = acorn.parse(actual, options); 51 | 52 | expect(actual).to.be.equal(expected); 53 | expect(tree).excludingEvery(['start', 'end', 'raw']).to.deep.equal(actualTree); 54 | } 55 | 56 | function testMin(code, expected) { 57 | var tree, actual, actualTree, options; 58 | 59 | options = { 60 | ranges: false, 61 | locations: false, 62 | ecmaVersion: 12 63 | }; 64 | 65 | tree = acorn.parse(code, options); 66 | 67 | // for UNIX text comment 68 | actual = escodegen.generate(tree, { 69 | format: escodegen.FORMAT_MINIFY, 70 | raw: false 71 | }).replace(/[\n\r]$/, '') + '\n'; 72 | actualTree = acorn.parse(actual, options); 73 | 74 | expect(actual).to.be.equal(expected); 75 | expect(tree).excludingEvery(['start', 'end', 'raw']).to.deep.equal(actualTree); 76 | } 77 | 78 | describe('compare acorn es2021 test', function () { 79 | fs.readdirSync(__dirname + '/compare-acorn-es2021').sort().forEach(function(file) { 80 | var code, expected, exp, min; 81 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 82 | it(file, function () { 83 | exp = file.replace(/\.js$/, '.expected.js'); 84 | min = file.replace(/\.js$/, '.expected.min.js'); 85 | code = fs.readFileSync(__dirname + '/compare-acorn-es2021/' + file, 'utf-8'); 86 | expected = fs.readFileSync(__dirname + '/compare-acorn-es2021/' + exp, 'utf-8'); 87 | test(code, expected); 88 | if (fs.existsSync(__dirname + '/compare-acorn-es2021/' + min)) { 89 | expected = fs.readFileSync(__dirname + '/compare-acorn-es2021/' + min, 'utf-8'); 90 | testMin(code, expected); 91 | } 92 | }); 93 | } 94 | }); 95 | }); 96 | /* vim: set sw=4 ts=4 et tw=80 : */ 97 | -------------------------------------------------------------------------------- /test/compare-acorn-es2021/logical-assignments.expected.js: -------------------------------------------------------------------------------- 1 | undefined &&= 42; 2 | x &&= ++counter; 3 | x.a &&= 42; 4 | x['a'] &&= 42; 5 | undefined ||= 42; 6 | x ||= ++counter; 7 | x.a ||= 42; 8 | x['a'] ||= 42; 9 | undefined ??= 42; 10 | x ??= ++counter; 11 | x.a ??= 42; 12 | x['a'] ??= 42; -------------------------------------------------------------------------------- /test/compare-acorn-es2021/logical-assignments.expected.min.js: -------------------------------------------------------------------------------- 1 | undefined&&=42;x&&=++counter;x.a&&=42;x['a']&&=42;undefined||=42;x||=++counter;x.a||=42;x['a']||=42;undefined??=42;x??=++counter;x.a??=42;x['a']??=42 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es2021/logical-assignments.js: -------------------------------------------------------------------------------- 1 | undefined &&= 42; 2 | x &&= ++counter; 3 | x.a &&= 42; 4 | x['a'] &&= 42; 5 | 6 | undefined ||= 42; 7 | x ||= ++counter; 8 | x.a ||= 42; 9 | x['a'] ||= 42; 10 | 11 | undefined ??= 42; 12 | x ??= ++counter; 13 | x.a ??= 42; 14 | x['a'] ??= 42; 15 | -------------------------------------------------------------------------------- /test/compare-acorn-es6.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | acorn = require('acorn'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | function test(code, expected) { 34 | var tree, actual, options, StringObject; 35 | 36 | // alias, so that JSLint does not complain. 37 | StringObject = String; 38 | 39 | options = { 40 | ranges: true, 41 | locations: false, 42 | ecmaVersion: 6 43 | }; 44 | 45 | tree = acorn.parse(code, options); 46 | 47 | // for UNIX text comment 48 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 49 | expect(actual).to.be.equal(expected); 50 | } 51 | 52 | function testMin(code, expected) { 53 | var tree, actual, options, StringObject; 54 | 55 | // alias, so that JSLint does not complain. 56 | StringObject = String; 57 | 58 | options = { 59 | ranges: true, 60 | locations: false, 61 | ecmaVersion: 6 62 | }; 63 | 64 | tree = acorn.parse(code, options); 65 | 66 | // for UNIX text comment 67 | actual = escodegen.generate(tree, { 68 | format: escodegen.FORMAT_MINIFY, 69 | raw: false 70 | }).replace(/[\n\r]$/, '') + '\n'; 71 | expect(actual).to.be.equal(expected); 72 | } 73 | 74 | describe('compare acorn es6 test', function () { 75 | fs.readdirSync(__dirname + '/compare-acorn-es6').sort().forEach(function(file) { 76 | var code, expected, exp, min; 77 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 78 | it(file, function () { 79 | exp = file.replace(/\.js$/, '.expected.js'); 80 | min = file.replace(/\.js$/, '.expected.min.js'); 81 | code = fs.readFileSync(__dirname + '/compare-acorn-es6/' + file, 'utf-8'); 82 | expected = fs.readFileSync(__dirname + '/compare-acorn-es6/' + exp, 'utf-8'); 83 | test(code, expected); 84 | if (fs.existsSync(__dirname + '/compare-acorn-es6/' + min)) { 85 | expected = fs.readFileSync(__dirname + '/compare-acorn-es6/' + min, 'utf-8'); 86 | testMin(code, expected); 87 | } 88 | }); 89 | } 90 | }); 91 | }); 92 | /* vim: set sw=4 ts=4 et tw=80 : */ 93 | -------------------------------------------------------------------------------- /test/compare-acorn-es6/assignment-pattern.expected.js: -------------------------------------------------------------------------------- 1 | function x(a = { a: 6 }, b = null, ...d) { 2 | } 3 | -------------------------------------------------------------------------------- /test/compare-acorn-es6/assignment-pattern.expected.min.js: -------------------------------------------------------------------------------- 1 | function x(a={a:6},b=null,...d){} 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es6/assignment-pattern.js: -------------------------------------------------------------------------------- 1 | function x(a={a:6}, b=null, ...d) 2 | { 3 | } 4 | -------------------------------------------------------------------------------- /test/compare-acorn-es6/class-declaration.expected.js: -------------------------------------------------------------------------------- 1 | class ComputedKey { 2 | [n1 + n2]() { 3 | } 4 | } 5 | class AssignmentExpressionAsKey { 6 | [n1 = n2]() { 7 | } 8 | } 9 | class SequenceExpressionAsKey { 10 | [(n1, n2)]() { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/compare-acorn-es6/class-declaration.expected.min.js: -------------------------------------------------------------------------------- 1 | class ComputedKey{[n1+n2](){}}class AssignmentExpressionAsKey{[n1=n2](){}}class SequenceExpressionAsKey{[(n1,n2)](){}} 2 | -------------------------------------------------------------------------------- /test/compare-acorn-es6/class-declaration.js: -------------------------------------------------------------------------------- 1 | class ComputedKey { 2 | [n1 + n2]() {} 3 | } 4 | class AssignmentExpressionAsKey { 5 | [n1 = n2]() {} 6 | } 7 | class SequenceExpressionAsKey { 8 | [(n1, n2)]() {} 9 | } -------------------------------------------------------------------------------- /test/compare-acorn-es7.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | acorn = require('acorn'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | function test(code, expected) { 34 | var tree, actual, options, StringObject; 35 | 36 | // alias, so that JSLint does not complain. 37 | StringObject = String; 38 | 39 | options = { 40 | ranges: true, 41 | locations: false, 42 | ecmaVersion: 7 43 | }; 44 | 45 | tree = acorn.parse(code, options); 46 | 47 | // for UNIX text comment 48 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 49 | expect(actual).to.be.equal(expected); 50 | } 51 | 52 | function testMin(code, expected) { 53 | var tree, actual, options, StringObject; 54 | 55 | // alias, so that JSLint does not complain. 56 | StringObject = String; 57 | 58 | options = { 59 | ranges: true, 60 | locations: false, 61 | ecmaVersion: 7 62 | }; 63 | 64 | tree = acorn.parse(code, options); 65 | 66 | // for UNIX text comment 67 | actual = escodegen.generate(tree, { 68 | format: escodegen.FORMAT_MINIFY, 69 | raw: false 70 | }).replace(/[\n\r]$/, '') + '\n'; 71 | expect(actual).to.be.equal(expected); 72 | } 73 | 74 | describe('compare acorn es7 test', function () { 75 | fs.readdirSync(__dirname + '/compare-acorn-es7').sort().forEach(function(file) { 76 | var code, expected, exp, min; 77 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 78 | it(file, function () { 79 | exp = file.replace(/\.js$/, '.expected.js'); 80 | min = file.replace(/\.js$/, '.expected.min.js'); 81 | code = fs.readFileSync(__dirname + '/compare-acorn-es7/' + file, 'utf-8'); 82 | expected = fs.readFileSync(__dirname + '/compare-acorn-es7/' + exp, 'utf-8'); 83 | test(code, expected); 84 | if (fs.existsSync(__dirname + '/compare-acorn-es7/' + min)) { 85 | expected = fs.readFileSync(__dirname + '/compare-acorn-es7/' + min, 'utf-8'); 86 | testMin(code, expected); 87 | } 88 | }); 89 | } 90 | }); 91 | }); 92 | /* vim: set sw=4 ts=4 et tw=80 : */ 93 | -------------------------------------------------------------------------------- /test/compare-acorn-es7/exponentiation-precedence.expected.js: -------------------------------------------------------------------------------- 1 | x ** y * z; 2 | x ** (y * z); 3 | (x * y) ** z; 4 | x * y ** z; 5 | x ** y ** z; 6 | (x ** y) ** z; 7 | (-1) ** 0; 8 | a++ ** b; 9 | 0 ** -1; 10 | -------------------------------------------------------------------------------- /test/compare-acorn-es7/exponentiation-precedence.js: -------------------------------------------------------------------------------- 1 | (x ** y) * z; 2 | x ** (y * z); 3 | 4 | (x * y) ** z; 5 | x * (y ** z); 6 | 7 | x ** (y ** z); 8 | (x ** y) ** z; 9 | 10 | (-1) ** 0; 11 | a++ ** b; 12 | 0 ** (-1); 13 | -------------------------------------------------------------------------------- /test/compare-esprima2.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | esprima = require('./3rdparty/esprima-2.7.1'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect, 32 | DIR = 'compare-esprima2'; 33 | 34 | function test(code, expected) { 35 | var tree, actual, options, StringObject; 36 | 37 | // alias, so that JSLint does not complain. 38 | StringObject = String; 39 | 40 | options = { 41 | range: true, 42 | loc: false, 43 | tokens: true, 44 | raw: false, 45 | comment: true, 46 | sourceType: 'module' 47 | }; 48 | 49 | tree = esprima.parse(code, options); 50 | 51 | // for UNIX text comment 52 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 53 | expect(actual).to.be.equal(expected); 54 | } 55 | 56 | function testMin(code, expected) { 57 | var tree, tree2, actual, actual2, options, StringObject; 58 | 59 | // alias, so that JSLint does not complain. 60 | StringObject = String; 61 | 62 | options = { 63 | range: true, 64 | loc: false, 65 | tokens: true, 66 | raw: false, 67 | sourceType: 'module' 68 | }; 69 | 70 | tree = esprima.parse(code, options); 71 | 72 | // for UNIX text comment 73 | actual = escodegen.generate(tree, { 74 | format: escodegen.FORMAT_MINIFY, 75 | raw: false 76 | }).replace(/[\n\r]$/, '') + '\n'; 77 | expect(actual).to.be.equal(expected); 78 | 79 | // And ensure that minified value is exactly equal. 80 | tree2 = esprima.parse(actual, options); 81 | actual2 = escodegen.generate(tree2, { 82 | format: escodegen.FORMAT_MINIFY, 83 | raw: false 84 | }).replace(/[\n\r]$/, '') + '\n'; 85 | expect(actual2).to.be.equal(actual); 86 | } 87 | 88 | describe('compare esprima 2 test', function () { 89 | fs.readdirSync(__dirname + '/' + DIR).sort().forEach(function(file) { 90 | var code, expected, exp, min; 91 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 92 | it(file, function () { 93 | exp = file.replace(/\.js$/, '.expected.js'); 94 | min = file.replace(/\.js$/, '.expected.min.js'); 95 | code = fs.readFileSync(__dirname + '/' + DIR + '/' + file, 'utf-8'); 96 | expected = fs.readFileSync(__dirname + '/' + DIR + '/' + exp, 'utf-8'); 97 | test(code, expected); 98 | if (fs.existsSync(__dirname + '/' + DIR + '/' + min)) { 99 | expected = fs.readFileSync(__dirname + '/' + DIR + '/' + min, 'utf-8'); 100 | testMin(code, expected); 101 | } 102 | }); 103 | } 104 | }); 105 | }); 106 | /* vim: set sw=4 ts=4 et tw=80 : */ 107 | -------------------------------------------------------------------------------- /test/compare-esprima2/export-declaration.expected.js: -------------------------------------------------------------------------------- 1 | export { 2 | foo 3 | }; 4 | -------------------------------------------------------------------------------- /test/compare-esprima2/export-declaration.expected.min.js: -------------------------------------------------------------------------------- 1 | export{foo} 2 | -------------------------------------------------------------------------------- /test/compare-esprima2/export-declaration.js: -------------------------------------------------------------------------------- 1 | export { foo }; 2 | -------------------------------------------------------------------------------- /test/compare-esprima2/export-default-declaration.expected.js: -------------------------------------------------------------------------------- 1 | export default function a() { 2 | } 3 | export default function () { 4 | } 5 | export default class A { 6 | } 7 | export default class { 8 | } 9 | -------------------------------------------------------------------------------- /test/compare-esprima2/export-default-declaration.expected.min.js: -------------------------------------------------------------------------------- 1 | export default function a(){}export default function (){}export default class A{}export default class{} 2 | -------------------------------------------------------------------------------- /test/compare-esprima2/export-default-declaration.js: -------------------------------------------------------------------------------- 1 | export default function a () { } 2 | // export default var i = 20; 3 | // export default const K = 20; 4 | export default function () { } 5 | export default class A { } 6 | export default class { } 7 | -------------------------------------------------------------------------------- /test/compare-esprima2/exports.expected.js: -------------------------------------------------------------------------------- 1 | export * from 'OK'; 2 | export { 3 | name 4 | } from 'OK'; 5 | export { 6 | a as b, 7 | c as d 8 | } from 'hello'; 9 | export { 10 | a as b, 11 | c as d 12 | }; 13 | export { }; 14 | export function test() { 15 | } 16 | export var i = 20; 17 | export let i = 42; 18 | -------------------------------------------------------------------------------- /test/compare-esprima2/exports.expected.min.js: -------------------------------------------------------------------------------- 1 | export*from'OK';export{name}from'OK';export{a as b,c as d}from'hello';export{a as b,c as d};export{};export function test(){}export var i=20;export let i=42 2 | -------------------------------------------------------------------------------- /test/compare-esprima2/exports.js: -------------------------------------------------------------------------------- 1 | export * from "OK" 2 | export { name } from "OK" 3 | export { a as b, c as d } from "hello" 4 | export { a as b, c as d } 5 | export { } 6 | export function test() { } 7 | export var i = 20 8 | export let i = 42 9 | -------------------------------------------------------------------------------- /test/compare-esprima2/import-with-default.expected.js: -------------------------------------------------------------------------------- 1 | import foo from 'foo'; 2 | import foo, * as foo from 'foo'; 3 | import * as foo from 'foo'; 4 | import ok, { 5 | foo as bar, 6 | test as testing, 7 | logging 8 | } from 'foo'; 9 | -------------------------------------------------------------------------------- /test/compare-esprima2/import-with-default.expected.min.js: -------------------------------------------------------------------------------- 1 | import foo from'foo';import foo,*as foo from'foo';import*as foo from'foo';import ok,{foo as bar,test as testing,logging}from'foo' 2 | -------------------------------------------------------------------------------- /test/compare-esprima2/import-with-default.js: -------------------------------------------------------------------------------- 1 | import foo from 'foo'; 2 | import foo, * as foo from 'foo'; 3 | import * as foo from 'foo'; 4 | import ok, { 5 | foo as bar, 6 | test as testing, 7 | logging 8 | } from 'foo'; 9 | -------------------------------------------------------------------------------- /test/compare-esprima2/imports.expected.js: -------------------------------------------------------------------------------- 1 | import 'foo'; 2 | import { foo } from 'foo'; 3 | import { foo as bar } from 'foo'; 4 | import { 5 | foo as bar, 6 | test as testing, 7 | logging 8 | } from 'foo'; 9 | -------------------------------------------------------------------------------- /test/compare-esprima2/imports.expected.min.js: -------------------------------------------------------------------------------- 1 | import'foo';import{foo}from'foo';import{foo as bar}from'foo';import{foo as bar,test as testing,logging}from'foo' 2 | -------------------------------------------------------------------------------- /test/compare-esprima2/imports.js: -------------------------------------------------------------------------------- 1 | import 'foo'; 2 | import {foo} from 'foo'; 3 | import {foo as bar} from 'foo'; 4 | import { 5 | foo as bar, 6 | test as testing, 7 | logging 8 | } from 'foo'; 9 | -------------------------------------------------------------------------------- /test/compare-fixed-harmony.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | esprima = require('./3rdparty/esprima-harmony.patched'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | function test(code, expected) { 34 | var tree, actual, options, StringObject; 35 | 36 | // alias, so that JSLint does not complain. 37 | StringObject = String; 38 | 39 | options = { 40 | range: true, 41 | loc: false, 42 | tokens: true, 43 | raw: false 44 | }; 45 | 46 | tree = esprima.parse(code, options); 47 | 48 | // for UNIX text comment 49 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 50 | expect(actual).to.be.equal(expected); 51 | } 52 | 53 | function testMin(code, expected) { 54 | var tree, tree2, actual, actual2, options, StringObject; 55 | 56 | // alias, so that JSLint does not complain. 57 | StringObject = String; 58 | 59 | options = { 60 | range: true, 61 | loc: false, 62 | tokens: true, 63 | raw: false 64 | }; 65 | 66 | tree = esprima.parse(code, options); 67 | 68 | // for UNIX text comment 69 | actual = escodegen.generate(tree, { 70 | format: escodegen.FORMAT_MINIFY, 71 | raw: false 72 | }).replace(/[\n\r]$/, '') + '\n'; 73 | expect(actual).to.be.equal(expected); 74 | 75 | // And ensure that minified value is exactly equal. 76 | tree2 = esprima.parse(actual, options); 77 | actual2 = escodegen.generate(tree2, { 78 | format: escodegen.FORMAT_MINIFY, 79 | raw: false 80 | }).replace(/[\n\r]$/, '') + '\n'; 81 | expect(actual2).to.be.equal(actual); 82 | } 83 | 84 | describe('compare harmony test', function () { 85 | fs.readdirSync(__dirname + '/compare-fixed-harmony').sort().forEach(function(file) { 86 | var code, expected, exp, min; 87 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 88 | it(file, function () { 89 | exp = file.replace(/\.js$/, '.expected.js'); 90 | min = file.replace(/\.js$/, '.expected.min.js'); 91 | code = fs.readFileSync(__dirname + '/compare-fixed-harmony/' + file, 'utf-8'); 92 | expected = fs.readFileSync(__dirname + '/compare-fixed-harmony/' + exp, 'utf-8'); 93 | test(code, expected); 94 | if (fs.existsSync(__dirname + '/compare-fixed-harmony/' + min)) { 95 | expected = fs.readFileSync(__dirname + '/compare-fixed-harmony/' + min, 'utf-8'); 96 | testMin(code, expected); 97 | } 98 | }); 99 | } 100 | }); 101 | }); 102 | /* vim: set sw=4 ts=4 et tw=80 : */ 103 | -------------------------------------------------------------------------------- /test/compare-fixed-harmony/spread-element.expected.js: -------------------------------------------------------------------------------- 1 | var [a, b, ...rest] = array; 2 | const [a, b, ...rest] = array; 3 | function a([a, b, ...rest]) { 4 | } 5 | ([a, b, ...rest]) => { 6 | }; 7 | -------------------------------------------------------------------------------- /test/compare-fixed-harmony/spread-element.expected.min.js: -------------------------------------------------------------------------------- 1 | var [a,b,...rest]=array;const [a,b,...rest]=array;function a([a,b,...rest]){}([a,b,...rest])=>{} 2 | -------------------------------------------------------------------------------- /test/compare-fixed-harmony/spread-element.js: -------------------------------------------------------------------------------- 1 | var [a, b, ...rest] = array; 2 | const [a, b, ...rest] = array; 3 | function a([a, b, ...rest]) { 4 | } 5 | ([a, b, ...rest]) => { }; 6 | -------------------------------------------------------------------------------- /test/compare-harmony.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | esprima = require('./3rdparty/esprima-harmony.original'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect, 32 | DIR; 33 | 34 | function test(code, expected) { 35 | var tree, actual, options, StringObject; 36 | 37 | // alias, so that JSLint does not complain. 38 | StringObject = String; 39 | 40 | options = { 41 | range: true, 42 | loc: false, 43 | tokens: true, 44 | raw: false 45 | }; 46 | 47 | tree = esprima.parse(code, options); 48 | 49 | // for UNIX text comment 50 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 51 | expect(actual).to.be.equal(expected); 52 | } 53 | 54 | function testMin(code, expected) { 55 | var tree, tree2, actual, actual2, options, StringObject; 56 | 57 | // alias, so that JSLint does not complain. 58 | StringObject = String; 59 | 60 | options = { 61 | range: true, 62 | loc: false, 63 | tokens: true, 64 | raw: false 65 | }; 66 | 67 | tree = esprima.parse(code, options); 68 | 69 | // for UNIX text comment 70 | actual = escodegen.generate(tree, { 71 | format: escodegen.FORMAT_MINIFY, 72 | raw: false 73 | }).replace(/[\n\r]$/, '') + '\n'; 74 | expect(actual).to.be.equal(expected); 75 | 76 | // And ensure that minified value is exactly equal. 77 | tree2 = esprima.parse(actual, options); 78 | actual2 = escodegen.generate(tree2, { 79 | format: escodegen.FORMAT_MINIFY, 80 | raw: false 81 | }).replace(/[\n\r]$/, '') + '\n'; 82 | expect(actual2).to.be.equal(actual); 83 | } 84 | 85 | DIR = 'compare-harmony'; 86 | 87 | describe('compare harmony test', function () { 88 | fs.readdirSync(__dirname + '/' + DIR).sort().forEach(function(file) { 89 | var code, expected, exp, min; 90 | if (/\.js$/.test(file) && !/expected\.js$/.test(file) && !/expected\.min\.js$/.test(file)) { 91 | it(file, function () { 92 | exp = file.replace(/\.js$/, '.expected.js'); 93 | min = file.replace(/\.js$/, '.expected.min.js'); 94 | code = fs.readFileSync(__dirname + '/' + DIR + '/' + file, 'utf-8'); 95 | expected = fs.readFileSync(__dirname + '/' + DIR + '/' + exp, 'utf-8'); 96 | test(code, expected); 97 | if (fs.existsSync(__dirname + '/' + DIR + '/' + min)) { 98 | expected = fs.readFileSync(__dirname + '/' + DIR + '/' + min, 'utf-8'); 99 | testMin(code, expected); 100 | } 101 | }); 102 | } 103 | }); 104 | }); 105 | /* vim: set sw=4 ts=4 et tw=80 : */ 106 | -------------------------------------------------------------------------------- /test/compare-harmony/arrow-function.expected.js: -------------------------------------------------------------------------------- 1 | e => { 2 | print('hello world'); 3 | }; 4 | (e1, e2, e3) => { 5 | print('hello world'); 6 | }; 7 | e => e; 8 | (e1, e2, e3) => e; 9 | e => { 10 | }; 11 | e => 20 + 20; 12 | -------------------------------------------------------------------------------- /test/compare-harmony/arrow-function.expected.min.js: -------------------------------------------------------------------------------- 1 | e=>{print('hello world')};(e1,e2,e3)=>{print('hello world')};e=>e;(e1,e2,e3)=>e;e=>{};e=>20+20 2 | -------------------------------------------------------------------------------- /test/compare-harmony/arrow-function.js: -------------------------------------------------------------------------------- 1 | e => { 2 | print('hello world'); 3 | }; 4 | (e1, e2, e3) => { 5 | print('hello world'); 6 | }; 7 | e => e; 8 | (e1, e2, e3) => e; 9 | (e) => { 10 | }; 11 | e => 20 + 20 12 | -------------------------------------------------------------------------------- /test/compare-harmony/class-declaration.expected.js: -------------------------------------------------------------------------------- 1 | class Test { 2 | } 3 | class Derived extends Super { 4 | } 5 | class Derived2 extends Super() { 6 | } 7 | class StaticMethods { 8 | static n1() { 9 | } 10 | static get get1() { 11 | } 12 | static set set1(value) { 13 | } 14 | static *gen1() { 15 | } 16 | } 17 | class Methods { 18 | n2() { 19 | } 20 | get get2() { 21 | } 22 | set set2(value) { 23 | } 24 | *gen1() { 25 | } 26 | } 27 | class ComputedStaticMethods { 28 | static n1() { 29 | } 30 | static get get1() { 31 | } 32 | static set set1(value) { 33 | } 34 | static *gen1() { 35 | } 36 | } 37 | class ComputedMethods { 38 | n2() { 39 | } 40 | get get2() { 41 | } 42 | set set2(value) { 43 | } 44 | *gen1() { 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/compare-harmony/class-declaration.expected.min.js: -------------------------------------------------------------------------------- 1 | class Test{}class Derived extends Super{}class Derived2 extends Super(){}class StaticMethods{static n1(){}static get get1(){}static set set1(value){}static*gen1(){}}class Methods{n2(){}get get2(){}set set2(value){}*gen1(){}}class ComputedStaticMethods{static n1(){}static get get1(){}static set set1(value){}static*gen1(){}}class ComputedMethods{n2(){}get get2(){}set set2(value){}*gen1(){}} 2 | -------------------------------------------------------------------------------- /test/compare-harmony/class-declaration.js: -------------------------------------------------------------------------------- 1 | class Test { 2 | } 3 | class Derived extends Super { 4 | } 5 | class Derived2 extends Super() { 6 | } 7 | class StaticMethods { 8 | static n1() { 9 | } 10 | 11 | static get get1() { 12 | } 13 | 14 | static set set1(value) { 15 | } 16 | 17 | static *gen1() { 18 | } 19 | } 20 | class Methods { 21 | n2() { 22 | } 23 | 24 | get get2() { 25 | } 26 | 27 | set set2(value) { 28 | } 29 | 30 | *gen1() { 31 | } 32 | } 33 | class ComputedStaticMethods { 34 | static [n1]() { 35 | } 36 | 37 | static get [get1]() { 38 | } 39 | 40 | static set [set1](value) { 41 | } 42 | 43 | static *[gen1]() { 44 | } 45 | } 46 | class ComputedMethods { 47 | [n2]() { 48 | } 49 | 50 | get [get2]() { 51 | } 52 | 53 | set [set2](value) { 54 | } 55 | 56 | *[gen1]() { 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /test/compare-harmony/class-expression.expected.js: -------------------------------------------------------------------------------- 1 | (class Test { 2 | }); 3 | (class Derived extends Super { 4 | }); 5 | (class Derived2 extends Super() { 6 | }); 7 | (class StaticMethods { 8 | static n1() { 9 | } 10 | static get get1() { 11 | } 12 | static set set1(value) { 13 | } 14 | static *gen1() { 15 | } 16 | }); 17 | (class Methods { 18 | n2() { 19 | } 20 | get get2() { 21 | } 22 | set set2(value) { 23 | } 24 | *gen1() { 25 | } 26 | }); 27 | (class ComputedStaticMethods { 28 | static n1() { 29 | } 30 | static get get1() { 31 | } 32 | static set set1(value) { 33 | } 34 | static *gen1() { 35 | } 36 | }); 37 | (class ComputedMethods { 38 | n2() { 39 | } 40 | get get2() { 41 | } 42 | set set2(value) { 43 | } 44 | *gen1() { 45 | } 46 | }); 47 | (class { 48 | }); 49 | (class extends Super() { 50 | }); 51 | -------------------------------------------------------------------------------- /test/compare-harmony/class-expression.expected.min.js: -------------------------------------------------------------------------------- 1 | (class Test{});(class Derived extends Super{});(class Derived2 extends Super(){});(class StaticMethods{static n1(){}static get get1(){}static set set1(value){}static*gen1(){}});(class Methods{n2(){}get get2(){}set set2(value){}*gen1(){}});(class ComputedStaticMethods{static n1(){}static get get1(){}static set set1(value){}static*gen1(){}});(class ComputedMethods{n2(){}get get2(){}set set2(value){}*gen1(){}});(class{});(class extends Super(){}) 2 | -------------------------------------------------------------------------------- /test/compare-harmony/class-expression.js: -------------------------------------------------------------------------------- 1 | (class Test { }); 2 | (class Derived extends Super { }); 3 | (class Derived2 extends Super() { }); 4 | (class StaticMethods { 5 | static n1() { 6 | } 7 | 8 | static get get1() { 9 | } 10 | 11 | static set set1(value) { 12 | } 13 | 14 | static *gen1() { 15 | } 16 | }); 17 | (class Methods { 18 | n2() { 19 | } 20 | 21 | get get2() { 22 | } 23 | 24 | set set2(value) { 25 | } 26 | 27 | *gen1() { 28 | } 29 | }); 30 | (class ComputedStaticMethods { 31 | static [n1]() { 32 | } 33 | 34 | static get [get1]() { 35 | } 36 | 37 | static set [set1](value) { 38 | } 39 | 40 | static *[gen1]() { 41 | } 42 | }); 43 | (class ComputedMethods { 44 | [n2]() { 45 | } 46 | 47 | get [get2]() { 48 | } 49 | 50 | set [set2](value) { 51 | } 52 | 53 | *[gen1]() { 54 | } 55 | }); 56 | (class { }); 57 | (class extends Super() { }); 58 | -------------------------------------------------------------------------------- /test/compare-harmony/computed-property.expected.js: -------------------------------------------------------------------------------- 1 | var object1 = { 2 | get [Symbol.create]() { 3 | }, 4 | set [set()](value) { 5 | } 6 | }; 7 | var object2 = { 8 | *[generator()]() { 9 | } 10 | }; 11 | var object3 = { 12 | *[generator()]() { 13 | } 14 | }; 15 | var object4 = { 16 | [Symbol.xxx]: 'hello', 17 | [ok()]: 42 18 | }; 19 | -------------------------------------------------------------------------------- /test/compare-harmony/computed-property.expected.min.js: -------------------------------------------------------------------------------- 1 | var object1={get [Symbol.create](){},set [set()](value){}};var object2={*[generator()](){}};var object3={*[generator()](){}};var object4={[Symbol.xxx]:'hello',[ok()]:42} 2 | -------------------------------------------------------------------------------- /test/compare-harmony/computed-property.js: -------------------------------------------------------------------------------- 1 | var object1 = { 2 | // MethodDefinition 3 | get [Symbol.create]() { }, 4 | set [set()](value) { }, 5 | }; 6 | var object2 = { 7 | *[generator()]() { } 8 | }; 9 | var object3 = { 10 | *[generator()]() { } 11 | }; 12 | var object4 = { 13 | // Normal Property 14 | [Symbol.xxx]: 'hello', 15 | [ok()]: 42, 16 | }; 17 | -------------------------------------------------------------------------------- /test/compare-harmony/default-parameter.expected.js: -------------------------------------------------------------------------------- 1 | function a(p = 20) { 2 | } 3 | function b(p, q = 30) { 4 | } 5 | function c(p, q = 30, ...r) { 6 | } 7 | (p = 20) => { 8 | }; 9 | (p = 20, ...q) => { 10 | }; 11 | -------------------------------------------------------------------------------- /test/compare-harmony/default-parameter.expected.min.js: -------------------------------------------------------------------------------- 1 | function a(p=20){}function b(p,q=30){}function c(p,q=30,...r){}(p=20)=>{};(p=20,...q)=>{} 2 | -------------------------------------------------------------------------------- /test/compare-harmony/default-parameter.js: -------------------------------------------------------------------------------- 1 | function a(p=20) { 2 | } 3 | 4 | function b(p, q=30) { 5 | } 6 | 7 | function c(p, q=30, ...r) { 8 | } 9 | 10 | (p = 20) => { }; 11 | (p = 20, ...q) => { }; 12 | -------------------------------------------------------------------------------- /test/compare-harmony/destructuring-assignment.expected.js: -------------------------------------------------------------------------------- 1 | function t1({responseText: responseText}) { 2 | } 3 | function t2({responseText}) { 4 | } 5 | function t3([a, b]) { 6 | } 7 | var [i, j, k] = array; 8 | var {i, j, k} = obj; 9 | let {i, j, k} = obj; 10 | const {i, j, k} = obj; 11 | var {value} = obj; 12 | var {value} = obj; 13 | var [obj.hello] = prop; 14 | var [obj.hello, ...obj.ok] = prop; 15 | var [obj.hello, ...obj['hello']] = prop; 16 | -------------------------------------------------------------------------------- /test/compare-harmony/destructuring-assignment.expected.min.js: -------------------------------------------------------------------------------- 1 | function t1({responseText:responseText}){}function t2({responseText}){}function t3([a,b]){}var [i,j,k]=array;var {i,j,k}=obj;let {i,j,k}=obj;const {i,j,k}=obj;var {value}=obj;var {value}=obj;var [obj.hello]=prop;var [obj.hello,...obj.ok]=prop;var [obj.hello,...obj['hello']]=prop 2 | -------------------------------------------------------------------------------- /test/compare-harmony/destructuring-assignment.js: -------------------------------------------------------------------------------- 1 | function t1({responseText: responseText}) { 2 | } 3 | function t2({responseText}) { 4 | } 5 | function t3([a, b]) { 6 | } 7 | var [i, j, k] = array; 8 | var {i, j, k} = obj; 9 | let {i, j, k} = obj; 10 | const {i, j, k} = obj; 11 | var { 12 | value 13 | } = obj; 14 | var { 15 | value 16 | } = obj; 17 | var [obj.hello] = prop; 18 | var [obj.hello, ...obj.ok] = prop; 19 | var [obj.hello, ...obj['hello']] = prop; 20 | -------------------------------------------------------------------------------- /test/compare-harmony/for-of-statement.expected.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | for (var i of array) { 3 | } 4 | for (let i of array) { 5 | } 6 | for (let c of ('x', String('cat'))) { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/compare-harmony/for-of-statement.expected.min.js: -------------------------------------------------------------------------------- 1 | function test(){for(var i of array){}for(let i of array){}for(let c of('x',String('cat'))){}} 2 | -------------------------------------------------------------------------------- /test/compare-harmony/for-of-statement.js: -------------------------------------------------------------------------------- 1 | function test() { 2 | for (var i of array) { 3 | } 4 | 5 | for (let i of array) { 6 | } 7 | 8 | for (let c of ('x', String('cat'))) { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/compare-harmony/one-assignment-property.expected.js: -------------------------------------------------------------------------------- 1 | ({t: t} = obj); 2 | ({ 3 | t: {C: C} 4 | } = obj); 5 | ({a, b, c} = obj); 6 | -------------------------------------------------------------------------------- /test/compare-harmony/one-assignment-property.expected.min.js: -------------------------------------------------------------------------------- 1 | ({t:t}=obj);({t:{C:C}}=obj);({a,b,c}=obj) 2 | -------------------------------------------------------------------------------- /test/compare-harmony/one-assignment-property.js: -------------------------------------------------------------------------------- 1 | ({ t: t }) = obj; 2 | ({ 3 | t: { C: C } 4 | }) = obj; 5 | ({ a, b, c }) = obj; 6 | -------------------------------------------------------------------------------- /test/compare-harmony/spread-element.expected.js: -------------------------------------------------------------------------------- 1 | var [a, b, ...rest] = array; 2 | const [a, b, ...rest] = array; 3 | -------------------------------------------------------------------------------- /test/compare-harmony/spread-element.expected.min.js: -------------------------------------------------------------------------------- 1 | var [a,b,...rest]=array;const [a,b,...rest]=array 2 | -------------------------------------------------------------------------------- /test/compare-harmony/spread-element.js: -------------------------------------------------------------------------------- 1 | var [a, b, ...rest] = array; 2 | const [a, b, ...rest] = array; 3 | -------------------------------------------------------------------------------- /test/compare-harmony/templates-escape.expected.js: -------------------------------------------------------------------------------- 1 | var escaped = ` 2 | \u2028 3 | \u2029 4 | `; 5 | var escaped = ` 6 | \v 7 | \b 8 | \t 9 | \n 10 | \r 11 | `; 12 | -------------------------------------------------------------------------------- /test/compare-harmony/templates-escape.expected.min.js: -------------------------------------------------------------------------------- 1 | var escaped=` 2 | \u2028 3 | \u2029 4 | `;var escaped=` 5 | \v 6 | \b 7 | \t 8 | \n 9 | \r 10 | ` 11 | -------------------------------------------------------------------------------- /test/compare-harmony/templates-escape.js: -------------------------------------------------------------------------------- 1 | var escaped = ` 2 | \u2028 3 | \u2029 4 | `; 5 | 6 | var escaped = ` 7 | \v 8 | \b 9 | \t 10 | \n 11 | \r 12 | `; 13 | -------------------------------------------------------------------------------- /test/compare-harmony/templates.expected.js: -------------------------------------------------------------------------------- 1 | var hello = `hello`; 2 | var hello = ` 3 | line 4 | terminators`; 5 | var tagged = tagged`hello`; 6 | var tagged = member.call`hello`; 7 | var tagged = new call`hello`(); 8 | var tagged = new (call`hello`())(); 9 | var tageed = member[call`hello`]; 10 | var middles = ` 11 | Is the order a rabbit? 12 | `; 13 | var middles = ` 14 | Is the order ${ order }? 15 | `; 16 | var middles = ` 17 | Is the order ${ order }? 18 | `; 19 | var middles = ` 20 | 1. ${ cocoa } 21 | 2. ${ chino } 22 | 3. ${ rize } 23 | 4. ${ syaro } 24 | 5. ${ chiya } 25 | `; 26 | -------------------------------------------------------------------------------- /test/compare-harmony/templates.expected.min.js: -------------------------------------------------------------------------------- 1 | var hello=`hello`;var hello=` 2 | line 3 | terminators`;var tagged=tagged`hello`;var tagged=member.call`hello`;var tagged=new call`hello`;var tagged=new(call`hello`());var tageed=member[call`hello`];var middles=` 4 | Is the order a rabbit? 5 | `;var middles=` 6 | Is the order ${order}? 7 | `;var middles=` 8 | Is the order ${order}? 9 | `;var middles=` 10 | 1. ${cocoa} 11 | 2. ${chino} 12 | 3. ${rize} 13 | 4. ${syaro} 14 | 5. ${chiya} 15 | ` 16 | -------------------------------------------------------------------------------- /test/compare-harmony/templates.js: -------------------------------------------------------------------------------- 1 | var hello = `hello`; 2 | 3 | var hello = ` 4 | line 5 | terminators`; 6 | 7 | var tagged = tagged`hello`; 8 | var tagged = member.call`hello`; 9 | var tagged = new call`hello`(); 10 | var tagged = new (call`hello`()); 11 | var tageed = member[call`hello`]; 12 | 13 | var middles = ` 14 | Is the order a rabbit? 15 | `; 16 | 17 | var middles = ` 18 | Is the order ${ order }? 19 | `; 20 | 21 | var middles = ` 22 | Is the order ${ order }? 23 | `; 24 | 25 | var middles = ` 26 | 1. ${ cocoa } 27 | 2. ${ chino } 28 | 3. ${ rize } 29 | 4. ${ syaro } 30 | 5. ${ chiya } 31 | `; 32 | -------------------------------------------------------------------------------- /test/compare-harmony/yield-precedence.expected.js: -------------------------------------------------------------------------------- 1 | function* foo() { 2 | var a = yield wat(), b = 2; 3 | var c = yield a = b; 4 | yield a, yield b; 5 | yield a = b; 6 | return (yield 1) || (yield 2); 7 | } 8 | -------------------------------------------------------------------------------- /test/compare-harmony/yield-precedence.expected.min.js: -------------------------------------------------------------------------------- 1 | function*foo(){var a=yield wat(),b=2;var c=yield a=b;yield a,yield b;yield a=b;return(yield 1)||(yield 2)} 2 | -------------------------------------------------------------------------------- /test/compare-harmony/yield-precedence.js: -------------------------------------------------------------------------------- 1 | function *foo () { 2 | var a = yield wat(), b = 2; 3 | var c = yield a = b; 4 | yield a, yield b; 5 | yield a = b; 6 | return (yield 1) || (yield 2); 7 | } 8 | -------------------------------------------------------------------------------- /test/compare.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | esprima = require('./3rdparty/esprima-1.0.0-dev'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect; 32 | 33 | function test(code, expected) { 34 | var tree, actual, options, StringObject; 35 | 36 | // alias, so that JSLint does not complain. 37 | StringObject = String; 38 | 39 | options = { 40 | range: true, 41 | loc: false, 42 | tokens: true, 43 | raw: false 44 | }; 45 | 46 | tree = esprima.parse(code, options); 47 | 48 | // for UNIX text comment 49 | actual = escodegen.generate(tree).replace(/[\n\r]$/, '') + '\n'; 50 | expect(actual).to.be.equal(expected); 51 | } 52 | 53 | describe('compare test', function () { 54 | fs.readdirSync(__dirname + '/compare').sort().forEach(function(file) { 55 | var code, expected, p; 56 | if (/\.js$/.test(file) && !/expected\.js$/.test(file)) { 57 | it(file, function () { 58 | p = file.replace(/\.js$/, '.expected.js'); 59 | code = fs.readFileSync(__dirname + '/compare/' + file, 'utf-8'); 60 | expected = fs.readFileSync(__dirname + '/compare/' + p, 'utf-8'); 61 | test(code, expected); 62 | }); 63 | } 64 | }); 65 | }); 66 | 67 | /* vim: set sw=4 ts=4 et tw=80 : */ 68 | -------------------------------------------------------------------------------- /test/compare/binary-precedence.expected.js: -------------------------------------------------------------------------------- 1 | a + b + c; 2 | a + (b + c); 3 | a + b * c; 4 | a * b + c; 5 | -------------------------------------------------------------------------------- /test/compare/binary-precedence.js: -------------------------------------------------------------------------------- 1 | (a + b) + c; 2 | a + (b + c); 3 | a + b * c; 4 | a * b + c; 5 | -------------------------------------------------------------------------------- /test/compare/bitwise-precedence.expected.js: -------------------------------------------------------------------------------- 1 | x | y ^ z; 2 | x | y ^ z; 3 | (x | y) ^ z; 4 | -------------------------------------------------------------------------------- /test/compare/bitwise-precedence.js: -------------------------------------------------------------------------------- 1 | x | y ^ z; 2 | x | (y ^ z); 3 | (x | y) ^ z; 4 | -------------------------------------------------------------------------------- /test/compare/floating-point.expected.js: -------------------------------------------------------------------------------- 1 | 1 .valueOf(); 2 | 1.1.valueOf(); 3 | 1e+300.valueOf(); 4 | -------------------------------------------------------------------------------- /test/compare/floating-point.js: -------------------------------------------------------------------------------- 1 | (1).valueOf(); 2 | 1.1.valueOf(); 3 | (1e+300).valueOf(); 4 | -------------------------------------------------------------------------------- /test/compare/for-in-no-in.expected.js: -------------------------------------------------------------------------------- 1 | for (var i = (1 in []) in []); 2 | for (var i = 1 in [] in []); 3 | for (var i = (10 * 10 in []) in []); 4 | for (var i = (10 + 10 in []) in []); 5 | for (var i = 10 + (10 in []) in []); 6 | for (var i = 10 + 10 in [] in []); 7 | for (var i = (1 in []);;); 8 | for ((1 in []);;); 9 | for (1 * (1 in []);;); 10 | for (1 * (1 + 1 in []);;); 11 | for (1 * (1 + 1 in []);;); 12 | for (1 * (1 + (1 in []));;); 13 | -------------------------------------------------------------------------------- /test/compare/for-in-no-in.js: -------------------------------------------------------------------------------- 1 | for (var i = (1 in []) in []); 2 | for (var i = 1 in [] in []); 3 | for (var i = (10 * 10 in []) in []); 4 | for (var i = (10 + 10 in []) in []); 5 | for (var i = 10 + (10 in []) in []); 6 | for (var i = 10 + 10 in [] in []); 7 | for (var i = (1 in []);;); 8 | for ((1 in []);;); 9 | for (1 * (1 in []);;); 10 | for (1 * (1 + 1 in []);;); 11 | for (1 * ((1 + 1) in []);;); 12 | for (1 * (1 + (1 in []));;); 13 | -------------------------------------------------------------------------------- /test/compare/new-precedence.expected.js: -------------------------------------------------------------------------------- 1 | new (a()).b(); 2 | new a().b(); 3 | new (a()).b(); 4 | new (a())(); 5 | new new a(a)(); 6 | new new a()(a); 7 | new a().test; 8 | new a().test; 9 | new (a()).test(); 10 | -------------------------------------------------------------------------------- /test/compare/new-precedence.js: -------------------------------------------------------------------------------- 1 | new (a().b)(); 2 | new a().b(); 3 | new (a()).b(); 4 | new (a()); 5 | new new a(a); 6 | new (new a)(a); 7 | (new a()).test; 8 | (new a().test); 9 | (new (a().test)); 10 | -------------------------------------------------------------------------------- /test/compare/one-property-with-line-terminator.expected.js: -------------------------------------------------------------------------------- 1 | dejavu.Class.declare({ 2 | method2: function () { 3 | } 4 | }); 5 | -------------------------------------------------------------------------------- /test/compare/one-property-with-line-terminator.js: -------------------------------------------------------------------------------- 1 | dejavu.Class.declare({ 2 | method2: function () {} 3 | }); 4 | -------------------------------------------------------------------------------- /test/compare/unary-op.expected.js: -------------------------------------------------------------------------------- 1 | delete delete i; 2 | + +i; 3 | !!i; 4 | + ++i; 5 | - --i; 6 | -------------------------------------------------------------------------------- /test/compare/unary-op.js: -------------------------------------------------------------------------------- 1 | delete delete i; 2 | + +i; 3 | !!i; 4 | + ++i; 5 | - --i; 6 | -------------------------------------------------------------------------------- /test/compare/unnecessary-parenthesized-in-2.expected.js: -------------------------------------------------------------------------------- 1 | var i = 1 * (2 + 0 in []); 2 | for (var i = 1 * (2 + 0 in []) in []); 3 | -------------------------------------------------------------------------------- /test/compare/unnecessary-parenthesized-in-2.js: -------------------------------------------------------------------------------- 1 | var i = 1 * (2 + 0 in []); 2 | for (var i = 1 * (2 + 0 in []) in []); 3 | -------------------------------------------------------------------------------- /test/compare/unnecessary-parenthesized-in.expected.js: -------------------------------------------------------------------------------- 1 | var i = 0 in ['test']; 2 | -------------------------------------------------------------------------------- /test/compare/unnecessary-parenthesized-in.js: -------------------------------------------------------------------------------- 1 | var i = 0 in ['test']; 2 | -------------------------------------------------------------------------------- /test/compare/variable-declaration.expected.js: -------------------------------------------------------------------------------- 1 | var fact5 = function fact(n) { 2 | if (n <= 1) 3 | return 1; 4 | return n * fact(n - 1); 5 | }(5); 6 | -------------------------------------------------------------------------------- /test/compare/variable-declaration.js: -------------------------------------------------------------------------------- 1 | var fact5 = function fact(n){ 2 | if (n <= 1) return 1 3 | return n * fact(n - 1) 4 | }(5) -------------------------------------------------------------------------------- /test/directive.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var esprima = require('./3rdparty/esprima-1.0.0-dev'), 28 | escodegen = require('./loader'), 29 | chai = require('chai'), 30 | expect = chai.expect, 31 | data; 32 | 33 | data = { 34 | 'DirectiveStatement': { 35 | 36 | '\'use strict\';': { 37 | type: 'Program', 38 | body: [{ 39 | type: 'DirectiveStatement', 40 | directive: 'use strict', 41 | }] 42 | }, 43 | 44 | '(\'use strict\');': { 45 | type: 'Program', 46 | body: [{ 47 | type: 'ExpressionStatement', 48 | expression: { 49 | type: 'Literal', 50 | value: 'use strict', 51 | } 52 | }] 53 | }, 54 | 55 | '{\n \'use strict\';\n}': { 56 | type: 'Program', 57 | body: [{ 58 | type: 'BlockStatement', 59 | body: [{ 60 | type: 'ExpressionStatement', 61 | expression: { 62 | type: 'Literal', 63 | value: 'use strict', 64 | } 65 | }] 66 | }] 67 | }, 68 | 69 | '(function () {\n (\'use strict\');\n});': { 70 | type: 'Program', 71 | body: [{ 72 | type: 'ExpressionStatement', 73 | expression: { 74 | type: 'FunctionExpression', 75 | id: null, 76 | params: [], 77 | body: { 78 | type: 'BlockStatement', 79 | body: [{ 80 | type: 'ExpressionStatement', 81 | expression: { 82 | type: 'Literal', 83 | value: 'use strict', 84 | } 85 | }] 86 | } 87 | } 88 | }] 89 | }, 90 | 91 | '(function () {\n \'use strict\';\n});': { 92 | type: 'Program', 93 | body: [{ 94 | type: 'ExpressionStatement', 95 | expression: { 96 | type: 'FunctionExpression', 97 | id: null, 98 | params: [], 99 | body: { 100 | type: 'BlockStatement', 101 | body: [{ 102 | type: 'DirectiveStatement', 103 | directive: 'use strict', 104 | }] 105 | } 106 | } 107 | }] 108 | }, 109 | 110 | '(function () {\n "use strict";\n});': { 111 | type: 'Program', 112 | body: [{ 113 | type: 'ExpressionStatement', 114 | expression: { 115 | type: 'FunctionExpression', 116 | id: null, 117 | params: [], 118 | body: { 119 | type: 'BlockStatement', 120 | body: [{ 121 | type: 'DirectiveStatement', 122 | directive: 'use strict', 123 | raw: '"use strict"' 124 | }] 125 | } 126 | } 127 | }] 128 | }, 129 | 130 | '(function () {\n \'use\\u0020strict\';\n});': { 131 | type: 'Program', 132 | body: [{ 133 | type: 'ExpressionStatement', 134 | expression: { 135 | type: 'FunctionExpression', 136 | id: null, 137 | params: [], 138 | body: { 139 | type: 'BlockStatement', 140 | body: [{ 141 | type: 'DirectiveStatement', 142 | directive: 'use\\u0020strict', 143 | }] 144 | } 145 | } 146 | }] 147 | }, 148 | 149 | '(function () {\n "use\\u0020strict\'";\n});': { 150 | type: 'Program', 151 | body: [{ 152 | type: 'ExpressionStatement', 153 | expression: { 154 | type: 'FunctionExpression', 155 | id: null, 156 | params: [], 157 | body: { 158 | type: 'BlockStatement', 159 | body: [{ 160 | type: 'DirectiveStatement', 161 | directive: 'use\\u0020strict\'', 162 | }] 163 | } 164 | } 165 | }] 166 | }, 167 | 168 | '(function () {\n {\n \'use strict\';\n }\n});': { 169 | type: 'Program', 170 | body: [{ 171 | type: 'ExpressionStatement', 172 | expression: { 173 | type: 'FunctionExpression', 174 | id: null, 175 | params: [], 176 | body: { 177 | type: 'BlockStatement', 178 | body: [{ 179 | type: 'BlockStatement', 180 | body: [{ 181 | type: 'ExpressionStatement', 182 | expression: { 183 | type: 'Literal', 184 | value: 'use strict', 185 | } 186 | }] 187 | }] 188 | } 189 | } 190 | }] 191 | } 192 | 193 | } 194 | }; 195 | 196 | function runTest(expected, result) { 197 | var actual, options; 198 | 199 | options = { 200 | indent: ' ', 201 | directive: true, 202 | parse: esprima.parse 203 | }; 204 | 205 | actual = escodegen.generate(result, options); 206 | expect(actual).to.be.equal(expected); 207 | } 208 | 209 | describe('directive support', function () { 210 | Object.keys(data).forEach(function (category) { 211 | it(category, function () { 212 | Object.keys(data[category]).forEach(function (source) { 213 | runTest(source, data[category][source]); 214 | }); 215 | }); 216 | }); 217 | }); 218 | -------------------------------------------------------------------------------- /test/harmony-esprima2.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011-2013 Yusuke Suzuki 3 | Copyright (C) 2015 Ingvar Stepanyan 4 | Copyright (C) 2012 Ariya Hidayat 5 | Copyright (C) 2012 Joost-Wim Boekesteijn 6 | Copyright (C) 2012 Yusuke Suzuki 7 | Copyright (C) 2012 Arpad Borsos 8 | Copyright (C) 2011 Ariya Hidayat 9 | Copyright (C) 2011 Arpad Borsos 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | 14 | * Redistributions of source code must retain the above copyright 15 | notice, this list of conditions and the following disclaimer. 16 | * Redistributions in binary form must reproduce the above copyright 17 | notice, this list of conditions and the following disclaimer in the 18 | documentation and/or other materials provided with the distribution. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 24 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | 'use strict'; 33 | 34 | var esprima = require('./3rdparty/esprima-2.7.1'), 35 | escodegen = require('./loader'), 36 | chai = require('chai'), 37 | expect = chai.expect, 38 | data; 39 | 40 | data = { 41 | 'Harmony MetaProperty': { 42 | 'class SomeClass { constructor() { if (new.target === SomeClass) { throw new Error(\'Boom\'); }}}': { 43 | type: 'Program', 44 | body: [ { 45 | type: "ClassDeclaration", 46 | id: { 47 | type: "Identifier", 48 | name: "SomeClass" 49 | }, 50 | superClass: null, 51 | body: { 52 | type: "ClassBody", 53 | body: [ 54 | { 55 | type: "MethodDefinition", 56 | key: { 57 | type: "Identifier", 58 | name: "constructor" 59 | }, 60 | computed: false, 61 | value: { 62 | type: "FunctionExpression", 63 | id: null, 64 | params: [], 65 | defaults: [], 66 | body: { 67 | type: "BlockStatement", 68 | body: [ 69 | { 70 | type: "IfStatement", 71 | test: { 72 | type: "BinaryExpression", 73 | operator: "===", 74 | left: { 75 | type: "MetaProperty", 76 | meta: { 77 | type: "Identifier", 78 | name: "new" 79 | }, 80 | property: { 81 | type: "Identifier", 82 | name: "target" 83 | }, 84 | }, 85 | right: { 86 | type: "Identifier", 87 | name: "SomeClass" 88 | } 89 | }, 90 | consequent: { 91 | type: "BlockStatement", 92 | body: [ 93 | { 94 | type: "ThrowStatement", 95 | argument: { 96 | type: "NewExpression", 97 | callee: { 98 | type: "Identifier", 99 | name: "Error" 100 | }, 101 | arguments: [ 102 | { 103 | type: "Literal", 104 | value: "Boom", 105 | raw: "'Boom'" 106 | } 107 | ] 108 | } 109 | } 110 | ] 111 | }, 112 | alternate: null 113 | } 114 | ] 115 | }, 116 | generator: false, 117 | expression: false 118 | }, 119 | kind: "constructor", 120 | static: false 121 | } 122 | ], 123 | } 124 | }], 125 | } 126 | }, 127 | }; 128 | 129 | function updateDeeply(target, override) { 130 | var key, val; 131 | 132 | function isHashObject(target) { 133 | return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp); 134 | } 135 | 136 | for (key in override) { 137 | if (override.hasOwnProperty(key)) { 138 | val = override[key]; 139 | if (isHashObject(val)) { 140 | if (isHashObject(target[key])) { 141 | updateDeeply(target[key], val); 142 | } else { 143 | target[key] = updateDeeply({}, val); 144 | } 145 | } else { 146 | target[key] = val; 147 | } 148 | } 149 | } 150 | return target; 151 | } 152 | 153 | // Special handling for regular expression literal since we need to 154 | // convert it to a string literal, otherwise it will be decoded 155 | // as object "{}" and the regular expression would be lost. 156 | function adjustRegexLiteral(key, value) { 157 | 'use strict'; 158 | if (key === 'value' && value instanceof RegExp) { 159 | value = value.toString(); 160 | } 161 | return value; 162 | } 163 | 164 | function testIdentity(code, syntax) { 165 | 'use strict'; 166 | var expected, tree, actual, actual2, options, StringObject; 167 | 168 | // alias, so that JSLint does not complain. 169 | StringObject = String; 170 | 171 | options = { 172 | comment: false, 173 | range: false, 174 | loc: false, 175 | tokens: false, 176 | raw: false 177 | }; 178 | 179 | tree = esprima.parse(code, options); 180 | expected = JSON.stringify(tree, adjustRegexLiteral, 4); 181 | tree = esprima.parse(escodegen.generate(tree), options); 182 | actual = JSON.stringify(tree, adjustRegexLiteral, 4); 183 | tree = esprima.parse(escodegen.generate(syntax), options); 184 | actual2 = JSON.stringify(tree, adjustRegexLiteral, 4); 185 | expect(actual).to.be.equal(expected); 186 | expect(actual2).to.be.equal(expected); 187 | } 188 | 189 | function testGenerate(expected, result) { 190 | 'use strict'; 191 | var actual, options; 192 | 193 | options = { 194 | indent: ' ', 195 | parse: esprima.parse 196 | }; 197 | 198 | if (result.options) { 199 | options = updateDeeply(options, result.options); 200 | } 201 | 202 | actual = escodegen.generate(result.generateFrom, options); 203 | expect(actual).to.be.equal(expected); 204 | } 205 | 206 | function isGeneratorIdentityFixture(result) { 207 | 'use strict'; 208 | return !result.hasOwnProperty('generateFrom') && 209 | !result.hasOwnProperty('result'); 210 | } 211 | 212 | function runTest(code, result) { 213 | 'use strict'; 214 | if (result.hasOwnProperty('generateFrom')) { 215 | testGenerate(code, result); 216 | } else { 217 | testIdentity(code, result); 218 | } 219 | } 220 | 221 | describe('harmony 2.x test', function () { 222 | Object.keys(data).forEach(function (category) { 223 | Object.keys(data[category]).forEach(function (source) { 224 | it(category, function () { 225 | var expected = data[category][source]; 226 | runTest(source, expected); 227 | }); 228 | }); 229 | }); 230 | }); 231 | /* vim: set sw=4 ts=4 et tw=80 : */ 232 | -------------------------------------------------------------------------------- /test/identity.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var fs = require('fs'), 28 | esprima = require('./3rdparty/esprima-1.0.0-dev'), 29 | escodegen = require('./loader'), 30 | chai = require('chai'), 31 | expect = chai.expect, 32 | fixtures; 33 | 34 | function slug(name) { 35 | return name.toLowerCase().replace(/\s/g, '-'); 36 | } 37 | 38 | function adjustRegexLiteral(key, value) { 39 | if (key === 'value' && value instanceof RegExp) { 40 | value = value.toString(); 41 | } 42 | return value; 43 | } 44 | 45 | fixtures = [ 46 | 'jQuery 1.7.1', 47 | 'jQuery 1.6.4', 48 | 'jQuery.Mobile 1.0', 49 | 'Prototype 1.7.0.0', 50 | 'Prototype 1.6.1', 51 | 'Ext Core 3.1.0', 52 | 'Ext Core 3.0.0', 53 | 'MooTools 1.4.1', 54 | 'MooTools 1.3.2', 55 | 'Backbone 0.5.3', 56 | 'Underscore 1.2.3' 57 | ]; 58 | 59 | function testIdentity(code) { 60 | var expected, tree, actual, options, commentOptions, commentTree, StringObject, err; 61 | 62 | // alias, so that JSLint does not complain. 63 | StringObject = String; 64 | 65 | // once 66 | options = { 67 | comment: false, 68 | range: false, 69 | loc: false, 70 | tokens: false, 71 | raw: false 72 | }; 73 | 74 | tree = esprima.parse(code, options); 75 | expected = JSON.stringify(tree, adjustRegexLiteral, 4); 76 | tree = esprima.parse(escodegen.generate(tree), options); 77 | actual = JSON.stringify(tree, adjustRegexLiteral, 4); 78 | expect(actual).to.be.equal(expected); 79 | 80 | // second, attachComments 81 | commentOptions = { 82 | comment: true, 83 | range: true, 84 | loc: false, 85 | tokens: true, 86 | raw: false 87 | }; 88 | 89 | commentTree = esprima.parse(code, commentOptions); 90 | commentTree = escodegen.attachComments(commentTree, commentTree.comments, commentTree.tokens); 91 | tree = esprima.parse(escodegen.generate(commentTree), options); 92 | actual = JSON.stringify(tree, adjustRegexLiteral, 4); 93 | expect(actual).to.be.equal(expected); 94 | } 95 | 96 | describe('identity test', function () { 97 | fixtures.forEach(function (filename) { 98 | it(filename, function () { 99 | var source = fs.readFileSync(__dirname + '/3rdparty/' + slug(filename) + '.js', 'utf-8'), 100 | size = source.length; 101 | testIdentity(source); 102 | }); 103 | }); 104 | }); 105 | /* vim: set sw=4 ts=4 et tw=80 : */ 106 | -------------------------------------------------------------------------------- /test/loader.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 'use strict'; 25 | 26 | var fs = require('fs'), 27 | path = require('path'), 28 | root = path.join(path.dirname(fs.realpathSync(__filename)), '..'), 29 | escodegen = require(root); 30 | 31 | // Make generate's first argument freezed. 32 | function freezing(escodegen) { 33 | var original = escodegen.generate; 34 | escodegen.generate = function () { 35 | var ast = arguments[0]; 36 | Object.freeze(ast); 37 | return original.apply(this, arguments); 38 | }; 39 | return escodegen; 40 | }; 41 | 42 | module.exports = freezing(escodegen); 43 | 44 | /* vim: set sw=4 ts=4 et tw=80 : */ 45 | -------------------------------------------------------------------------------- /test/preserve-blank-lines.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011-2013 Yusuke Suzuki 3 | Copyright (C) 2014 Kevin Barabash 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | 'use strict'; 27 | 28 | var fs = require('fs'), 29 | esprima = require('esprima'), 30 | escodegen = require('./loader'), 31 | chai = require('chai'), 32 | expect = chai.expect; 33 | 34 | function test(code, expected) { 35 | var tree, actual, options, StringObject; 36 | 37 | // alias, so that JSLint does not complain. 38 | StringObject = String; 39 | 40 | options = { 41 | range: true, 42 | tokens: true, 43 | comment: true 44 | }; 45 | 46 | tree = esprima.parse(code, options); 47 | tree = escodegen.attachComments(tree, tree.comments, tree.tokens); 48 | 49 | options = { 50 | comment: true, 51 | sourceCode: code, 52 | format: { 53 | preserveBlankLines: true 54 | } 55 | }; 56 | 57 | // for UNIX text comment 58 | actual = escodegen.generate(tree, options); 59 | expect(actual).to.be.equal(expected); 60 | } 61 | 62 | describe('preserve blank lines test', function () { 63 | fs.readdirSync(__dirname + '/preserve-blank-lines').sort().forEach(function(file) { 64 | var code, expected, p; 65 | if (/\.js$/.test(file) && !/expected\.js$/.test(file)) { 66 | it(file, function () { 67 | p = file.replace(/\.js$/, '.expected.js'); 68 | code = fs.readFileSync(__dirname + '/preserve-blank-lines/' + file, 'utf-8'); 69 | expected = fs.readFileSync(__dirname + '/preserve-blank-lines/' + p, 'utf-8'); 70 | test(code, expected); 71 | }); 72 | } 73 | }); 74 | }); 75 | 76 | /* vim: set sw=4 ts=4 et tw=80 : */ 77 | -------------------------------------------------------------------------------- /test/preserve-blank-lines/block-comments.expected.js: -------------------------------------------------------------------------------- 1 | var x; /* block comment after code */ 2 | 3 | var y = 5; 4 | 5 | /* block comment in between lines */ 6 | 7 | var z = 10; 8 | 9 | /** 10 | * multiline block comment 11 | */ 12 | 13 | var foo = function () { 14 | var a = 0; 15 | 16 | /* block comment in a function */ 17 | 18 | var b = 1; 19 | 20 | /** 21 | * multiline block comment in a function 22 | */ 23 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/block-comments.js: -------------------------------------------------------------------------------- 1 | var x; /* block comment after code */ 2 | 3 | var y = 5; 4 | 5 | /* block comment in between lines */ 6 | 7 | var z = 10; 8 | 9 | /** 10 | * multiline block comment 11 | */ 12 | 13 | var foo = function () { 14 | var a = 0; 15 | 16 | /* block comment in a function */ 17 | 18 | var b = 1; 19 | 20 | /** 21 | * multiline block comment in a function 22 | */ 23 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/comment-at-start-of-function.expected.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | // comment before code in function 3 | var x = 5; 4 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/comment-at-start-of-function.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | // comment before code in function 3 | var x = 5; 4 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/comments.expected.js: -------------------------------------------------------------------------------- 1 | /* single line block comment */ 2 | 3 | var x; 4 | 5 | // single line comment 6 | 7 | var y = 5; // comment after code 8 | 9 | var z = 10; 10 | 11 | var foo = function () { 12 | var a = 0; 13 | 14 | // single line comment in function 15 | 16 | var b = 1; // commdent after code in a function 17 | 18 | var c = 2; 19 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/comments.js: -------------------------------------------------------------------------------- 1 | /* single line block comment */ 2 | 3 | var x; 4 | 5 | // single line comment 6 | 7 | var y = 5; // comment after code 8 | 9 | var z = 10; 10 | 11 | var foo = function () { 12 | var a = 0; 13 | 14 | // single line comment in function 15 | 16 | var b = 1; // commdent after code in a function 17 | 18 | var c = 2; 19 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/functions.expected.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | var a; 3 | }; 4 | 5 | function bar() { 6 | var b; 7 | } 8 | 9 | var empty_foo = function () { 10 | 11 | }; 12 | 13 | function empty_bar() { 14 | // TODO: implement this function 15 | } 16 | 17 | foo(); 18 | 19 | bar(); -------------------------------------------------------------------------------- /test/preserve-blank-lines/functions.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | var a; 3 | }; 4 | 5 | function bar() { 6 | var b; 7 | } 8 | 9 | var empty_foo = function () { 10 | 11 | }; 12 | 13 | function empty_bar() { 14 | // TODO: implement this function 15 | } 16 | 17 | foo(); 18 | 19 | bar(); -------------------------------------------------------------------------------- /test/preserve-blank-lines/multiple-comments.expected.js: -------------------------------------------------------------------------------- 1 | // comment 1 2 | // comment 2 3 | // comment 3 4 | var a = 5; -------------------------------------------------------------------------------- /test/preserve-blank-lines/multiple-comments.js: -------------------------------------------------------------------------------- 1 | // comment 1 2 | // comment 2 3 | // comment 3 4 | var a = 5; -------------------------------------------------------------------------------- /test/preserve-blank-lines/trailing-comment-in-function.expected.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | var a = 0; 3 | 4 | var b = 1; // test 5 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/trailing-comment-in-function.js: -------------------------------------------------------------------------------- 1 | var foo = function () { 2 | var a = 0; 3 | 4 | var b = 1; // test 5 | }; -------------------------------------------------------------------------------- /test/preserve-blank-lines/trailing-comment-in-program.expected.js: -------------------------------------------------------------------------------- 1 | var a = 0; 2 | 3 | var b = 1; // test -------------------------------------------------------------------------------- /test/preserve-blank-lines/trailing-comment-in-program.js: -------------------------------------------------------------------------------- 1 | var a = 0; 2 | 3 | var b = 1; // test -------------------------------------------------------------------------------- /test/preserve-blank-lines/variables.expected.js: -------------------------------------------------------------------------------- 1 | var x; 2 | 3 | var y = 5; 4 | 5 | var z = 10; -------------------------------------------------------------------------------- /test/preserve-blank-lines/variables.js: -------------------------------------------------------------------------------- 1 | var x; 2 | 3 | var y = 5; 4 | 5 | var z = 10; -------------------------------------------------------------------------------- /test/verbatim.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012-2013 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict'; 26 | 27 | var esprima = require('./3rdparty/esprima-1.0.0-dev'), 28 | escodegen = require('./loader'), 29 | chai = require('chai'), 30 | expect = chai.expect, 31 | StringData, 32 | ObjectData; 33 | 34 | function make_eval(code) { 35 | return { 36 | type: 'CallExpression', 37 | callee: { 38 | type: 'Identifier', 39 | name: 'eval' 40 | }, 41 | 'arguments': [{ 42 | type: 'Literal', 43 | value: code 44 | }], 45 | verbatim: code 46 | }; 47 | } 48 | 49 | function runTest(expected, result, verbatim) { 50 | var actual, options; 51 | 52 | options = { 53 | indent: ' ', 54 | directive: true, 55 | parse: esprima.parse, 56 | verbatim: verbatim 57 | }; 58 | 59 | expect(function () { 60 | actual = escodegen.generate(result, options); 61 | }).not.to.be.throw(); 62 | expect(expected).to.be.equal(actual); 63 | } 64 | 65 | StringData = { 66 | 'DISABLED': { 67 | "eval('foo');": { 68 | type: 'ExpressionStatement', 69 | expression: make_eval('foo') 70 | } 71 | }, 72 | 73 | 'verbatim': { 74 | // Check it doesn't apply to statements 75 | "continue;": { 76 | type: 'ContinueStatement', 77 | verbatim: 'FOOBARBAZ' 78 | }, 79 | "foo;": { 80 | type: 'ExpressionStatement', 81 | expression: make_eval('foo') 82 | }, 83 | "true && (foo)": { 84 | type: 'BinaryExpression', 85 | operator: '&&', 86 | left: { type: 'Literal', value: true }, 87 | right: make_eval('foo') 88 | }, 89 | "var a = (window.location.href);": { 90 | type: 'VariableDeclaration', 91 | kind: 'var', 92 | declarations: [{ 93 | type: 'VariableDeclarator', 94 | id: { type: 'Identifier', name: 'a' }, 95 | init: make_eval('window.location.href') 96 | }] 97 | }, 98 | // Multiline 99 | "if (true) {\n foo('bar');\n foo('baz');\n}": { 100 | type: 'IfStatement', 101 | test: { type: 'Literal', value: true }, 102 | consequent: { 103 | type: 'BlockStatement', 104 | body: [{ 105 | type: 'ExpressionStatement', 106 | expression: make_eval("foo('bar');\nfoo('baz')") 107 | }] 108 | } 109 | }, 110 | // Embedded into sequences 111 | "foo(a, (10, 20), b)": { 112 | type: 'CallExpression', 113 | callee: { type: 'Identifier', name: 'foo' }, 114 | arguments: [{ 115 | type: 'Identifier', 116 | name: 'a' 117 | }, 118 | make_eval('10, 20'), 119 | { 120 | type: 'Identifier', 121 | name: 'b' 122 | }] 123 | }, 124 | // Floating point 125 | "(0).a": { 126 | type: 'MemberExpression', 127 | object: { type: 'Literal', value: 0, verbatim: '0' }, 128 | property: { type: 'Identifier', name: 'a' }, 129 | computed: false 130 | } 131 | } 132 | }; 133 | 134 | describe('verbatim string test', function () { 135 | var data = StringData; 136 | Object.keys(data).forEach(function (category) { 137 | it(category, function () { 138 | Object.keys(data[category]).forEach(function (source) { 139 | var expected = data[category][source]; 140 | runTest(source, expected, category); 141 | }); 142 | }); 143 | }); 144 | }); 145 | 146 | ObjectData = { 147 | 'verbatim': { 148 | // Floating point 149 | "(0).a": { 150 | type: 'MemberExpression', 151 | object: { type: 'Literal', value: 0, verbatim: { content: '0' } }, 152 | property: { type: 'Identifier', name: 'a' }, 153 | computed: false 154 | }, 155 | "([]).a": { 156 | type: 'MemberExpression', 157 | object: { type: 'Literal', verbatim: { content: '[]' } }, 158 | property: { type: 'Identifier', name: 'a' }, 159 | computed: false 160 | }, 161 | "[].a": { 162 | type: 'MemberExpression', 163 | object: { type: 'Literal', verbatim: { content: '[]', precedence: escodegen.Precedence.Primary } }, 164 | property: { type: 'Identifier', name: 'a' }, 165 | computed: false 166 | } 167 | } 168 | }; 169 | 170 | describe('verbatim object test', function () { 171 | var data = ObjectData; 172 | Object.keys(data).forEach(function (category) { 173 | it(category, function () { 174 | Object.keys(data[category]).forEach(function (source) { 175 | var expected = data[category][source]; 176 | runTest(source, expected, category); 177 | }); 178 | }); 179 | }); 180 | }); 181 | /* vim: set sw=4 ts=4 et tw=80 : */ 182 | -------------------------------------------------------------------------------- /tools/entry-point.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | (function () { 26 | 'use strict'; 27 | global.escodegen = require('../escodegen'); 28 | escodegen.browser = true; 29 | }()); 30 | -------------------------------------------------------------------------------- /tools/release.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | Copyright (C) 2012 Yusuke Suzuki 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | /*jslint sloppy:true node:true */ 27 | 28 | var fs = require('fs'), 29 | path = require('path'), 30 | root = path.join(path.dirname(fs.realpathSync(__filename)), '..'), 31 | escodegen = require(root), 32 | esprima = require('esprima'), 33 | RegistryClient = require('bower-registry-client'), 34 | semver = require('semver'), 35 | child_process = require('child_process'), 36 | Promise = require('bluebird'); 37 | 38 | function exec(cmd) { 39 | return new Promise(function (resolve, reject) { 40 | console.log(cmd); 41 | child_process.exec(cmd, function (error, stdout, stderr) { 42 | resolve(error, stdout, stderr); 43 | }); 44 | }); 45 | } 46 | 47 | (function () { 48 | var config, matched, version, devVersion, registry; 49 | 50 | config = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8')); 51 | devVersion = config.version; 52 | matched = devVersion.match(/^(\d+\.\d+\.\d+(-\d+)?)$/); 53 | if (!matched) { 54 | console.error('version style "' + devVersion + '" is not matched to X.X.X[-X].'); 55 | process.exit(1); 56 | } 57 | 58 | version = matched[1]; 59 | config.version = version; 60 | 61 | registry = new RegistryClient(); 62 | 63 | function ping(memo, name) { 64 | return new Promise(function (resolve, reject) { 65 | var pattern; 66 | console.log('[' + name + '] ' + 'send ping'); 67 | 68 | pattern = config.dependencies[name]; 69 | 70 | registry.lookup(name, function (err, entry) { 71 | var i, iz, version; 72 | 73 | if (err) { 74 | console.error('[' + name + '] ' + err.message + '. skip this dependency'); 75 | return; 76 | } 77 | 78 | console.log('[' + name + '] ' + 'received result'); 79 | memo[name] = pattern; 80 | resolve(); 81 | }); 82 | }); 83 | } 84 | 85 | exec('git branch -D ' + version) 86 | .then(function () { 87 | return exec('git checkout -b ' + version); 88 | }) 89 | .then(function generateConfigs() { 90 | var dependencies = {}, 91 | optionalDependencies = {}, 92 | promises; 93 | fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(config, null, 4), 'utf-8'); 94 | 95 | // generate component.json 96 | promises = 97 | Object.keys(config.dependencies).map(ping.bind(null, dependencies)).concat( 98 | Object.keys(config.optionalDependencies).map(ping.bind(null, optionalDependencies))); 99 | return Promise.all(promises).then(function () { 100 | config.dependencies = dependencies; 101 | config.optionalDependencies = optionalDependencies; 102 | fs.writeFileSync(path.join(root, 'component.json'), JSON.stringify(config, null, 4), 'utf-8'); 103 | }); 104 | }) 105 | .then(function browserify() { 106 | return exec('npm run-script build'); 107 | }) 108 | .then(function browserify() { 109 | return exec('npm run-script build-min'); 110 | }) 111 | .then(function gitAdd() { 112 | return exec('git add "' + root + '"'); 113 | }) 114 | .then(function gitCommit() { 115 | return exec('git commit -m "Bump version ' + version + '"'); 116 | }) 117 | .then(function gitDeleteTag() { 118 | return exec('git tag -d ' + version); 119 | }) 120 | .then(function gitAddTag() { 121 | return exec('git tag -a ' + version + ' -m "version ' + version + '"'); 122 | }) 123 | .then(function () { 124 | console.log('Finally you should execute npm publish and git push --tags'); 125 | }); 126 | }()); 127 | 128 | /* vim: set sw=4 ts=4 et tw=80 : */ 129 | -------------------------------------------------------------------------------- /tools/rules/push-with-multiple-arguments.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2014 Yusuke Suzuki 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 17 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | 'use strict' 26 | 27 | module.exports = function (context) { 28 | var MESSAGE = '"push" with multiple arguments hurts performance since optimizing compiler would not support it'; 29 | function checkPush(node) { 30 | var member; 31 | if (node.callee.type !== 'MemberExpression') { 32 | return; 33 | } 34 | member = node.callee; 35 | if (member.computed) { 36 | return; 37 | } 38 | if (member.property.type !== 'Identifier') { 39 | return; 40 | } 41 | if (member.property.name !== 'push') { 42 | return; 43 | } 44 | // Ensure arguments length is 1. 45 | if (node.arguments.length !== 1) { 46 | context.report(node, MESSAGE); 47 | } 48 | } 49 | 50 | return { 51 | 'CallExpression': checkPush 52 | }; 53 | }; 54 | --------------------------------------------------------------------------------