From d2fe87892de8bdfa733f4730c1ea79dd4998e84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 28 Apr 2015 15:14:42 -0700 Subject: [PATCH] Remove transforms from repo, react-tools Time to just use jstransform. --- main.js | 103 +---- package.json | 7 +- vendor/browser-transforms.js | 57 ++- vendor/fbtransform/.eslintrc | 9 - vendor/fbtransform/syntax.js | 94 ----- .../transforms/__tests__/jsx-test.js | 142 ------- .../__tests__/react-displayName-test.js | 174 -------- .../transforms/__tests__/react-test.js | 396 ------------------ vendor/fbtransform/transforms/jsx.js | 138 ------ vendor/fbtransform/transforms/react.js | 241 ----------- .../transforms/reactDisplayName.js | 126 ------ vendor/fbtransform/visitors.js | 125 ------ vendor/inline-source-map.js | 27 -- 13 files changed, 52 insertions(+), 1587 deletions(-) delete mode 100644 vendor/fbtransform/.eslintrc delete mode 100644 vendor/fbtransform/syntax.js delete mode 100644 vendor/fbtransform/transforms/__tests__/jsx-test.js delete mode 100644 vendor/fbtransform/transforms/__tests__/react-displayName-test.js delete mode 100644 vendor/fbtransform/transforms/__tests__/react-test.js delete mode 100644 vendor/fbtransform/transforms/jsx.js delete mode 100644 vendor/fbtransform/transforms/react.js delete mode 100644 vendor/fbtransform/transforms/reactDisplayName.js delete mode 100644 vendor/fbtransform/visitors.js delete mode 100644 vendor/inline-source-map.js diff --git a/main.js b/main.js index f15d44244c..cd0c4270f7 100644 --- a/main.js +++ b/main.js @@ -8,88 +8,31 @@ */ 'use strict'; -/*eslint-disable no-undef*/ -var visitors = require('./vendor/fbtransform/visitors'); -var transform = require('jstransform').transform; -var typesSyntax = require('jstransform/visitors/type-syntax'); -var inlineSourceMap = require('./vendor/inline-source-map'); + +var jstransform = require('jstransform/simple'); + +function transformWithDetails(code, opts) { + opts = opts || {}; + + // Copy out the values we need and make sure they are compatible with + // jstransform options. Always set react:true. + var options = { + react: true, + harmony: opts.harmony, + stripTypes: opts.stripTypes, + sourceMapInline: opts.sourceMap, + sourceFilename: opts.sourceFilename, + es6module: opts.es6module, + nonStrictEs6module: opts.nonStrictEs6module, + target: opts.target + }; + + return jstransform.transform(code, options); +} module.exports = { transform: function(input, options) { - options = processOptions(options); - var output = innerTransform(input, options); - var result = output.code; - if (options.sourceMap) { - var map = inlineSourceMap( - output.sourceMap, - input, - options.filename - ); - result += '\n' + map; - } - return result; + return transformWithDetails(input, options).code; }, - transformWithDetails: function(input, options) { - options = processOptions(options); - var output = innerTransform(input, options); - var result = {}; - result.code = output.code; - if (options.sourceMap) { - result.sourceMap = output.sourceMap.toJSON(); - } - if (options.filename) { - result.sourceMap.sources = [options.filename]; - } - return result; - } + transformWithDetails: transformWithDetails }; - -/** - * Only copy the values that we need. We'll do some preprocessing to account for - * converting command line flags to options that jstransform can actually use. - */ -function processOptions(opts) { - opts = opts || {}; - var options = {}; - - options.harmony = opts.harmony; - options.stripTypes = opts.stripTypes; - options.sourceMap = opts.sourceMap; - options.filename = opts.sourceFilename; - - if (opts.es6module) { - options.sourceType = 'module'; - } - if (opts.nonStrictEs6module) { - options.sourceType = 'nonStrictModule'; - } - - // Instead of doing any fancy validation, only look for 'es3'. If we have - // that, then use it. Otherwise use 'es5'. - options.es3 = opts.target === 'es3'; - options.es5 = !options.es3; - - return options; -} - -function innerTransform(input, options) { - var visitorSets = ['react']; - if (options.harmony) { - visitorSets.push('harmony'); - } - - if (options.es3) { - visitorSets.push('es3'); - } - - if (options.stripTypes) { - // Stripping types needs to happen before the other transforms - // unfortunately, due to bad interactions. For example, - // es6-rest-param-visitors conflict with stripping rest param type - // annotation - input = transform(typesSyntax.visitorList, input, options).code; - } - - var visitorList = visitors.getVisitorsBySet(visitorSets); - return transform(visitorList, input, options); -} diff --git a/package.json b/package.json index 1e43bf3d53..77509c10af 100644 --- a/package.json +++ b/package.json @@ -14,9 +14,7 @@ "files": [ "main.js", "bin/jsx", - "src/", - "vendor/fbtransform/", - "vendor/inline-source-map.js" + "src/" ], "main": "main.js", "bin": { @@ -28,7 +26,8 @@ }, "dependencies": { "commoner": "^0.10.0", - "jstransform": "^10.1.0" + "esprima-fb": "^15001.1.0-dev-harmony-fb", + "jstransform": "^11.0.0" }, "devDependencies": { "babel-core": "^5.2.7", diff --git a/vendor/browser-transforms.js b/vendor/browser-transforms.js index 9cedfd8377..5a2b5b141c 100644 --- a/vendor/browser-transforms.js +++ b/vendor/browser-transforms.js @@ -13,8 +13,7 @@ 'use strict'; -var ReactTools = require('../main'); -var inlineSourceMap = require('./inline-source-map'); +var jstransform = require('jstransform/simple'); var headEl; var dummyAnchor; @@ -36,6 +35,9 @@ var supportsAccessors = Object.prototype.hasOwnProperty('__defineGetter__'); function transformReact(source, options) { options = options || {}; + // Always enable the React transforms. + options.react = true; + // Force the sourcemaps option manually. We don't want to use it if it will // break (see above note about supportsAccessors). We'll only override the // value here if sourceMap was specified and is truthy. This guarantees that @@ -45,7 +47,7 @@ function transformReact(source, options) { } // Otherwise just pass all options straight through to react-tools. - return ReactTools.transformWithDetails(source, options); + return jstransform.transform(source, options); } /** @@ -119,7 +121,7 @@ function createSourceCodeErrorMessage(code, e) { */ function transformCode(code, url, options) { try { - var transformed = transformReact(code, options); + return transformReact(code, options).code; } catch(e) { e.message += '\n at '; if (url) { @@ -136,32 +138,6 @@ function transformCode(code, url, options) { e.message += createSourceCodeErrorMessage(code, e); throw e; } - - if (!transformed.sourceMap) { - return transformed.code; - } - - var source; - if (url == null) { - source = 'Inline JSX script'; - inlineScriptCount++; - if (inlineScriptCount > 1) { - source += ' (' + inlineScriptCount + ')'; - } - } else if (dummyAnchor) { - // Firefox has problems when the sourcemap source is a proper URL with a - // protocol and hostname, so use the pathname. We could use just the - // filename, but hopefully using the full path will prevent potential - // issues where the same filename exists in multiple directories. - dummyAnchor.href = url; - source = dummyAnchor.pathname.substr(1); - } - - return ( - transformed.code + - '\n' + - inlineSourceMap(transformed.sourceMap, code, source) - ); } @@ -239,8 +215,27 @@ function loadScripts(scripts) { } scripts.forEach(function(script, i) { + // Determine the filename to use for the sourcemap. + var sourceFilename; + if (script.src == null) { + sourceFilename = 'Inline JSX script'; + inlineScriptCount++; + if (inlineScriptCount > 1) { + sourceFilename += ' (' + inlineScriptCount + ')'; + } + } else if (dummyAnchor) { + // Firefox has problems when the sourcemap sourceFilename is a proper URL + // with a protocol and hostname, so use the pathname. We could use just + // the filename, but hopefully using the full path will prevent potential + // issues where the same filename exists in multiple directories. + dummyAnchor.href = script.src; + sourceFilename = dummyAnchor.pathname.substr(1); + } + console.log(sourceFilename); + var options = { - sourceMap: true + sourceMapInline: true, + sourceFilename: sourceFilename }; if (/;harmony=true(;|$)/.test(script.type)) { options.harmony = true; diff --git a/vendor/fbtransform/.eslintrc b/vendor/fbtransform/.eslintrc deleted file mode 100644 index 4f4e56f233..0000000000 --- a/vendor/fbtransform/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ ---- -globals: - describe: true - expect: true - it: true - jest: true - -rules: - no-process-exit: 0 diff --git a/vendor/fbtransform/syntax.js b/vendor/fbtransform/syntax.js deleted file mode 100644 index 6f04302b3b..0000000000 --- a/vendor/fbtransform/syntax.js +++ /dev/null @@ -1,94 +0,0 @@ -/*global process:false*/ -/*global module:true*/ -/*global exports:true*/ -"use strict"; - -var transform = require('jstransform').transform; -var typesSyntax = require('jstransform/visitors/type-syntax'); -var visitors = require('./visitors'); - -/** - * @typechecks - * @param {string} source - * @param {object?} options - * @param {array?} excludes - * @return {string} - */ -function transformAll(source, options, excludes) { - excludes = excludes || []; - - // Stripping types needs to happen before the other transforms - // unfortunately, due to bad interactions. For example, - // es6-rest-param-visitors conflict with stripping rest param type - // annotation - source = transform(typesSyntax.visitorList, source, options).code; - - // The typechecker transform must run in a second pass in order to operate on - // the entire source code -- so exclude it from the first pass - var visitorsList = visitors.getAllVisitors(excludes.concat('typechecker')); - source = transform(visitorsList, source, options); - if (excludes.indexOf('typechecks') == -1 && /@typechecks/.test(source.code)) { - source = transform( - visitors.transformVisitors.typechecker, - source.code, - options - ); - } - return source; -} - -function runCli(argv) { - var options = {}; - for (var optName in argv) { - if (optName === '_' || optName === '$0') { - continue; - } - options[optName] = optimist.argv[optName]; - } - - if (options.help) { - optimist.showHelp(); - process.exit(0); - } - - var excludes = options.excludes; - delete options.excludes; - - var source = ''; - process.stdin.resume(); - process.stdin.setEncoding('utf8'); - process.stdin.on('data', function(chunk) { - source += chunk; - }); - process.stdin.on('end', function() { - try { - source = transformAll(source, options, excludes); - } catch (e) { - console.error(e.stack); - process.exit(1); - } - process.stdout.write(source.code); - }); -} - -if (require.main === module) { - var optimist = require('optimist'); - - optimist = optimist - .usage('Usage: $0 [options]') - .default('exclude', []) - .boolean('help').alias('h', 'help') - .boolean('minify') - .describe( - 'minify', - 'Best-effort minification of the output source (when possible)' - ) - .describe( - 'exclude', - 'A list of transformNames to exclude' - ); - - runCli(optimist.argv); -} else { - exports.transformAll = transformAll; -} diff --git a/vendor/fbtransform/transforms/__tests__/jsx-test.js b/vendor/fbtransform/transforms/__tests__/jsx-test.js deleted file mode 100644 index 76d6da19f9..0000000000 --- a/vendor/fbtransform/transforms/__tests__/jsx-test.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @emails jeffmo@fb.com - */ - -'use strict'; - -require('mock-modules').autoMockOff(); - -describe('jsx', function() { - var jsx = require('../jsx'); - var utils = require('jstransform/src/utils'); - var esprima = require('esprima-fb'); - - function runWithLiteral(text, isLast) { - var source = '
' + text + '
'; - var ast = esprima.parse(source, { range: true }); - var state = utils.createState(source); - var literal = ast.body[0].expression.children[0]; - state.g.position = literal.range[0]; - jsx.renderJSXLiteral(literal, isLast, state); - return state; - } - - function runWithAttribute(inlineAttribute, isLast) { - var source = '
'; - var ast = esprima.parse(source, { range: true }); - var state = utils.createState(source); - var attribute = ast.body[0].expression.openingElement.attributes[0]; - state.g.position = attribute.value.range[0]; - jsx.renderJSXExpressionContainer( - function() {}, - attribute.value, - isLast, - [], - state - ); - return state; - } - - it('should render simple literal', function() { - var state = runWithLiteral('a', true); - expect(state.g.buffer).toEqual('"a"'); - }); - - - it('should render simple literal with single space before', function() { - var state = runWithLiteral(' a', true); - expect(state.g.buffer).toEqual('" a"'); - }); - - it('should render simple literal with single space before' + - ' from multiple spaces', function() { - var state = runWithLiteral(' \t a', true); - expect(state.g.buffer).toEqual('" a"'); - }); - - it('should render simple literal with single space after', function() { - var state = runWithLiteral('a ', true); - expect(state.g.buffer).toEqual('"a "'); - }); - - it('should render simple literal with single space after' + - ' from multiple spaces', function() { - var state = runWithLiteral('a \t \t ', true); - expect(state.g.buffer).toEqual('"a "'); - }); - - it('should render multiline literal as last', function() { - var state = runWithLiteral( - ' sdfsdfsdf\n' + - ' sdlkfjsdfljs\n' + - ' ', - true); - - expect(state.g.buffer).toEqual( - '" sdfsdfsdf" + \' \' +\n' + - ' "sdlkfjsdfljs"\n' + - ' '); - }); - - it('should render multiline literal as not last', function() { - var state = runWithLiteral( - ' sdfsdfsdf\n' + - ' sdlkfjsdfljs\n' + - ' ', - false); - - expect(state.g.buffer).toEqual( - '" sdfsdfsdf" + \' \' +\n' + - ' "sdlkfjsdfljs", \n' + - ' '); - }); - - it('should render attribute expressions', function() { - var state = runWithAttribute('attr={"foo"}', true); - expect(state.g.buffer).toEqual('"foo"'); - }); - - it('should render attribute expressions as not last', function() { - var state = runWithAttribute('attr={"foo"}', false); - expect(state.g.buffer).toEqual('"foo", '); - }); - - it('should render attribute expressions with spaces', function() { - var state = runWithAttribute('attr={ "foo"\n }', true); - expect(state.g.buffer).toEqual(' "foo"\n '); - }); - - it('should render attribute expressions with commas before trailing ' + - 'whitespace', function() { - var state = runWithAttribute('attr={\n"foo"\n }', false); - expect(state.g.buffer).toEqual('\n"foo", \n '); - }); - - it('should render empty child expressions with comments', function() { - var source = '
{/*comment*/}
'; - var ast = esprima.parse(source, {range: true}); - var child = ast.body[0].expression.children[0]; - var state = utils.createState(source, child); - state.g.position = child.range[0]; - jsx.renderJSXExpressionContainer(function() {}, child, true, [], state); - expect(state.g.buffer).toBe('/*comment*/'); - }); - - it('should not render commas after empty child expressions even if they\'re' + - 'not last', function() { - var source = '
{/*comment*/}
'; - var ast = esprima.parse(source, {range: true}); - var child = ast.body[0].expression.children[0]; - var state = utils.createState(source, child); - state.g.position = child.range[0]; - jsx.renderJSXExpressionContainer(function() {}, child, false, [], state); - expect(state.g.buffer).toBe('/*comment*/'); - }); -}); diff --git a/vendor/fbtransform/transforms/__tests__/react-displayName-test.js b/vendor/fbtransform/transforms/__tests__/react-displayName-test.js deleted file mode 100644 index 7a49b1466e..0000000000 --- a/vendor/fbtransform/transforms/__tests__/react-displayName-test.js +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @emails react-core - */ -'use strict'; - -require('mock-modules').autoMockOff(); - -var transformAll = require('../../syntax.js').transformAll; - -function transform(source) { - return transformAll(source, {}, ['sourcemeta']); -} - -describe('react displayName jsx', function() { - - it('should only inject displayName if missing', function() { - var code = [ - '"use strict";', - 'var Whateva = React.createClass({', - ' displayName: "Whateva",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - var result = [ - '"use strict";', - 'var Whateva = React.createClass({', - ' displayName: "Whateva",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should inject displayName in simple assignment', () => { - var code = [ - 'var Component = React.createClass({', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - var result = [ - 'var Component = React.createClass({displayName: "Component",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should inject displayName in simple assignment without var', () => { - var code = [ - 'var Component;', - 'Component = React.createClass({', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - var result = [ - 'var Component;', - 'Component = React.createClass({displayName: "Component",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should inject displayName in property assignment', () => { - var code = [ - 'ns.Component = React.createClass({', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - var result = [ - 'ns.Component = React.createClass({displayName: "ns.Component",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should inject displayName in chained property assignment', () => { - var code = [ - 'ns.ns1.Component = React.createClass({', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - var result = [ - 'ns.ns1.Component = React.createClass({displayName: "ns.ns1.Component",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - - it('should inject displayName in exports property assignment', () => { - var code = [ - 'exports.Component = React.createClass({', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - var result = [ - 'exports.Component = React.createClass({displayName: "Component",', - ' render: function() {', - ' return null;', - ' }', - '});' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should inject displayName in object declaration', () => { - var code = [ - 'exports = {', - ' Component: React.createClass({', - ' render: function() {', - ' return null;', - ' }', - ' })', - '};' - ].join('\n'); - - var result = [ - 'exports = {', - ' Component: React.createClass({displayName: "Component",', - ' render: function() {', - ' return null;', - ' }', - ' })', - '};' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - -}); diff --git a/vendor/fbtransform/transforms/__tests__/react-test.js b/vendor/fbtransform/transforms/__tests__/react-test.js deleted file mode 100644 index fbe1082f28..0000000000 --- a/vendor/fbtransform/transforms/__tests__/react-test.js +++ /dev/null @@ -1,396 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @emails react-core - */ - -/*jshint evil:true, unused:false*/ - -'use strict'; - -require('mock-modules').autoMockOff(); - -describe('react jsx', function() { - var transformAll = require('../../syntax.js').transformAll; - - var transform = function(code, options, excludes) { - return transformAll( - code, - options, - (excludes || []).concat(['sourcemeta']) - ); - }; - - // These are placeholder variables in scope that we can use to assert that a - // specific variable reference was passed, rather than an object clone of it. - var x = 123456; - var y = 789012; - var z = 345678; - - var expectObjectAssign = function(code) { - /*eslint-disable no-unused-vars, no-eval*/ - var Component = jest.genMockFunction(); - var Child = jest.genMockFunction(); - var objectAssignMock = jest.genMockFunction(); - React.__spread = objectAssignMock; - eval(transform(code).code); - return expect(objectAssignMock); - /*eslint-enable*/ - }; - - var React = { - createElement: jest.genMockFunction() - }; - - it('should convert simple tags', function() { - var code = 'var x =
;'; - var result = 'var x = React.createElement("div", null);'; - - expect(transform(code).code).toEqual(result); - }); - - it('should convert simple text', function() { - var code = 'var x =
text
;'; - var result = 'var x = React.createElement("div", null, "text");'; - - expect(transform(code).code).toEqual(result); - }); - - it('should have correct comma in nested children', function() { - var code = [ - 'var x =
', - '

', - ' {foo}
{bar}
', - '
', - '
;' - ].join('\n'); - var result = [ - 'var x = React.createElement("div", null, ', - ' React.createElement("div", null, ' + - 'React.createElement("br", null)), ', - ' React.createElement(Component, null, foo, ' + - 'React.createElement("br", null), bar), ', - ' React.createElement("br", null)', - ');' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should avoid wrapping in extra parens if not needed', function() { - // Try with a single composite child, wrapped in a div. - var code = [ - 'var x =
', - ' ', - '
;' - ].join('\n'); - var result = [ - 'var x = React.createElement("div", null, ', - ' React.createElement(Component, null)', - ');' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - - // Try with a single interpolated child, wrapped in a div. - code = [ - 'var x =
', - ' {this.props.children}', - '
;' - ].join('\n'); - result = [ - 'var x = React.createElement("div", null, ', - ' this.props.children', - ');' - ].join('\n'); - expect(transform(code).code).toEqual(result); - - // Try with a single interpolated child, wrapped in a composite. - code = [ - 'var x = ', - ' {this.props.children}', - ';' - ].join('\n'); - result = [ - 'var x = React.createElement(Composite, null, ', - ' this.props.children', - ');' - ].join('\n'); - expect(transform(code).code).toEqual(result); - - // Try with a single composite child, wrapped in a composite. - code = [ - 'var x = ', - ' ', - ';' - ].join('\n'); - result = [ - 'var x = React.createElement(Composite, null, ', - ' React.createElement(Composite2, null)', - ');' - ].join('\n'); - expect(transform(code).code).toEqual(result); - }); - - it('should insert commas after expressions before whitespace', function() { - var code = [ - 'var x =', - ' ', - '
;' - ].join('\n'); - var result = [ - 'var x =', - ' React.createElement("div", {', - ' attr1: ', - ' "foo" + "bar", ', - ' ', - ' attr2: ', - ' "foo" + "bar" +', - ' ', - ' "baz" + "bug", ', - ' ', - ' attr3: ', - ' "foo" + "bar" +', - ' "baz" + "bug", ', - ' // Extra line here.', - ' ', - ' attr4: "baz"}', - ' );' - ].join('\n'); - - expect(transform(code).code).toEqual(result); - }); - - it('should properly handle comments adjacent to children', function() { - var code = [ - 'var x = (', - '
', - ' {/* A comment at the beginning */}', - ' {/* A second comment at the beginning */}', - ' ', - ' {/* A nested comment */}', - ' ', - ' {/* A sandwiched comment */}', - '
', - ' {/* A comment at the end */}', - ' {/* A second comment at the end */}', - '
', - ');' - ].join('\n'); - var result = [ - 'var x = (', - ' React.createElement("div", null, ', - ' /* A comment at the beginning */', - ' /* A second comment at the beginning */', - ' React.createElement("span", null', - ' /* A nested comment */', - ' ), ', - ' /* A sandwiched comment */', - ' React.createElement("br", null)', - ' /* A comment at the end */', - ' /* A second comment at the end */', - ' )', - ');' - ].join('\n'); - - expect(transform(code).code).toBe(result); - }); - - it('should properly handle comments between props', function() { - var code = [ - 'var x = (', - ' ', - ' ', - ' ', - ');' - ].join('\n'); - var result = [ - 'var x = (', - ' React.createElement("div", {', - ' /* a multi-line', - ' comment */', - ' attr1: "foo"}, ', - ' React.createElement("span", {// a double-slash comment', - ' attr2: "bar"}', - ' )', - ' )', - ');' - ].join('\n'); - - expect(transform(code).code).toBe(result); - }); - - it('should not strip tags with a single child of  ', function() { - var code = [ - '
 
;' - ].join('\n'); - var result = [ - 'React.createElement("div", null, "\u00A0");' - ].join('\n'); - - expect(transform(code).code).toBe(result); - }); - - it('should not strip   even coupled with other whitespace', function() { - var code = [ - '
 
;' - ].join('\n'); - var result = [ - 'React.createElement("div", null, "\u00A0 ");' - ].join('\n'); - - expect(transform(code).code).toBe(result); - }); - - it('should handle hasOwnProperty correctly', function() { - var code = 'testing;'; - var result = 'React.createElement("hasOwnProperty", null, "testing");'; - expect(transform(code).code).toBe(result); - }); - - it('should allow constructor as prop', function() { - var code = ';'; - var result = 'React.createElement(Component, {constructor: "foo"});'; - - expect(transform(code).code).toBe(result); - }); - - it('should allow JS namespacing', function() { - var code = ';'; - var result = 'React.createElement(Namespace.Component, null);'; - - expect(transform(code).code).toBe(result); - }); - - it('should allow deeper JS namespacing', function() { - var code = ';'; - var result = - 'React.createElement(Namespace.DeepNamespace.Component, null);'; - - expect(transform(code).code).toBe(result); - }); - - it('should disallow XML namespacing', function() { - var code = ';'; - - expect(() => transform(code)).toThrow(); - }); - - it('wraps props in React.__spread for spread attributes', function() { - var code = - ''; - var result = - 'React.createElement(Component, React.__spread({}, x , {y: \n' + - '2, z: true}))'; - - expect(transform(code).code).toBe(result); - }); - - it('adds appropriate newlines when using spread attribute', function() { - var code = - ''; - var result = - 'React.createElement(Component, React.__spread({}, \n' + - ' this.props, \n' + - ' {sound: "moo"}))'; - - expect(transform(code).code).toBe(result); - }); - - it('handles overparenthesized JS', function() { - var code = - 'Foo {(e+f //A line comment\n' + - '/* A multiline comment */)\n' + - '} bar\n' + - ''; - var result = 'React.createElement("foo", {a: (b), c: (d)}, "Foo ", (e+f //A line comment\n' + - '/* A multiline comment */), \n' + - '" bar"\n' + - ')'; - expect(transform(code).code).toBe(result); - }); - - it('should transform known hyphenated tags', function() { - var code = ';'; - var result = 'React.createElement("font-face", null);'; - - expect(transform(code).code).toBe(result); - }); - - it('does not call React.__spread when there are no spreads', function() { - expectObjectAssign( - '' - ).not.toBeCalled(); - }); - - it('should not throw for unknown hyphenated tags', function() { - var code = ';'; - expect(function() { - transform(code); - }).not.toThrow(); - }); - - it('calls assign with a new target object for spreads', function() { - expectObjectAssign( - '' - ).toBeCalledWith({}, x); - }); - - it('calls assign with an empty object when the spread is first', function() { - expectObjectAssign( - '' - ).toBeCalledWith({}, x, {y: 2}); - }); - - it('coalesces consecutive properties into a single object', function() { - expectObjectAssign( - '' - ).toBeCalledWith({}, x, {y: 2, z: true}); - }); - - it('avoids an unnecessary empty object when spread is not first', function() { - expectObjectAssign( - '' - ).toBeCalledWith({x: 1}, y); - }); - - it('passes the same value multiple times to React.__spread', function() { - expectObjectAssign( - '' - ).toBeCalledWith({x: 1, y: '2'}, z, z); - }); - - it('evaluates sequences before passing them to React.__spread', function() { - expectObjectAssign( - 'Text' - ).toBeCalledWith({x: '1'}, {y: 2}, {z: 3}); - }); - -}); diff --git a/vendor/fbtransform/transforms/jsx.js b/vendor/fbtransform/transforms/jsx.js deleted file mode 100644 index b1a1037bbd..0000000000 --- a/vendor/fbtransform/transforms/jsx.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -/*global exports:true*/ -'use strict'; -var Syntax = require('jstransform').Syntax; -var utils = require('jstransform/src/utils'); - -function commaAfterLastParen(value) { - var state = 'normal'; - var commaPos = 0; - for (var i = 0; i < value.length; ++i) { - if (state === 'normal') { - if (value.substr(i, 2) === '//') { - state = 'singleline'; - i += 1; - } else if (value.substr(i, 2) === '/*') { - state = 'multiline'; - i += 1; - } else if (value.charAt(i).trim() !== '') { - commaPos = i + 1; - } - } else if (state === 'singleline' && value.charAt(i) === '\n') { - state = 'normal'; - } else if (state === 'multiline' && - value.charAt(i) === '*' && - i + 1 < value.length && - value.charAt(i + 1) === '/') { - i += 1; - state = 'normal'; - } - } - return value.substring(0, commaPos) + ', ' + trimLeft(value.substring(commaPos)); -} - -function renderJSXLiteral(object, isLast, state, start, end) { - var lines = object.value.split(/\r\n|\n|\r/); - - if (start) { - utils.append(start, state); - } - - var lastNonEmptyLine = 0; - - lines.forEach(function(line, index) { - if (line.match(/[^ \t]/)) { - lastNonEmptyLine = index; - } - }); - - lines.forEach(function(line, index) { - var isFirstLine = index === 0; - var isLastLine = index === lines.length - 1; - var isLastNonEmptyLine = index === lastNonEmptyLine; - - // replace rendered whitespace tabs with spaces - var trimmedLine = line.replace(/\t/g, ' '); - - // trim whitespace touching a newline - if (!isFirstLine) { - trimmedLine = trimmedLine.replace(/^[ ]+/, ''); - } - if (!isLastLine) { - trimmedLine = trimmedLine.replace(/[ ]+$/, ''); - } - - if (!isFirstLine) { - utils.append(line.match(/^[ \t]*/)[0], state); - } - - if (trimmedLine || isLastNonEmptyLine) { - utils.append( - JSON.stringify(trimmedLine) + - (!isLastNonEmptyLine ? ' + \' \' +' : ''), - state); - - if (isLastNonEmptyLine) { - if (end) { - utils.append(end, state); - } - if (!isLast) { - utils.append(', ', state); - } - } - - // only restore tail whitespace if line had literals - if (trimmedLine && !isLastLine) { - utils.append(line.match(/[ \t]*$/)[0], state); - } - } - - if (!isLastLine) { - utils.append('\n', state); - } - }); - - utils.move(object.range[1], state); -} - -function renderJSXExpressionContainer(traverse, object, isLast, path, state) { - // Plus 1 to skip `{`. - utils.move(object.range[0] + 1, state); - utils.catchup(object.expression.range[0], state); - traverse(object.expression, path, state); - - if (!isLast && object.expression.type !== Syntax.JSXEmptyExpression) { - // If we need to append a comma, make sure to do so after the expression. - utils.catchup(object.expression.range[1], state, trimLeft); - utils.catchup(object.range[1] - 1, state, commaAfterLastParen); - } else { - // Minus 1 to skip `}`. - utils.catchup(object.range[1] - 1, state, trimLeft); - } - utils.move(object.range[1], state); - return false; -} - -function quoteAttrName(attr) { - // Quote invalid JS identifiers. - if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { - return '"' + attr + '"'; - } - return attr; -} - -function trimLeft(value) { - return value.replace(/^[ ]+/, ''); -} - -exports.renderJSXExpressionContainer = renderJSXExpressionContainer; -exports.renderJSXLiteral = renderJSXLiteral; -exports.quoteAttrName = quoteAttrName; -exports.trimLeft = trimLeft; diff --git a/vendor/fbtransform/transforms/react.js b/vendor/fbtransform/transforms/react.js deleted file mode 100644 index 8e93f27879..0000000000 --- a/vendor/fbtransform/transforms/react.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -'use strict'; - -/*global exports:true*/ - -var Syntax = require('jstransform').Syntax; -var utils = require('jstransform/src/utils'); - -var renderJSXExpressionContainer = require('./jsx').renderJSXExpressionContainer; -var renderJSXLiteral = require('./jsx').renderJSXLiteral; -var quoteAttrName = require('./jsx').quoteAttrName; - -var trimLeft = require('./jsx').trimLeft; - -/** - * Customized desugar processor for React JSX. Currently: - * - * => React.createElement(X, null) - * => React.createElement(X, {prop: '1'}, null) - * => React.createElement(X, {prop:'2'}, - * React.createElement(Y, null) - * ) - *
=> React.createElement("div", null) - */ - -/** - * Removes all non-whitespace/parenthesis characters - */ -var reNonWhiteParen = /([^\s\(\)])/g; -function stripNonWhiteParen(value) { - return value.replace(reNonWhiteParen, ''); -} - -var tagConvention = /^[a-z]|\-/; -function isTagName(name) { - return tagConvention.test(name); -} - -function visitReactTag(traverse, object, path, state) { - var openingElement = object.openingElement; - var nameObject = openingElement.name; - var attributesObject = openingElement.attributes; - - utils.catchup(openingElement.range[0], state, trimLeft); - - if (nameObject.type === Syntax.JSXNamespacedName && nameObject.namespace) { - throw new Error('Namespace tags are not supported. ReactJSX is not XML.'); - } - - // We assume that the React runtime is already in scope - utils.append('React.createElement(', state); - - if (nameObject.type === Syntax.JSXIdentifier && isTagName(nameObject.name)) { - utils.append('"' + nameObject.name + '"', state); - utils.move(nameObject.range[1], state); - } else { - // Use utils.catchup in this case so we can easily handle - // JSXMemberExpressions which look like Foo.Bar.Baz. This also handles - // JSXIdentifiers that aren't fallback tags. - utils.move(nameObject.range[0], state); - utils.catchup(nameObject.range[1], state); - } - - utils.append(', ', state); - - var hasAttributes = attributesObject.length; - - var hasAtLeastOneSpreadProperty = attributesObject.some(function(attr) { - return attr.type === Syntax.JSXSpreadAttribute; - }); - - // if we don't have any attributes, pass in null - if (hasAtLeastOneSpreadProperty) { - utils.append('React.__spread({', state); - } else if (hasAttributes) { - utils.append('{', state); - } else { - utils.append('null', state); - } - - // keep track of if the previous attribute was a spread attribute - var previousWasSpread = false; - - // write attributes - attributesObject.forEach(function(attr, index) { - var isLast = index === attributesObject.length - 1; - - if (attr.type === Syntax.JSXSpreadAttribute) { - // Close the previous object or initial object - if (!previousWasSpread) { - utils.append('}, ', state); - } - - // Move to the expression start, ignoring everything except parenthesis - // and whitespace. - utils.catchup(attr.range[0], state, stripNonWhiteParen); - // Plus 1 to skip `{`. - utils.move(attr.range[0] + 1, state); - utils.catchup(attr.argument.range[0], state, stripNonWhiteParen); - - traverse(attr.argument, path, state); - - utils.catchup(attr.argument.range[1], state); - - // Move to the end, ignoring parenthesis and the closing `}` - utils.catchup(attr.range[1] - 1, state, stripNonWhiteParen); - - if (!isLast) { - utils.append(', ', state); - } - - utils.move(attr.range[1], state); - - previousWasSpread = true; - - return; - } - - // If the next attribute is a spread, we're effective last in this object - if (!isLast) { - isLast = attributesObject[index + 1].type === Syntax.JSXSpreadAttribute; - } - - if (attr.name.namespace) { - throw new Error( - 'Namespace attributes are not supported. ReactJSX is not XML.'); - } - var name = attr.name.name; - - utils.catchup(attr.range[0], state, trimLeft); - - if (previousWasSpread) { - utils.append('{', state); - } - - utils.append(quoteAttrName(name), state); - utils.append(': ', state); - - if (!attr.value) { - state.g.buffer += 'true'; - state.g.position = attr.name.range[1]; - if (!isLast) { - utils.append(', ', state); - } - } else { - utils.move(attr.name.range[1], state); - // Use catchupNewlines to skip over the '=' in the attribute - utils.catchupNewlines(attr.value.range[0], state); - if (attr.value.type === Syntax.Literal) { - renderJSXLiteral(attr.value, isLast, state); - } else { - renderJSXExpressionContainer(traverse, attr.value, isLast, path, state); - } - } - - utils.catchup(attr.range[1], state, trimLeft); - - previousWasSpread = false; - }); - - if (!openingElement.selfClosing) { - utils.catchup(openingElement.range[1] - 1, state, trimLeft); - utils.move(openingElement.range[1], state); - } - - if (hasAttributes && !previousWasSpread) { - utils.append('}', state); - } - - if (hasAtLeastOneSpreadProperty) { - utils.append(')', state); - } - - // filter out whitespace - var childrenToRender = object.children.filter(function(child) { - return !(child.type === Syntax.Literal - && typeof child.value === 'string' - && child.value.match(/^[ \t]*[\r\n][ \t\r\n]*$/)); - }); - if (childrenToRender.length > 0) { - var lastRenderableIndex; - - childrenToRender.forEach(function(child, index) { - if (child.type !== Syntax.JSXExpressionContainer || - child.expression.type !== Syntax.JSXEmptyExpression) { - lastRenderableIndex = index; - } - }); - - if (lastRenderableIndex !== undefined) { - utils.append(', ', state); - } - - childrenToRender.forEach(function(child, index) { - utils.catchup(child.range[0], state, trimLeft); - - var isLast = index >= lastRenderableIndex; - - if (child.type === Syntax.Literal) { - renderJSXLiteral(child, isLast, state); - } else if (child.type === Syntax.JSXExpressionContainer) { - renderJSXExpressionContainer(traverse, child, isLast, path, state); - } else { - traverse(child, path, state); - if (!isLast) { - utils.append(', ', state); - } - } - - utils.catchup(child.range[1], state, trimLeft); - }); - } - - if (openingElement.selfClosing) { - // everything up to /> - utils.catchup(openingElement.range[1] - 2, state, trimLeft); - utils.move(openingElement.range[1], state); - } else { - // everything up to - utils.catchup(object.closingElement.range[0], state, trimLeft); - utils.move(object.closingElement.range[1], state); - } - - utils.append(')', state); - return false; -} - -visitReactTag.test = function(object, path, state) { - return object.type === Syntax.JSXElement; -}; - -exports.visitorList = [ - visitReactTag -]; diff --git a/vendor/fbtransform/transforms/reactDisplayName.js b/vendor/fbtransform/transforms/reactDisplayName.js deleted file mode 100644 index 5621c5c944..0000000000 --- a/vendor/fbtransform/transforms/reactDisplayName.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ -/*global exports:true*/ -'use strict'; - -var Syntax = require('jstransform').Syntax; -var utils = require('jstransform/src/utils'); - -function shouldAddDisplayName(object) { - if (object && - object.type === Syntax.CallExpression && - object.callee.type === Syntax.MemberExpression && - object.callee.object.type === Syntax.Identifier && - object.callee.object.name === 'React' && - object.callee.property.type === Syntax.Identifier && - object.callee.property.name === 'createClass' && - object.arguments.length === 1 && - object.arguments[0].type === Syntax.ObjectExpression) { - // Verify that the displayName property isn't already set - var properties = object.arguments[0].properties; - var safe = properties.every(function(property) { - var value = property.key.type === Syntax.Identifier ? - property.key.name : - property.key.value; - return value !== 'displayName'; - }); - return safe; - } - return false; -} - -/** - * If `expr` is an Identifier or MemberExpression node made of identifiers and - * dot accesses, return a list of the identifier parts. Other nodes return null. - * - * Examples: - * - * MyComponent -> ['MyComponent'] - * namespace.MyComponent -> ['namespace', 'MyComponent'] - * namespace['foo'] -> null - * namespace['foo'].bar -> ['bar'] - */ -function flattenIdentifierOrMemberExpression(expr) { - if (expr.type === Syntax.Identifier) { - return [expr.name]; - } else if (expr.type === Syntax.MemberExpression) { - if (!expr.computed && expr.property.type === Syntax.Identifier) { - var flattenedObject = flattenIdentifierOrMemberExpression(expr.object); - if (flattenedObject) { - flattenedObject.push(expr.property.name); - return flattenedObject; - } else { - return [expr.property.name]; - } - } - } - return null; -} - -/** - * Transforms the following: - * - * var MyComponent = React.createClass({ - * render: ... - * }); - * - * into: - * - * var MyComponent = React.createClass({ - * displayName: 'MyComponent', - * render: ... - * }); - * - * Also catches: - * - * MyComponent = React.createClass(...); - * namespace.MyComponent = React.createClass(...); - * exports.MyComponent = React.createClass(...); - * module.exports = {MyComponent: React.createClass(...)}; - */ -function visitReactDisplayName(traverse, object, path, state) { - var left, right; - - if (object.type === Syntax.AssignmentExpression) { - left = object.left; - right = object.right; - } else if (object.type === Syntax.Property) { - left = object.key; - right = object.value; - } else if (object.type === Syntax.VariableDeclarator) { - left = object.id; - right = object.init; - } - - if (right && shouldAddDisplayName(right)) { - var displayNamePath = flattenIdentifierOrMemberExpression(left); - if (displayNamePath) { - if (displayNamePath.length > 1 && displayNamePath[0] === 'exports') { - displayNamePath.shift(); - } - - var displayName = displayNamePath.join('.'); - - utils.catchup(right.arguments[0].range[0] + 1, state); - utils.append('displayName: "' + displayName + '",', state); - } - } -} - -visitReactDisplayName.test = function(object, path, state) { - return ( - object.type === Syntax.AssignmentExpression || - object.type === Syntax.Property || - object.type === Syntax.VariableDeclarator - ); -}; - -exports.visitorList = [ - visitReactDisplayName -]; diff --git a/vendor/fbtransform/visitors.js b/vendor/fbtransform/visitors.js deleted file mode 100644 index a07ab4ab3f..0000000000 --- a/vendor/fbtransform/visitors.js +++ /dev/null @@ -1,125 +0,0 @@ -/*global exports:true*/ - -'use strict'; - -var es6ArrowFunctions = - require('jstransform/visitors/es6-arrow-function-visitors'); -var es6Classes = require('jstransform/visitors/es6-class-visitors'); -var es6Destructuring = - require('jstransform/visitors/es6-destructuring-visitors'); -var es6ObjectConciseMethod = - require('jstransform/visitors/es6-object-concise-method-visitors'); -var es6ObjectShortNotation = - require('jstransform/visitors/es6-object-short-notation-visitors'); -var es6RestParameters = require('jstransform/visitors/es6-rest-param-visitors'); -var es6Templates = require('jstransform/visitors/es6-template-visitors'); -var es6CallSpread = - require('jstransform/visitors/es6-call-spread-visitors'); -var es7SpreadProperty = - require('jstransform/visitors/es7-spread-property-visitors'); -var react = require('./transforms/react'); -var reactDisplayName = require('./transforms/reactDisplayName'); -var reservedWords = require('jstransform/visitors/reserved-words-visitors'); - -/** - * Map from transformName => orderedListOfVisitors. - */ -var transformVisitors = { - 'es6-arrow-functions': es6ArrowFunctions.visitorList, - 'es6-classes': es6Classes.visitorList, - 'es6-destructuring': es6Destructuring.visitorList, - 'es6-object-concise-method': es6ObjectConciseMethod.visitorList, - 'es6-object-short-notation': es6ObjectShortNotation.visitorList, - 'es6-rest-params': es6RestParameters.visitorList, - 'es6-templates': es6Templates.visitorList, - 'es6-call-spread': es6CallSpread.visitorList, - 'es7-spread-property': es7SpreadProperty.visitorList, - 'react': react.visitorList.concat(reactDisplayName.visitorList), - 'reserved-words': reservedWords.visitorList -}; - -var transformSets = { - 'harmony': [ - 'es6-arrow-functions', - 'es6-object-concise-method', - 'es6-object-short-notation', - 'es6-classes', - 'es6-rest-params', - 'es6-templates', - 'es6-destructuring', - 'es6-call-spread', - 'es7-spread-property' - ], - 'es3': [ - 'reserved-words' - ], - 'react': [ - 'react' - ] -}; - -/** - * Specifies the order in which each transform should run. - */ -var transformRunOrder = [ - 'reserved-words', - 'es6-arrow-functions', - 'es6-object-concise-method', - 'es6-object-short-notation', - 'es6-classes', - 'es6-rest-params', - 'es6-templates', - 'es6-destructuring', - 'es6-call-spread', - 'es7-spread-property', - 'react' -]; - -/** - * Given a list of transform names, return the ordered list of visitors to be - * passed to the transform() function. - * - * @param {array?} excludes - * @return {array} - */ -function getAllVisitors(excludes) { - var ret = []; - for (var i = 0, il = transformRunOrder.length; i < il; i++) { - if (!excludes || excludes.indexOf(transformRunOrder[i]) === -1) { - ret = ret.concat(transformVisitors[transformRunOrder[i]]); - } - } - return ret; -} - -/** - * Given a list of visitor set names, return the ordered list of visitors to be - * passed to jstransform. - * - * @param {array} - * @return {array} - */ -function getVisitorsBySet(sets) { - var visitorsToInclude = sets.reduce(function(visitors, set) { - if (!transformSets.hasOwnProperty(set)) { - throw new Error('Unknown visitor set: ' + set); - } - transformSets[set].forEach(function(visitor) { - visitors[visitor] = true; - }); - return visitors; - }, {}); - - var visitorList = []; - for (var i = 0; i < transformRunOrder.length; i++) { - if (visitorsToInclude.hasOwnProperty(transformRunOrder[i])) { - visitorList = visitorList.concat(transformVisitors[transformRunOrder[i]]); - } - } - - return visitorList; -} - -exports.getVisitorsBySet = getVisitorsBySet; -exports.getAllVisitors = getAllVisitors; -exports.transformVisitors = transformVisitors; diff --git a/vendor/inline-source-map.js b/vendor/inline-source-map.js deleted file mode 100644 index 7d0219e2cc..0000000000 --- a/vendor/inline-source-map.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright 2013-2015, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -'use strict'; -/*eslint-disable no-undef*/ -var Buffer = require('buffer').Buffer; - -function inlineSourceMap(sourceMap, sourceCode, sourceFilename) { - // This can be used with a sourcemap that has already has toJSON called on it. - // Check first. - var json = sourceMap; - if (typeof sourceMap.toJSON === 'function') { - json = sourceMap.toJSON(); - } - json.sources = [sourceFilename]; - json.sourcesContent = [sourceCode]; - var base64 = Buffer(JSON.stringify(json)).toString('base64'); - return '//# sourceMappingURL=data:application/json;base64,' + base64; -} - -module.exports = inlineSourceMap;