From 6a5b414991339db1b892c4bf42cf6c745197816f Mon Sep 17 00:00:00 2001 From: Jason Quense Date: Tue, 14 Dec 2021 15:28:54 -0500 Subject: [PATCH] fix: react automatic runtime transform --- src/features/css-prop.ts | 38 ++++++++++++++++------- src/runtime/jsx.js | 12 ++++--- test/__file_snapshots__/integration-js.js | 11 +++++-- test/__file_snapshots__/issue-365-js.js | 11 +++++-- test/css-prop.test.js | 4 ++- 5 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/features/css-prop.ts b/src/features/css-prop.ts index 1eb31c60..50cbb36a 100644 --- a/src/features/css-prop.ts +++ b/src/features/css-prop.ts @@ -212,12 +212,9 @@ export default { CallExpression(path: NodePath, state: CssPropPluginState) { const { file } = state; const pluginOptions = state.defaultedOptions; + const isAutomaticRuntime = isJsxCallExpression(path); - if ( - !path[IS_JSX] && - !isCreateElementCall(path) && - !isJsxCallExpression(path) - ) + if (!path[IS_JSX] && !isCreateElementCall(path) && !isAutomaticRuntime) return; const typeName = getNameFromPath(path.get('arguments')[0]); @@ -244,14 +241,31 @@ export default { const { changeset } = file.get(STYLES); const callee = path.get('callee'); - changeset.push({ - type: 'create-element', - code: jsx.name, - start: callee.node.start, - end: callee.node.end, - }); + if (isAutomaticRuntime) { + const end = path.get('arguments')[0]!.node!.start!; + + const calleeName = (callee.node as any).name; + changeset.push({ + type: 'create-element', + code: `${jsx.name}.jsx2(${calleeName}, `, + start: callee.node.start, + end, + }); + + path.unshiftContainer('arguments', t.identifier(calleeName)); + callee.replaceWith( + t.memberExpression(t.identifier(jsx.name), t.identifier('jsx2')), + ); + } else { + changeset.push({ + type: 'create-element', + code: jsx.name, + start: callee.node.start, + end: callee.node.end, + }); + callee.replaceWith(t.identifier(jsx.name)); + } - callee.replaceWith(t.identifier(jsx.name)); file.set(HAS_CREATE_ELEMENT, true); } }, diff --git a/src/runtime/jsx.js b/src/runtime/jsx.js index 7ecc31b4..3dc79918 100644 --- a/src/runtime/jsx.js +++ b/src/runtime/jsx.js @@ -14,7 +14,7 @@ export function varsToStyles(props, vars) { return style; } -function jsx(type, props, ...children) { +function jsx2(fn, type, props, ...args) { if (props && props.css) { const { css, className, ...childProps } = props; const componentClassName = css[0].cls2 || css[0].cls1; @@ -24,14 +24,18 @@ function jsx(type, props, ...children) { } ${resolveVariants(css[2])}`; props = childProps; } - - return createElement(type, props, ...children); + return fn(type, props, ...args); } +function jsx(type, props, ...children) { + return jsx2(createElement, type, props, ...children); +} + jsx.F = Fragment; +jsx.jsx2 = jsx2; // the reason for the crazy exports here is that you need to do a BUNCH of work // to keep typescript from eliding (removing) the jsx imports // see: https://github.com/babel/babel/pull/11523 -export { jsx, Fragment as F }; +export { jsx2, jsx, Fragment as F }; export default jsx; diff --git a/test/__file_snapshots__/integration-js.js b/test/__file_snapshots__/integration-js.js index 7b1697b7..eb7ea24b 100644 --- a/test/__file_snapshots__/integration-js.js +++ b/test/__file_snapshots__/integration-js.js @@ -304,6 +304,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "resolveVariants": () => (/* binding */ resolveVariants), /* harmony export */ "varsToStyles": () => (/* binding */ varsToStyles), +/* harmony export */ "jsx2": () => (/* binding */ jsx2), /* harmony export */ "jsx": () => (/* binding */ jsx), /* harmony export */ "F": () => (/* reexport safe */ react__WEBPACK_IMPORTED_MODULE_0__.Fragment), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) @@ -325,7 +326,7 @@ function varsToStyles(props, vars) { return style; } -function jsx(type, props, ...children) { +function jsx2(fn, type, props, ...args) { if (props && props.css) { const { css, className, ...childProps } = props; const componentClassName = css[0].cls2 || css[0].cls1; @@ -335,10 +336,14 @@ function jsx(type, props, ...children) { } ${resolveVariants(css[2])}`; props = childProps; } - - return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(type, props, ...children); + return fn(type, props, ...args); } +function jsx(type, props, ...children) { + return jsx2(react__WEBPACK_IMPORTED_MODULE_0__.createElement, type, props, ...children); +} + jsx.F = react__WEBPACK_IMPORTED_MODULE_0__.Fragment; +jsx.jsx2 = jsx2; // the reason for the crazy exports here is that you need to do a BUNCH of work // to keep typescript from eliding (removing) the jsx imports diff --git a/test/__file_snapshots__/issue-365-js.js b/test/__file_snapshots__/issue-365-js.js index bba3c61c..95bfced9 100644 --- a/test/__file_snapshots__/issue-365-js.js +++ b/test/__file_snapshots__/issue-365-js.js @@ -93,6 +93,7 @@ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "resolveVariants": () => (/* binding */ resolveVariants), /* harmony export */ "varsToStyles": () => (/* binding */ varsToStyles), +/* harmony export */ "jsx2": () => (/* binding */ jsx2), /* harmony export */ "jsx": () => (/* binding */ jsx), /* harmony export */ "F": () => (/* reexport safe */ react__WEBPACK_IMPORTED_MODULE_0__.Fragment), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) @@ -114,7 +115,7 @@ function varsToStyles(props, vars) { return style; } -function jsx(type, props, ...children) { +function jsx2(fn, type, props, ...args) { if (props && props.css) { const { css, className, ...childProps } = props; const componentClassName = css[0].cls2 || css[0].cls1; @@ -124,10 +125,14 @@ function jsx(type, props, ...children) { } ${resolveVariants(css[2])}`; props = childProps; } - - return (0,react__WEBPACK_IMPORTED_MODULE_0__.createElement)(type, props, ...children); + return fn(type, props, ...args); } +function jsx(type, props, ...children) { + return jsx2(react__WEBPACK_IMPORTED_MODULE_0__.createElement, type, props, ...children); +} + jsx.F = react__WEBPACK_IMPORTED_MODULE_0__.Fragment; +jsx.jsx2 = jsx2; // the reason for the crazy exports here is that you need to do a BUNCH of work // to keep typescript from eliding (removing) the jsx imports diff --git a/test/css-prop.test.js b/test/css-prop.test.js index 519c5040..457987b9 100644 --- a/test/css-prop.test.js +++ b/test/css-prop.test.js @@ -148,7 +148,9 @@ describe('css prop', () => { expect(code).not.toContain('/** @jsxFrag'); expect(code).toMatch('import _j from "astroturf/jsx";'); - expect(code).toMatch('_j('); + expect(code).toMatch('_j.jsx2('); + expect(code).toMatch('_jsx'); + expect(code).toMatch('_jsxs'); expect(styles).toHaveLength(2); expect(styles[0].identifier).toEqual('CssProp1_div'); },