Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support JSX Syntax #1467

Closed
ariya opened this issue Feb 7, 2016 · 10 comments
Closed

Support JSX Syntax #1467

ariya opened this issue Feb 7, 2016 · 10 comments
Assignees
Milestone

Comments

@ariya
Copy link
Contributor

ariya commented Feb 7, 2016

Optionally, Esprima should be able to consume JSX syntax: https://facebook.github.io/jsx/. See also https://github.com/facebook/jsx/blob/master/AST.md.

The grammar extension is summarized below (adopted from the specification linked above).

Lexical Grammar

JSXIdentifier :: JSXIdentifierStart | JSXIdentifier JSXIdentifierPart

JSXIdentifierStart :: IdentifierStart (but not \)

JSXIdentifierPart :: IdentifierPart (but_not \) | -

JSXText :: JSXTextCharacter JSXTextopt

JSXTextCharacter :: SourceCharacter but not one of {, <, > or }

JSXStringLiteral :: ' JSXText ' | " JSXText "

Primary expression

JSX extends the PrimaryExpression in the ECMAScript 6th Edition (ECMA-262) grammar:

PrimaryExpression :: JSXElement

Elements

Note: names of JSXOpeningElement and JSXClosingElement should match.

JSXElement :: JSXSelfClosingElement | JSXOpeningElement JSXChildrenopt JSXClosingElement

JSXSelfClosingElement :: < JSXElementName JSXAttributesopt / >

JSXOpeningElement :: < JSXElementName JSXAttributesopt >

JSXClosingElement :: < / JSXElementName >

JSXElementName :: JSXIdentifier | JSXNamedspacedName | JSXMemberExpression

JSXNamespacedName :: JSXIdentifier : JSXIdentifier

JSXMemberExpression :: JSXIdentifier . JSXIdentifier | JSXMemberExpression . JSXIdentifier

Attributes

JSXAttributes :: JSXSpreadAttribute JSXAttributesopt | JSXAttribute JSXAttributesopt

JSXSpreadAttribute :: { ... AssignmentExpression }

JSXAttribute :: JSXAttributeName | JSXAttributeName = JSXAttributeValue

JSXAttributeName :: JSXIdentifier | JSXNamespacedName

JSXAttributeValue :: StringLiteral | { AssignmentExpression } | JSXElement

Children

JSXChildren : JSXChild JSXChildrenopt

JSXChild :: JSXText | JSXElement | { AssignmentExpressionopt }

@ariya ariya self-assigned this Feb 7, 2016
@ariya ariya added this to the 3.0 milestone Feb 7, 2016
@michaelficarra
Copy link
Contributor

Why? This isn't even standards track.

@ariya
Copy link
Contributor Author

ariya commented Feb 7, 2016

Given the current modular state of the code base, I believe it is time for Esprima to participate in the React.js world without a significant additional maintenance burden!

@michaelficarra
Copy link
Contributor

If it was user extensible, esprima wouldn't have to participate, and more importantly wouldn't have to take on that maintenance burden.

@ariya
Copy link
Contributor Author

ariya commented Feb 7, 2016

After considering a few different strategies, I've decided that I can take the risk of implementing it in Esprima, with the future possibilities of subsequent refactoring, a detached plug-in, or other types of improvements.

@ariya
Copy link
Contributor Author

ariya commented Feb 7, 2016

A notable difference between Flow and the old esprima-fb is the use of JSXText node instead of plain Literal node in the list of child nodes JSXChildren. Consider the example snippet <strong> <em>Hello</em> </strong> and the children of the element:

Flow:

[ { type: 'JSXText', value: ' ', raw: ' ' },
  { type: 'JSXElement',
    openingElement: 
     { type: 'JSXOpeningElement',
       name: [Object],
       selfClosing: false,
       attributes: [] },
    closingElement: { type: 'JSXClosingElement', name: [Object] },
    children: [ [Object] ] },
  { type: 'JSXText', value: ' ', raw: ' ' } ]

old esprima-fb:

[ { type: 'Literal', value: ' ', raw: ' ' },
  { type: 'JSXElement',
    openingElement: 
     { type: 'JSXOpeningElement',
       name: [Object],
       selfClosing: false,
       attributes: [] },
    closingElement: { type: 'JSXClosingElement', name: [Object] },
    children: [ [Object] ] },
  { type: 'Literal', value: ' ', raw: ' ' } ]

Which one shall I follow @sebmarkbage @jeffmo?

@sebmarkbage
Copy link
Contributor

The ESTree compatible extension spec for JSX says Literal:

https://github.com/facebook/jsx/blob/master/AST.md#jsx-element

I believe it is what Babylon/Acorn does.

@jeffmo Should we update Flow to be consistent with this ESTree extension?

@michaelficarra
Copy link
Contributor

@sebmarkbage Overloading Literal even more than it already is sounds like a bad idea. Also, I believe the babel AST split apart the Literal node long ago.

@ariya
Copy link
Contributor Author

ariya commented Feb 9, 2016

Babel has switched from Literal to JSXText since version 6. Even non-ESTree tools such as TypeScript and Traceur do not stick with Literal and use a similar name, JsxText.

I am also leaning towards JSXText node. After all, I assume Flow should be the reference here.

I can open an ESTree issue if we prefer the discussion to happen over there.

@bartosz-k
Copy link

Asking here because couldn't find answer anywhere on the Internet: how to parse today using esprima with JSX support enabled?

@ariya
Copy link
Contributor Author

ariya commented Mar 19, 2016

@Bartq This is not part of any release yet. To watch for a release, subscribe yourself to a service like https://libraries.io/npm/esprima.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants