Skip to content

Use raw value of JSXText and JSXAttribute#5256

Merged
danez merged 1 commit intobabel:7.0from
lightscript:jsx-escaping
Apr 4, 2017
Merged

Use raw value of JSXText and JSXAttribute#5256
danez merged 1 commit intobabel:7.0from
lightscript:jsx-escaping

Conversation

@rattrayalex
Copy link
Copy Markdown
Contributor

Q A
Patch: Bug Fix? yes
Major: Breaking Change? maybe?
Minor: New Feature? no
Deprecations? no
Spec Compliancy? I think so
Tests Added/Pass? Few tests added, which pass
Fixed Tickets Fixes babel/babylon#316 , Fixes babel/babylon#271
License MIT
Doc PR no
Dependency Changes babylon is changed as well

Depends on babel/babylon#344 (see that PR for description; happy to elaborate here if desired).

@babel-bot
Copy link
Copy Markdown
Collaborator

Hey @rattrayalex! It looks like one or more of your builds have failed. I've copied the relevant info below to save you some time.

@rattrayalex
Copy link
Copy Markdown
Contributor Author

Tests are failing b/c they're reading from the wrong version of Babylon; not sure how that is best addressed.

@xtuc
Copy link
Copy Markdown
Member

xtuc commented Feb 2, 2017

Thanks for your PR 👍

If tests are green locally, that's fine for now. We need to wait for babel/babylon#344.

Copy link
Copy Markdown
Member

@danez danez left a comment

Choose a reason for hiding this comment

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

Thanks for your PR but this is wrong, as JSX is not escaped as JS but as XHTML. That is the reason why the raw value is currently not present, so that we can escape the raw xhtml value with jsesc in babel when the jsx tag is converted to a StringLiteral. This will currently break I think and jsx->js is probably more used than jsx->jsx.

Having no raw for now is correct.

@rattrayalex
Copy link
Copy Markdown
Contributor Author

@danez can you provide an example test case?

@rattrayalex
Copy link
Copy Markdown
Contributor Author

rattrayalex commented Feb 2, 2017

Ahh, I think I understand... I essentially need to add tests with the transform-react-jsx plugin enabled, correct? And verify that, eg, React.createElement('div', {}, '\\w') is output instead of React.createElement('div', {}, '\w') ?

If so, didn't quite grasp the nature of the challenge at hand, apologies.

Judging by @kittens 's rants about the Literal node type, we'll need to do something like addExtra('isJSXText', true) – does that sound palatable?

EDIT: obviously not ideal, but perhaps better than removing an otherwise valid attribute from extra, which seems quite a bit hackier

@rattrayalex
Copy link
Copy Markdown
Contributor Author

Another possibility may be modifying the transform-react-jsx plugin itself, probably eg; here and here. Removing (or modifying) node.extra.rawand node.extra.rawValue at that point may be more appropriate.

Thoughts?

const raw = node.extra && node.extra.raw;
this.token("=");
this.print(node.value, node);
this.print(raw || node.value, node);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I know this PR has a few comments against the current implementation already, but I also want to add that this could in some cases lead to a breaking change. Say you had a transform that worked on these nodes that changed the .value. With this PR, the mutated value would be ignored in the final output since raw would exist. You'd want to use getPossibleRaw:

