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

JSX Transformer / DisplayName Visitor: Multiple declarations with one var statement #27

Merged
merged 2 commits into from
May 31, 2013

Conversation

seiffert
Copy link
Contributor

The bug fixed by this commit prevented the correct parsing of var statements with multiple variables being declared. Instead of trying to parse a whole 'variable declarations' (a var statement with all its declarations), this visitor now only parses single 'variable declarators'.

An example (from the tutorial) that did not work before this patch:

    var CommentBox = React.createClass({
      ...
    }),

    CommentList = React.createClass({
      ...
    });

What did work is the following:

    var CommentBox = React.createClass({
      ...
    });

    var CommentList = React.createClass({
      ...
    });

Of course, there are different coding styles and guidelines. Most developers probably don't like multiple variables being declared with one var statement, but nevertheless, it should be possible.

The bug fixed by this commit prevented the correct parsing of
`var` statements with multiple variables being declared. Instead
of trying to parse a whole 'variable declarations' (a `var`
statement with all its declarations), this visitor now only
parses single 'variable declarators'.
@jordwalke
Copy link
Contributor

:like: I hadn't considered this case. I'm curious how you are using the displayName. We have a bookmarklet that will annotate the page with visual labels on top of the DOM that tell you the names of the components that generated that part of the page. I'll see if we can get that checked in.

@seiffert
Copy link
Contributor Author

Oh actually I'm not using displayName myself, the page just won't render because javascript dies with an Uncaught SyntaxError: Unexpected token <. The output of fbtransform still contains tag literals:

      var CommentBox = React.createClass({
        ...
      }),

      CommentList = React.createClass({
        render: function() {
          var comments = this.props.data.map(function (comment) {
            return <Comment author={comment.author}>{comment.text}</Comment>;
          });

          return (
            <div class="commentList">
              {comments}
            </div>
          );
        }
      });

(the body of CommentBox is omitted since it is transformed correctly.)

@seiffert
Copy link
Contributor Author

And: I would really be interested in this bookmarklet! :)

@jeffmo
Copy link
Contributor

jeffmo commented May 30, 2013

Hmm, I'm having a hard time reproing this issue... I made repro.js:

/**
 * @jsx React.DOM
 */

var CommentBox = React.createClass({render: function() {}}),

        CommentList = React.createClass({render: function() {}});

and when I run ./bin/jsx repro.js I get this:

/**
 * @jsx React.DOM
 */

var CommentBox = React.createClass({displayName: 'CommentBox',render: function() {}}),

        CommentList = React.createClass({displayName: 'CommentList',render: function() {}});

Did you include the "@jsx" tag in the docblock at the top? Or maybe I'm missing something?

@seiffert
Copy link
Contributor Author

@jeffmo Could you please try to make render return a DOM component? The transformation of this JSX code to javascript is what doesn't work for me... The transformation should happen in browser-transforms.js on line 39. However, after executing this line, the variable functionBody holds the string contained in this gist: https://gist.github.com/seiffert/5681370.
What is happening is that the reactDisplayName visitor iterates over all declarations included in the var. As far as I understand, it should only add the component's displayName property to its initializer's first argument. What it actually does is the following: For every declaration, it copies the script from the current pointer to the first argument of the declaration's initializer into the script buffer. However, this step copies all contents from the last declaration's initializer's first argument's position (stored in state.g.position) to the current declaration's initializer's first argument into the buffer. This effectively copies the whole untransformed initializer into the script buffer.
After this, the normal transformation takes place which leads to the correct but somehow ~duplicate output at the bottom...

Yes, I do have a @jsx React.DOM tag in the docblock at the top of my <script> tag - see the whole HTML document here.

@seiffert
Copy link
Contributor Author

I tried to reproduce the problem with the jsx binary - it does not occur! WIth the version of JSXTransformer.js installed via bower install react, the problem can be reproduced...

@jeffmo
Copy link
Contributor

jeffmo commented May 30, 2013

Aha you're right! It's because we move past the contents of the object literal in the displayName transform step before the react.js transform has a chance to run on the declaration node.

Ok, do you mind filling out our CLA and then I can merge this in for you:
https://developers.facebook.com/opensource/cla

dec.init.callee.property.name === 'createClass' &&
dec.init['arguments'].length === 1 &&
dec.init['arguments'][0].type === Syntax.ObjectExpression) {
if (object.type === Syntax.VariableDeclarator &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This first conditional is no longer necessary since it's checked in visitReactDisplayName.test() -- mind killing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, if we can rely on test() being called before visitReactDisplayName(), we can remove that first condition!

@jeffmo
Copy link
Contributor

jeffmo commented May 31, 2013

This looks good to after we clear up line 39 -- thanks a ton for the fix!

@seiffert
Copy link
Contributor Author

I already signed the CLA!

jeffmo pushed a commit that referenced this pull request May 31, 2013
JSX Transformer / DisplayName Visitor: Multiple declarations with one `var` statement
@jeffmo jeffmo merged commit 2d253fe into facebook:master May 31, 2013
steveluscher added a commit that referenced this pull request Sep 14, 2015
…-edition

Community Roundup #27 – Relay Edition
steveluscher added a commit that referenced this pull request Sep 14, 2015
(cherry picked from commit f30b0d1)
bvaughn added a commit to bvaughn/react that referenced this pull request Aug 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants