GithubHelp home page GithubHelp logo

estools / escodegen Goto Github PK

View Code? Open in Web Editor NEW
2.6K 63.0 333.0 2.68 MB

ECMAScript code generator

License: BSD 2-Clause "Simplified" License

JavaScript 99.97% Shell 0.03%
estree ast javascript ecmascript

escodegen's People

Contributors

adamjmcgrath avatar arian avatar ariya avatar bezoerb avatar comp615 avatar constellation avatar drslump avatar ef4 avatar gozala avatar gregglind avatar jkroso avatar johnjbarton avatar juandopazo avatar kennethkufluk avatar kevinbarabash avatar mathiasbynens avatar michaelficarra avatar msridhar avatar papandreou avatar realityking avatar rgustbardon avatar rreverser avatar sanex3339 avatar therajumandapati avatar tolmasky avatar tootallnate avatar toshok avatar twada avatar zaach avatar zjmiller avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

escodegen's Issues

undefined appearing in function definitions?

Hi all,

I am using the following code to try out escodegen:

var source = "var hello = function(){return 'hello world!';}; var hello1 = world; function world(hello){return hello;} var number = function(num){return num;}; hello(); var hello2 = 1+1*number(1)"
var res = esprima.parse(source);
escodegen.generate(res)

the output on my end is:

"var hello = function () {
undefinedreturn 'hello world!';
}; 
var hello1 = world;
function world(hello) {
undefinedreturn hello;
}
var number = function (num) {
undefinedreturn num;
};
hello();
var hello2 = 1 + 1 * number(1);"

The problem is with all the "undefined" appearing in the function body. Any help would be appreciated :)

Jason

Use estraverse where appropriate

VisitorOption, traverse, and Syntax seem to be available in estraverse, can we include estraverse as a dependency and remove the duplicate code from escodegen?

Spaces in properties names cause problems?

js> print(this.escodegen.generate(Reflect.parse('var a = {}; a["some thing"] = 1')))
var a = {};
a.some thing = 1;

Perhaps Syntax.MemberExpression?

result.push('.' + expr.property.name);

It seems like all of this opens a can of worms, but who knows!

remove unnecessary parenthesis around 'in'

Currenlty, for NoIn expression, we always add parenthesis around 'in' operator.

for example,

for (i = (20 in 30) in 40);

should not generate

for (i = 20 in 30 in 40);

Division becomes a single-line comment

With options.format.compact enabled, the problem described at http://code.google.com/p/closure-compiler/issues/detail?id=620 can be observed.

TEMP=$(mktemp)
echo '/ / / / /' | tee "$TEMP"
node <<ENDH
console.log(require("util").inspect(
    require(process.env.HOME + "/github/ariya/esprima/esprima.js").parse(
        "/ / / / /", {comment: true}), null, null))
ENDH
v8 \
  "$HOME/github/ariya/esprima/esprima.js" \
  "$HOME/github/Constellation/escodegen/escodegen.js" \
  /dev/stdin > "$TEMP" <<'ENDH'
print(escodegen.generate(esprima.parse("/ / / / /"), {format: {compact:true}}))
ENDH
cat "$TEMP"
node <<ENDH
console.log(require("util").inspect(
    require(process.env.HOME + "/github/ariya/esprima/esprima.js").parse(
        require("fs").readFileSync("$TEMP"), {comment: true}), null, null))
ENDH

Tested on Ubuntu 12.04 LTS with ariya/esprima@465a4ea and 5de45f6

Error: Cannot find module 'esprima' when install only escodegen

Step to reproduce

  1. Remove all package from npm global
  2. npm install -g escodegen
  3. 'escodegen file'

Actual Result

Error: Cannot find module 'esprima'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:362:17)
    at require (module.js:378:17)
    at Object.<anonymous> (npm/lib/node_modules/escodegen/bin/esgenerate.js:29:15)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)

Escodegen support of Moz-style harmony js is incomplete

it needs at least:

ObjectPattern
escodegen.js:350: Error: Numeric literal whose value is negative
escodegen.js:1143: Error: Unknown expression type: YieldExpression
escodegen.js:1611: Error: Unknown statement type: CallExpression

Implement complete automatic semicolon insertion

For the time being, when options.format.semicolons is set to false, only semicolons at the end of programs, blocks, and case blocks are omitted. However, setting this option to false should make complete reliance on automatic semicolon insertion (7.9) possible, e.g.

42;foo;

should result in (with options.format.compact set to false)

42
foo

instead of

42;
foo

Moreover, in the future, with options.format.compact and comments preserved, the input:

42;
/*A
*/
foo;

should result in

42/*A
*/foo

and the input

42;
//A
foo;

should result in

42//A
foo

For pitfalls with regard to reliance on automatic semicolon insertion, see http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#Semicolons

---x, +++x

{ type: 'UpdateExpression',
  argument:                                                                               
   { type: 'UnaryExpression',
     argument: { type: 'Identifier', name: 'x' },
     operator: '-' },
  operator: '--',
  prefix: true }

produces ---x instead of -(--x) or - --x. I'm preparing a patch.

Throw an error if comments can't be attached

If esprima has been used to generate a tree without any of range, tokens or comment options, I think escodegen can't output the comments. I think escodegen should just throw (or at least console.warn) in these cases to indicate that comments can't be properly outputed.

Make escodegen.attachComments implicit with comment: true

Currently, the following doesn't work:

var ast = esprima.parse(sourceCode, {range: true, tokens: true, comment: true})
console.log('result:', escodegen.generate(ast, {comment: true}));

However, this works:

var ast = esprima.parse(sourceCode, {range: true, tokens: true, comment: true});
ast = escodegen.attachComments(ast, ast.comments, ast.tokens);
console.log('result:', escodegen.generate(ast, {comment: true}));

I don't understand the need for the attachComments call. Passing comment:true should be enough so that comments show up.

Support compliance with JSHint

options.format.jshint would make sure that, as far as the code generator is concerned, i.e. without transforming the abstract syntax tree, and with all enforcing options available in JSHint, generated code is JSHint-compliant. Whether the option in question is to be enabled by default is another matter.

fails when ObjectExpression properties don't have a type property

When I parse var a = {a: 2} with acorn, the resulting AST is as follows:

{
  "type": "Program",
  "start": 0,
  "end": 14,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 14,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 14,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 5,
            "name": "a"
          },
          "init": {
            "type": "ObjectExpression",
            "start": 8,
            "end": 14,
            "properties": [
              {
                "key": {
                  "type": "Identifier",
                  "start": 9,
                  "end": 10,
                  "name": "a"
                },
                "value": {
                  "type": "Literal",
                  "start": 12,
                  "end": 13,
                  "value": 2,
                  "raw": "2"
                },
                "kind": "init"
              }
            ]
          }
        }
      ],
      "kind": "var"
    }
  ]
}

As you can see the properties of the ObjectExpression don't have a type property. This causes escodegen to fail:

/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1385
            throw new Error('Unknown expression type: ' + expr.type);
                  ^
Error: Unknown expression type: undefined
    at generateExpression (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1385:19)
    at result (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1188:28)
    at withIndent (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:592:21)
    at generateExpression (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1187:13)
    at generateStatement (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1512:21)
    at generateExpression.precedence (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1544:42)
    at withIndent (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:592:21)
    at generateStatement (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1537:17)
    at generateStatement (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1757:21)
    at Object.generate (/home/arian/www/wrapup/node_modules/escodegen/escodegen.js:1919:22)

Esprima addes type: "Property", however according to https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API#Expressions this is not required.

Allow safe concatenation with other programs

options.format.safe would make sure that the generated code can be safely followed by another ECMAScript program. The option would take precedence over disabled options.format.semicolons. One can think of the following behavior:

  • If a program ends with a semicolon and, optionally, whitespace characters (7.2; as opposed to line terminators and multi-line comments that include such terminators), the semicolon should be preserved (cf. http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#Semicolons). For instance, a semicolon should appear at the end of the code generated given !{}. However, it should not be added if it results in an empty statement that does not exist in the original program. For instance, a semicolon must not appear at the end of the code generated given {}.
  • If a program ends with a single-line comment, the character U+000A should be added at the end of the program.

Combining multiple ASTs

I have multiple AST trees with location info. They are either generated by CoffeeScriptRedux or esprima.parse() (in case of raw JS files). I want to combine them into one single file with one source-map.

My naive attempt to this was to take the individual parse trees and wrap them into another Program node:

{
    type: 'Program',
    body: [
        {type: 'Program', loc: {source: 'file1.js', start: {line: 1, column: 1}}, body: [...]},
        {type: 'Program', loc: {source: 'file2.coffee', start: {line: 1, column: 1}}, body: [...]},
    ]
}

Unfortunately that doesn't work, you end up with something like this:

 {"version":3,"file":"test.map","sources":["test.map"],"names":[],"mappings":"AAAA,OAAA,IAAA,CAAY,UAAZ,CAAA"}

Is there a another way to concatenate multiple files that could possibly work?

Define a new node type as a chunk of code to output verbatim

Currently I don't see any way to pass a chunk of code to be outputted just as is in the generated source. The use case is when generating an AST from a language that allows to define chunks of code to be placed verbatim in the generated javascript, much like CoffeeScript's backtick notation.

It could work something like this:

{
    type: 'CodeExpression',
    code: 'window.location.href = "http://google.com"'
}

The generator would output the contents of the code with only the following processing performed:

  • Indent first line to the current level if it belongs to ExpressionStatement
  • Indent additional lines to the current level

Since it's impossible to know the precedence order of that node, it should always be assumed that it's very low (Assignment), wrapping it with parens if used in a binary or member expression for example.

Add support for quirks

options.format.quirks or more sophisticated options would allow supporting quirks. These options would take precedence over any other options.

What follows are the quirks supported by the Closure Compiler when it comes to code generation:

  • breaking lines after an arbitrary number of characters (500 characters in the Closure Compiler; 32768 characters in UglifyJS),
  • escaping '-->' as '--\\>',
  • escaping '<!--' as '<\\!--',
  • escaping /<\/script([ \t\n\f\r]*>)/gi as '<\\/script$1',
  • escaping ']]>' as ']]\\>',
  • escaping reserved words used as identifiers (illegal; not supported by Esprima; var \u0069\u0066; would become var \u0069f;),
  • putting a do-while statement of an if statement in a block (if(x)do{foo()}while(y);),
  • putting sole functions in a block (if (true) function foo(){return}),
  • terminating a throw statement with a semicolon (function foo(){throw 'error';}).

See also http://code.google.com/p/closure-compiler/source/browse/trunk/test/com/google/javascript/jscomp/CodePrinterTest.java?r=2027

Include comments if available?

I don't know if it's even possible based on the output of require('esprima').parse(str, {comment: true}), but just in case.

I have more use cases for comment-and-whitespace-preserving JavaScript source manipulation than I can count :)

New Operator Precedence

The expression "new (a().b)()" as parsed by esprima is incorrectly generated as "new a().b()".

identifiers that are also keywords are not properly escaped

Identifiers that are also keywords are not properly escaped. This causes escodegen to create invalid programs from valid ASTs. The simplest example:

{ type: 'Identifier', name: 'do' }

Expected output: either d\u006f or \u0064o or (hopefully not, though) \u0064\u006f.

Observed output: do (an invalid program).

Block comment at the start of a file is not attached to the owning syntax node

If a JS file begins with a block comment, attachComments does not attach the block comment to the syntax node that owns the comment.

For example, I used Esprima to parse this file, then called attachComments:

/**
 * @class MyClass
 */
function MyClass() {}

The block comment should be attached to the MyClass declaration. Instead, it is attached to the root node. (See this gist for the complete AST.)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.