getPossibleRaw(node) {
so that value is compared to rawValue

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I'd intentionally avoided that because of the value and rawValue comparison, thinking that they'd be unequal in exactly the scenarios this PR attempts to address. But I didn't actually test that, and of course your point is valid, so I'll try to find a way to address it (may need to compare an escaped version of value or similar).

Thanks for the helpful catch @loganfsmyth !

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think you can use getPossibleRaw the same way we do for strings: https://github.com/babel/babel/blob/master/packages/babel-generator/src/generators/types.js#L139, if this PR is in fact accepted.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Cool, I'll give it a try. Thanks!

@rattrayalex
Copy link
Copy Markdown
Contributor Author

Thanks for the feedback @loganfsmyth – using getPossibleRaw now.

I'm now deleting node.extra.raw from the StringLiteral as it's generated from JSXAttribute, which feels much more appropriate and fixes the issues at hand.

I also added tests explicitly for the jsx->js case.

@danez does this look better to you?

@babel-bot
Copy link
Copy Markdown
Collaborator

Hey @rattrayalex! It looks like one or more of your builds have failed. I've copied the relevant info below to save you some time.

@rattrayalex
Copy link
Copy Markdown
Contributor Author

(as before, tests failing because they don't have the matching version of babylon, and pass locally)

@@ -0,0 +1,3 @@
<div id="wôw" />;
<div id="\w" />;
<div id="w &lt; w" />;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

would appreciate suggestions for other test-cases, as I think this is the crux of the issue (and was previously untested)

const raw = this.getPossibleRaw(node);
this.token("=");
this.print(node.value, node);
this.print(raw || node.value, node);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this particular call is actually doing anything, because JSXAttribute nodes don't have a .raw, their .value property does. I'm assuming this is working entirely because StringLiteral already checks for .raw.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah, yes, good catch. Thanks.

export function JSXText(node: Object) {
this.token(node.value);
const raw = this.getPossibleRaw(node);
this.token(raw || node.value);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we explicitly check === null since raw being an empty string would also cause this to use .value instead?

Thinking on this all a bit, I'm up for adding raw handling if we need it, but it seems like we should also have additional logic both here and in StringLiteral to handle encoding of .value, otherwise it's still totally possible for people to assign values to JSXText that will not be printed properly. The intention of .raw is to not lose the original formatting in the source file, if possible, but either way we don't want usage of .value without .raw to cause issues.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Can we explicitly check === null since raw being an empty string would also cause this to use .value instead?

Yep, good catch – though I assume you mean == null ?

I'll respond to the second para in a follow-up comment, since this thread is about to disappear when I push.

@rattrayalex
Copy link
Copy Markdown
Contributor Author

(pulling from in-thread comment from @loganfsmyth )

Thinking on this all a bit, I'm up for adding raw handling if we need it, but it seems like we should also have additional logic both here and in StringLiteral to handle encoding of .value, otherwise it's still totally possible for people to assign values to JSXText that will not be printed properly. The intention of .raw is to not lose the original formatting in the source file, if possible, but either way we don't want usage of .value without .raw to cause issues.

I'm not quite sure what you're suggesting?

I think the scenario you're concerned about is when a plugin modifies or creates a JSXText node with an invalid value – is that correct? And that, to defend against that, the printers for JSXText and StringLiteral should ensure that the value is always safe?

@babel-bot
Copy link
Copy Markdown
Collaborator

Hey @rattrayalex! It looks like one or more of your builds have failed. I've copied the relevant info below to save you some time.

@danez
Copy link
Copy Markdown
Member

danez commented Mar 16, 2017

I think what @loganfsmyth means is that even if raw is not set babel-generator should correctly create the raw value from value, so that we are not dependent on raw. Though I have no idea how we should do that, as I can't think of a solution of how we should do this correctly in all cases. Maybe you have an idea?

@danez
Copy link
Copy Markdown
Member

danez commented Mar 16, 2017

I'm fine with this as is for 7.0.

@danez danez added PR: Bug Fix 🐛 A type of pull request used for our changelog categories and removed enhancement labels Mar 16, 2017
@rattrayalex
Copy link
Copy Markdown
Contributor Author

Gotcha. Thanks @danez !

@danez
Copy link
Copy Markdown
Member

danez commented Mar 16, 2017

Can you rebase on the 7.0 branch?

@rattrayalex
Copy link
Copy Markdown
Contributor Author

Will do – though specs will still fail until babel/babylon#344 has gone out on 7.0

@rattrayalex rattrayalex changed the base branch from master to 7.0 March 16, 2017 17:39
@rattrayalex
Copy link
Copy Markdown
Contributor Author

Rebased and changed target

@danez danez merged commit 348cc5e into babel:7.0 Apr 4, 2017
@loganfsmyth
Copy link
Copy Markdown
Member

Looks like this is causing some test failures now that it is merged. Anyone know what's up? Did we land this too early since you said it depends on Babylon?

@danez
Copy link
Copy Markdown
Member

danez commented Apr 4, 2017

The tests are failing now because they are assuming new Babylon version. I wanted to create a new Babylon release for 7.0 but haven't gotten around. The change was bc so nothing really is broken.

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Oct 6, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Oct 6, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: generator PR: Bug Fix 🐛 A type of pull request used for our changelog categories

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants