estools / escodegen Goto Github PK
View Code? Open in Web Editor NEWECMAScript code generator
License: BSD 2-Clause "Simplified" License
ECMAScript code generator
License: BSD 2-Clause "Simplified" License
We should handle harmony operators, is & isnt.
Add esprima harmony code generation.
Handle harmony method property.
var obj = {
method() {
}
};
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
VisitorOption, traverse, and Syntax seem to be available in estraverse
, can we include estraverse
as a dependency and remove the duplicate code from escodegen
?
https://github.com/Constellation/escodegen/blob/master/escodegen.js#L722
It's looking at the last character which will always be the same character as the operator.
We should handle yield statement's delegate flag
Do I have to update ranges manually after any change on AST object?
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!
Support directive flag for esmangle, it is implemented as option.
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);
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
spawn from #4
Move indent and base options to format.indent option.
npm install -g escodegen
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)
if (cond) stmt; else stmt2;
currently
if(cond)stmt; else stmt2;
should be
if(cond)stmt;else stmt2;
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
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
{ 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.
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.
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.
I suggest adding minify option to code generator.
try{}//
finally{}
yields
try {
} // finally {
}
since ddc4cd5.
A test case is available at https://gist.github.com/3142709
Esprima can provide range / loc information, so we can create SourceMap from this.
https://github.com/Constellation/escodegen/blob/master/package.json#L24
By having a floating dependency, you expose all users of your module to breaking changes when they install this in the future and new versions of your dependencies are broken. This can and will happen. Floating dependencies also make it harder to track down problems in the future as it becomes unclear what version of the code was actually tested against.
issue from #4
currently
if (cond)stmt;else if(cond) stmt;
result
if(cond)stmt;else if(cond)stmt;
should be
if(cond)stmt;else if(cond)stmt
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.
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.
I find it weird that the demo is in a separate repo. It should be in this repo, so that pull requests for changes to the demo land here.
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:
!{}
. 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 {}
.Create Options table like,
Options = {
// default options
}
and update it by provided options.
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?
Thanks to @mishoo, it is found that remove-context-sensitive-expression pass has a bug.
http://lisperator.net/blog/uglifyjs-why-not-switching-to-spidermonkey-ast/
escodegen.js embeds a copy of estraverse (see https://github.com/Constellation/escodegen/blob/master/escodegen.js#L2027) - specifically one that does not benefit from bugfixes in estraverse (including the recent fix of ObjectExpressions by @michaelficarra.
It also exports the embedded traverse function which, depending on the order in which escodegen and estraverse are loaded, can clobber the fixed version.
For tools that need both the output JS string and the source map, it will be more efficient.
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:
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.
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:
'-->'
as '--\\>'
,'<!--'
as '<\\!--'
,/<\/script([ \t\n\f\r]*>)/gi
as '<\\/script$1'
,']]>'
as ']]\\>'
,var \u0069\u0066;
would become var \u0069f;
),if(x)do{foo()}while(y);
),if (true) function foo(){return}
),throw
statement with a semicolon (function foo(){throw 'error';}
).I got to this project while discussing ways to do advanced code formatting for JS (source)
It would be great if it had the same level of control as FDT advanced code formatter - options to define how white space is handled between each kind of token (line break, space, none), indentation, keep/remove empty lines, etc.
Basically transform escodegen into a hardcore version of JSBeautifier.
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 :)
{
type: if,
c: {
type: if,
c: ...
},
a: {
...
}
}
is invalid AST, because this tree cannot be constructed naturally.
So we should raise error when this AST is given.
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. 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).
UnaryExpression doesn't need space when space !== '' for readability.
For example,
- 10
should be
-10
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.)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.