From 33f945cfa28d55b148e23d2234c905bcaabfeac0 Mon Sep 17 00:00:00 2001 From: lustoykov Date: Fri, 11 Jan 2019 16:45:30 +0100 Subject: [PATCH 1/5] Enables jsx plugin in case jsx syntax is used in js files --- .../src/transforms/babel/jsx.js | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/core/parcel-bundler/src/transforms/babel/jsx.js b/packages/core/parcel-bundler/src/transforms/babel/jsx.js index de4ceb70210..9863cb9a38d 100644 --- a/packages/core/parcel-bundler/src/transforms/babel/jsx.js +++ b/packages/core/parcel-bundler/src/transforms/babel/jsx.js @@ -12,6 +12,26 @@ const JSX_PRAGMA = { hyperapp: 'h' }; +/** + * Solves a use case where people use JSX in .js files + */ +function isUsingJSXinJS(asset) { + // matches import * as React from 'react' and alike + const es6Candidate = /from\s+[`"'](react|preact|nervjs|hyperapp)[`"']/; + // matches const React = require('react') and alike + const commonJSCandidate = /require\([`"'](react|preact|nervjs|hyperapp)[`"']\)/; + + if (asset.contents.match(es6Candidate)) { + return true; + } + + if (asset.contents.match(commonJSCandidate)) { + return true; + } + + return false; +} + /** * Generates a babel config for JSX. Attempts to detect react or react-like libraries * and changes the pragma accordingly. @@ -37,7 +57,11 @@ async function getJSXConfig(asset, isSourceModule) { } } - if (pragma || JSX_EXTENSIONS[path.extname(asset.name)]) { + if ( + pragma || + JSX_EXTENSIONS[path.extname(asset.name)] || + isUsingJSXinJS(asset) + ) { return { internal: true, babelVersion: 7, From acb4ced3a853d69ee1cd1e16acd56ef9264a35fa Mon Sep 17 00:00:00 2001 From: lustoykov Date: Sat, 12 Jan 2019 19:43:46 +0100 Subject: [PATCH 2/5] Consider pragma when enabling JSX in .js files --- .../src/transforms/babel/jsx.js | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/core/parcel-bundler/src/transforms/babel/jsx.js b/packages/core/parcel-bundler/src/transforms/babel/jsx.js index 9863cb9a38d..1da6dd89b6c 100644 --- a/packages/core/parcel-bundler/src/transforms/babel/jsx.js +++ b/packages/core/parcel-bundler/src/transforms/babel/jsx.js @@ -12,24 +12,24 @@ const JSX_PRAGMA = { hyperapp: 'h' }; +function createJSXRegexFor(dependency) { + // result looks like /from\s+[`"']react[`"']|require\([`"']react[`"']\)/ + return new RegExp( + `from\\s+[\`"']${dependency}[\`"']|require\\([\`"']${dependency}[\`"']\\)` + ); +} + /** - * Solves a use case where people use JSX in .js files + * Solves a use case where JSX is used in .js files or where + * package.json is empty yet and pragma can not be determined based + * on pkg.dependencies / pkg.devDependencies */ -function isUsingJSXinJS(asset) { - // matches import * as React from 'react' and alike - const es6Candidate = /from\s+[`"'](react|preact|nervjs|hyperapp)[`"']/; - // matches const React = require('react') and alike - const commonJSCandidate = /require\([`"'](react|preact|nervjs|hyperapp)[`"']\)/; - - if (asset.contents.match(es6Candidate)) { - return true; - } - - if (asset.contents.match(commonJSCandidate)) { - return true; +function maybeCreateFallbackPragma(asset) { + for (const dep in JSX_PRAGMA) { + if (asset.contents.match(createJSXRegexFor(dep))) { + return JSX_PRAGMA[dep]; + } } - - return false; } /** @@ -57,11 +57,11 @@ async function getJSXConfig(asset, isSourceModule) { } } - if ( - pragma || - JSX_EXTENSIONS[path.extname(asset.name)] || - isUsingJSXinJS(asset) - ) { + if (!pragma) { + pragma = maybeCreateFallbackPragma(asset); + } + + if (pragma || JSX_EXTENSIONS[path.extname(asset.name)]) { return { internal: true, babelVersion: 7, From caa2ebc743f0eb4aca057608c2d209aec948ef40 Mon Sep 17 00:00:00 2001 From: lustoykov Date: Sat, 12 Jan 2019 20:18:27 +0100 Subject: [PATCH 3/5] Add tests for JSX support in JS even if no dependencies are specified --- .../integration/jsx-hyperapp-no-dep/index.js | 3 + .../jsx-hyperapp-no-dep/package.json | 3 + .../integration/jsx-nervjs-no-dep/index.js | 3 + .../jsx-nervjs-no-dep/package.json | 3 + .../integration/jsx-preact-no-dep/index.js | 3 + .../jsx-preact-no-dep/package.json | 3 + .../integration/jsx-react-no-dep/index.js | 3 + .../integration/jsx-react-no-dep/package.json | 3 + .../core/integration-tests/test/javascript.js | 89 +++++++++++++++++++ 9 files changed, 113 insertions(+) create mode 100644 packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js create mode 100644 packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json create mode 100644 packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js create mode 100644 packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json create mode 100644 packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js create mode 100644 packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json create mode 100644 packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js create mode 100644 packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json diff --git a/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js new file mode 100644 index 00000000000..4a97bbe9739 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js @@ -0,0 +1,3 @@ +import * as Hyperapp from 'hyperapp' + +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js new file mode 100644 index 00000000000..9c8f2c81f29 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js @@ -0,0 +1,3 @@ +import * as Nerv from 'nervjs'; + +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js new file mode 100644 index 00000000000..9483f2ef3e4 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js @@ -0,0 +1,3 @@ +const Preact = require('preact'); + +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js new file mode 100644 index 00000000000..4f5a71615ed --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js @@ -0,0 +1,3 @@ +import * as React from 'react'; + +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/javascript.js b/packages/core/integration-tests/test/javascript.js index ba255be5792..a6e80ec574b 100644 --- a/packages/core/integration-tests/test/javascript.js +++ b/packages/core/integration-tests/test/javascript.js @@ -1343,6 +1343,28 @@ describe('javascript', function() { assert(file.includes('React.createElement("div"')); }); + it('should support compiling JSX in JS files with React dependency even if React is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-react-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-react-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + + assert(file.includes('React.createElement("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-react-no-dep/package.json', + originalPkg + ); + }); + it('should support compiling JSX in JS files with Preact dependency', async function() { await bundle(path.join(__dirname, '/integration/jsx-preact/index.js')); @@ -1353,6 +1375,28 @@ describe('javascript', function() { assert(file.includes('h("div"')); }); + it('should support compiling JSX in JS files with Preact dependency even if Preact is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-preact-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-preact-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + + assert(file.includes('h("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-preact-no-dep/package.json', + originalPkg + ); + }); + it('should support compiling JSX in JS files with Nerv dependency', async function() { await bundle(path.join(__dirname, '/integration/jsx-nervjs/index.js')); @@ -1363,6 +1407,28 @@ describe('javascript', function() { assert(file.includes('Nerv.createElement("div"')); }); + it('should support compiling JSX in JS files with Nerv dependency even if Nerv is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-nervjs-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-nervjs-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + + assert(file.includes('Nerv.createElement("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-nervjs-no-dep/package.json', + originalPkg + ); + }); + it('should support compiling JSX in JS files with Hyperapp dependency', async function() { await bundle(path.join(__dirname, '/integration/jsx-hyperapp/index.js')); @@ -1370,7 +1436,30 @@ describe('javascript', function() { path.join(__dirname, '/dist/index.js'), 'utf8' ); + + assert(file.includes('h("div"')); + }); + + it('should support compiling JSX in JS files with Hyperapp dependency even if Hyperapp is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-hyperapp-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-hyperapp-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + assert(file.includes('h("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-hyperapp-no-dep/package.json', + originalPkg + ); }); it('should support optional dependencies in try...catch blocks', async function() { From 213383a6a33d8db98a1fc739a52ba754e9bbc9a3 Mon Sep 17 00:00:00 2001 From: lustoykov Date: Sat, 12 Jan 2019 22:58:11 +0100 Subject: [PATCH 4/5] Make comment more clear --- packages/core/parcel-bundler/src/transforms/babel/jsx.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/parcel-bundler/src/transforms/babel/jsx.js b/packages/core/parcel-bundler/src/transforms/babel/jsx.js index 1da6dd89b6c..687572d9749 100644 --- a/packages/core/parcel-bundler/src/transforms/babel/jsx.js +++ b/packages/core/parcel-bundler/src/transforms/babel/jsx.js @@ -20,9 +20,9 @@ function createJSXRegexFor(dependency) { } /** - * Solves a use case where JSX is used in .js files or where - * package.json is empty yet and pragma can not be determined based - * on pkg.dependencies / pkg.devDependencies + * Solves a use case when JSX is used in .js files, but + * package.json is empty or missing yet and therefore pragma cannot + * be determined based on pkg.dependencies / pkg.devDependencies */ function maybeCreateFallbackPragma(asset) { for (const dep in JSX_PRAGMA) { From 22bc1d40dfeefe7c2493fb6f80baa6fe468d5a3c Mon Sep 17 00:00:00 2001 From: lustoykov Date: Thu, 17 Jan 2019 11:15:25 +0100 Subject: [PATCH 5/5] Cache regex creation --- .../core/parcel-bundler/src/transforms/babel/jsx.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/core/parcel-bundler/src/transforms/babel/jsx.js b/packages/core/parcel-bundler/src/transforms/babel/jsx.js index 687572d9749..48e37d1c45e 100644 --- a/packages/core/parcel-bundler/src/transforms/babel/jsx.js +++ b/packages/core/parcel-bundler/src/transforms/babel/jsx.js @@ -24,9 +24,17 @@ function createJSXRegexFor(dependency) { * package.json is empty or missing yet and therefore pragma cannot * be determined based on pkg.dependencies / pkg.devDependencies */ +const cacheJsxRegexFor = {}; function maybeCreateFallbackPragma(asset) { for (const dep in JSX_PRAGMA) { - if (asset.contents.match(createJSXRegexFor(dep))) { + let regex = cacheJsxRegexFor[dep]; + + if (!regex) { + regex = createJSXRegexFor(dep); + cacheJsxRegexFor[dep] = regex; + } + + if (asset.contents.match(regex)) { return JSX_PRAGMA[dep]; } }