diff --git a/vendor/fbtransform/transforms/__tests__/react-test.js b/vendor/fbtransform/transforms/__tests__/react-test.js index 546db630d7898..b8d1d362f2f60 100644 --- a/vendor/fbtransform/transforms/__tests__/react-test.js +++ b/vendor/fbtransform/transforms/__tests__/react-test.js @@ -21,6 +21,12 @@ require('mock-modules').autoMockOff(); describe('react jsx', function() { var transformAll = require('../../syntax.js').transformAll; + var xjs = require('../xjs.js'); + + // Add to list of known tags to ensure that when we test support + // for hyphentated known tags, it's there. + // TODO: remove this when/if is supported out of the box. + xjs.knownTags['font-face'] = true; var transform = function(code, options, excludes) { return transformAll( @@ -346,6 +352,23 @@ describe('react jsx', function() { expect(transform(code).code).toBe(result); }); + it('should allow deeper JS namespacing', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + ';' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'Namespace.DeepNamespace.Component(null);' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + it('should disallow XML namespacing', function() { var code = [ '/**', @@ -357,4 +380,33 @@ describe('react jsx', function() { expect(() => transform(code)).toThrow(); }); + it('should transform known hyphenated tags', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + ';' + ].join('\n'); + var result = [ + '/**', + ' * @jsx React.DOM', + ' */', + 'React.DOM[\'font-face\'](null);' + ].join('\n'); + + expect(transform(code).code).toBe(result); + }); + + it('should throw for unknown hyphenated tags', function() { + var code = [ + '/**', + ' * @jsx React.DOM', + ' */', + ';' + ].join('\n'); + + expect(() => transform(code)).toThrow(); + }); + }); + diff --git a/vendor/fbtransform/transforms/react.js b/vendor/fbtransform/transforms/react.js index c79eaa85f5648..78ba671dd04ba 100644 --- a/vendor/fbtransform/transforms/react.js +++ b/vendor/fbtransform/transforms/react.js @@ -61,15 +61,42 @@ function visitReactTag(traverse, object, path, state) { throw new Error('Namespace tags are not supported. ReactJSX is not XML.'); } - // Only identifiers can be fallback tags. XJSMemberExpressions are not. - var isFallbackTag = - nameObject.type === Syntax.XJSIdentifier && - FALLBACK_TAGS.hasOwnProperty(nameObject.name); + // Only identifiers can be fallback tags or need quoting. We don't need to + // handle quoting for other types. + var didAddTag = false; - utils.append(isFallbackTag ? jsxObjIdent + '.' : '', state); + // Only identifiers can be fallback tags. XJSMemberExpressions are not. + if (nameObject.type === Syntax.XJSIdentifier) { + var tagName = nameObject.name; + var quotedTagName = quoteAttrName(tagName); + + if (FALLBACK_TAGS.hasOwnProperty(tagName)) { + // "Properly" handle invalid identifiers, like , which needs to + // be enclosed in quotes. + var predicate = + tagName === quotedTagName ? + ('.' + tagName) : + ('[' + quotedTagName + ']'); + utils.append(jsxObjIdent + predicate, state); + utils.move(nameObject.range[1], state); + didAddTag = true; + } else if (tagName !== quotedTagName) { + // If we're in the case where we need to quote and but don't recognize the + // tag, throw. + throw new Error( + 'Tags must be valid JS identifiers or a recognized special case. `<' + + tagName + '>` is not one of them.' + ); + } + } - utils.move(nameObject.range[0], state); - utils.catchup(nameObject.range[1], state); + // Use utils.catchup in this case so we can easily handle XJSMemberExpressions + // which look like Foo.Bar.Baz. This also handles unhyphenated XJSIdentifiers + // that aren't fallback tags. + if (!didAddTag) { + utils.move(nameObject.range[0], state); + utils.catchup(nameObject.range[1], state); + } utils.append('(', state); @@ -193,3 +220,4 @@ visitReactTag.test = function(object, path, state) { exports.visitorList = [ visitReactTag ]; + diff --git a/vendor/fbtransform/transforms/xjs.js b/vendor/fbtransform/transforms/xjs.js index 66a8fb13cb247..4636631fa0473 100644 --- a/vendor/fbtransform/transforms/xjs.js +++ b/vendor/fbtransform/transforms/xjs.js @@ -19,6 +19,7 @@ var Syntax = require('esprima-fb').Syntax; var utils = require('jstransform/src/utils'); var knownTags = { + 'font-face': true, a: true, abbr: true, address: true,