diff --git a/escodegen.js b/escodegen.js
index a8d0170c..54735ba6 100644
--- a/escodegen.js
+++ b/escodegen.js
@@ -2434,8 +2434,90 @@
ModuleSpecifier: function (expr, precedence, flags) {
return this.Literal(expr, precedence, flags);
- }
+ },
+
+ JSXIdentifier: function (expr, precedence, flags) {
+ return expr.name;
+ },
+
+ JSXMemberExpression: function (expr, precedence, flags) {
+ var result = [];
+ result.push(this.generateExpression(expr.object, precedence, flags));
+ result.push('.');
+ result.push(this.generateExpression(expr.property, precedence, flags));
+ return result;
+ },
+
+ JSXNamespacedName: function (expr, precedence, flags) {
+ var result = [];
+ result.push(this.generateExpression(expr.namespace, precedence, flags));
+ result.push(':');
+ result.push(this.generateExpression(expr.name, precedence, flags));
+ return result;
+ },
+ JSXEmptyExpression: function (expr, precedence, flags) {
+ return '';
+ },
+
+ JSXExpressionContainer: function (expr, precedence, flags) {
+ return ['{', this.generateExpression(expr.expression, precedence, flags), '}'];
+ },
+
+ JSXOpeningElement: function (expr, precedence, flags) {
+ var result, i, iz;
+ result = ['<'];
+ result.push(this.generateExpression(expr.name, precedence, flags));
+ if (expr.attributes) {
+ for(i = 0, iz = expr.attributes.length; i < iz; ++i) {
+ result.push(' ');
+ result.push(this.generateExpression(expr.attributes[i], precedence, flags));
+ }
+ }
+ result.push(expr.selfClosing ? ' />' : '>');
+ return result;
+ },
+
+ JSXClosingElement: function (expr, precedence, flags) {
+ return ['', this.generateExpression(expr.name, precedence, flags), '>'];
+ },
+
+ JSXAttribute: function (expr, precedence, flags) {
+ var result = [];
+ result.push(this.generateExpression(expr.name, precedence, flags));
+ result.push('=');
+ if (expr.value.type === 'Literal') {
+ result.push(this.generateExpression(expr.value, precedence, flags));
+ return result;
+ }
+ if (expr.value.type === 'JSXExpressionContainer') {
+ result.push(this.generateExpression(expr.value.expression, precedence, flags));
+ return result;
+ }
+ },
+
+ JSXSpreadAttribute: function (expr, precedence, flags) {
+ return ['{...', this.generateExpression(expr.argument, precedence, flags), '}'];
+ },
+
+ JSXText: function (expr, precedence, flags) {
+ return expr.value;
+ },
+
+ JSXElement: function (expr, precedence, flags) {
+ var result, i, iz;
+ result = [];
+ result.push(this.generateExpression(expr.openingElement, precedence, flags));
+ if (expr.children) {
+ for(i = 0, iz = expr.children.length; i < iz; ++i) {
+ result.push(this.generateExpression(expr.children[i], precedence, flags));
+ }
+ }
+ if (expr.closingElement) {
+ result.push(this.generateExpression(expr.closingElement, precedence, flags));
+ }
+ return result;
+ }
};
merge(CodeGenerator.prototype, CodeGenerator.Expression);
diff --git a/package.json b/package.json
index 30c90ddb..386df98c 100644
--- a/package.json
+++ b/package.json
@@ -30,9 +30,9 @@
"url": "http://github.com/estools/escodegen.git"
},
"dependencies": {
+ "esprima": "^4.0.1",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
- "esprima": "^3.1.3",
"optionator": "^0.8.1"
},
"optionalDependencies": {
diff --git a/test/test.js b/test/test.js
index a21cd487..0556ed37 100644
--- a/test/test.js
+++ b/test/test.js
@@ -30,7 +30,7 @@
'use strict';
-var esprima = require('./3rdparty/esprima-1.0.0-dev'),
+var esprima = require('esprima'),
escodegen = require('./loader'),
chai = require('chai'),
expect = chai.expect,
@@ -14871,6 +14871,357 @@ data = {
},
tokens: []
}
+ },
+
+ 'JSX': {
+
+ '': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'Tag'
+ },
+ selfClosing: true,
+ attributes: []
+ },
+ children: [],
+ closingElement: null
+ },
+
+ '': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'TagWithSpace'
+ },
+ selfClosing: true,
+ attributes: []
+ },
+ children: [],
+ closingElement: null
+ },
+
+
+ '': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXMemberExpression',
+ object: {
+ type: 'JSXMemberExpression',
+ object: {
+ type: 'JSXMemberExpression',
+ object: {
+ type: 'JSXIdentifier',
+ name: 'Member'
+ },
+ property: {
+ type: 'JSXIdentifier',
+ name: 'Expression'
+ }
+ },
+ property: {
+ type: 'JSXIdentifier',
+ name: 'Tag'
+ },
+ },
+ property: {
+ type: 'JSXIdentifier',
+ name: 'Name'
+ }
+ },
+ selfClosing: true,
+ attributes: []
+ },
+ children: [],
+ closingElement: null
+ },
+
+ '': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'Tag'
+ },
+ selfClosing: true,
+ attributes: [
+ {
+ type: 'JSXAttribute',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'attr'
+ },
+ value: {
+ type: 'Literal',
+ value: 'string',
+ raw: '\"string\"'
+ }
+ }
+ ]
+ },
+ children: [],
+ closingElement: null
+ },
+
+ ' {} }}/>': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'Spread'
+ },
+ selfClosing: true,
+ attributes: [
+ {
+ type: 'JSXSpreadAttribute',
+ argument: {
+ type: 'ObjectExpression',
+ properties: [
+ {
+ type: 'Property',
+ key: {
+ type: 'Identifier',
+ name: 'attr'
+ },
+ computed: false,
+ value: {
+ type: 'Literal',
+ value: 'string',
+ raw: 'string',
+ },
+ kind: 'init',
+ method: false,
+ shorthand: false
+ },
+ {
+ type: 'Property',
+ key: {
+ type: 'Identifier',
+ name: 'func'
+ },
+ computed: false,
+ value: {
+ type: 'ArrowFunctionExpression',
+ id: null,
+ params: [],
+ body: {
+ type: 'BlockStatement',
+ body: []
+ },
+ generator: false,
+ expression: false,
+ 'async': false
+ },
+ kind: 'init',
+ method: false,
+ shorthand: false
+ }
+ ]
+ }
+ }
+ ]
+ },
+ children: [],
+ closingElement: null
+ },
+
+ '': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXNamespacedName',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'Name'
+ },
+ namespace: {
+ type: 'JSXIdentifier',
+ name: 'Namespaced'
+ }
+ },
+ selfClosing: true,
+ attributes: []
+ },
+ children: [],
+ closingElement: null
+ },
+
+
+ ' { return true }}/>': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'Tag'
+ },
+ selfClosing: true,
+ attributes: [
+ {
+ "type": "JSXAttribute",
+ "name": {
+ "type": "JSXIdentifier",
+ "name": "attr"
+ },
+ "value": {
+ "type": "Literal",
+ "value": "string",
+ "raw": "\"string\""
+ }
+ },
+ {
+ "type": "JSXAttribute",
+ "name": {
+ "type": "JSXIdentifier",
+ "name": "expression"
+ },
+ "value": {
+ "type": "JSXExpressionContainer",
+ "expression": {
+ "type": "ArrowFunctionExpression",
+ "id": null,
+ "params": [],
+ "body": {
+ "type": "BlockStatement",
+ "body": [
+ {
+ "type": "ReturnStatement",
+ "argument": {
+ "type": "Literal",
+ "value": true,
+ "raw": "true"
+ }
+ }
+ ]
+ },
+ generator: false,
+ expression: false
+ }
+ }
+ }
+ ]
+ },
+ children: [],
+ closingElement: null
+ },
+
+ '': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'WithClosingTag'
+ },
+ attributes: []
+ },
+ children: [],
+ closingElement: {
+ type: 'JSXClosingElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'WithClosingTag'
+ }
+ }
+ },
+
+ 'text': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'WithTextChild'
+ },
+ attributes: []
+ },
+ children: [
+ {
+ type: 'JSXText',
+ value: 'text',
+ raw: 'text'
+ }
+ ],
+ closingElement: {
+ type: 'JSXClosingElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'WithTextChild'
+ }
+ }
+ },
+
+ '{() => {}}': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'WithExpressionChild'
+ },
+ attributes: []
+ },
+ children: [
+ {
+ type: 'JSXExpressionContainer',
+ expression: {
+ type: 'ArrowFunctionExpression',
+ id: null,
+ params: [],
+ body: {
+ type: 'BlockStatement',
+ body: []
+ },
+ generator: false,
+ expression: false,
+ 'async': false
+ }
+ }
+ ],
+ closingElement: {
+ type: 'JSXClosingElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'WithExpressionChild'
+ }
+ }
+ },
+
+ '{}': {
+ type: 'JSXElement',
+ openingElement: {
+ type: 'JSXOpeningElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'EmptyExpression'
+ },
+ selfClosing: false,
+ },
+ children: [
+ {
+ type: 'JSXExpressionContainer',
+ expression: {
+ type: 'JSXEmptyExpression'
+ }
+ }
+ ],
+ closingElement: {
+ type: 'JSXClosingElement',
+ name: {
+ type: 'JSXIdentifier',
+ name: 'EmptyExpression'
+ }
+ }
+ },
}
};
@@ -14895,7 +15246,8 @@ function testIdentity(code, syntax) {
range: false,
loc: false,
tokens: false,
- raw: false
+ raw: false,
+ jsx: true
};
expect(function () {