From 8a563128a346a637dfe6bc83df55f069947d2337 Mon Sep 17 00:00:00 2001 From: Remco Haszing Date: Tue, 18 Jul 2023 17:51:11 +0200 Subject: [PATCH] Refactor output to use spread, not `Object.assign` Closes GH-2328. Reviewed-by: Christian Murphy Reviewed-by: Titus Wormer --- docs/docs/using-mdx.server.mdx | 5 +- packages/mdx/lib/plugin/recma-jsx-rewrite.js | 23 +++---- packages/mdx/readme.md | 22 +++++-- packages/mdx/test/compile.js | 64 ++++++++++++++++---- packages/rollup/test/index.js | 2 +- 5 files changed, 82 insertions(+), 34 deletions(-) diff --git a/docs/docs/using-mdx.server.mdx b/docs/docs/using-mdx.server.mdx index 2488dd6e7..4153751c6 100644 --- a/docs/docs/using-mdx.server.mdx +++ b/docs/docs/using-mdx.server.mdx @@ -65,7 +65,10 @@ import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runti export const Thing = () => _jsx(_Fragment, {children: 'World'}) function _createMdxContent(props) { - const _components = Object.assign({h1: 'h1'}, props.components) + const _components = { + h1: 'h1', + ...props.components + } return _jsxs(_components.h1, { children: ['Hello ', _jsx(Thing, {})] }) diff --git a/packages/mdx/lib/plugin/recma-jsx-rewrite.js b/packages/mdx/lib/plugin/recma-jsx-rewrite.js index 4bc1dca98..abbc8bd6c 100644 --- a/packages/mdx/lib/plugin/recma-jsx-rewrite.js +++ b/packages/mdx/lib/plugin/recma-jsx-rewrite.js @@ -9,6 +9,7 @@ * @typedef {import('estree-jsx').ObjectPattern} ObjectPattern * @typedef {import('estree-jsx').Program} Program * @typedef {import('estree-jsx').Property} Property + * @typedef {import('estree-jsx').SpreadElement} SpreadElement * @typedef {import('estree-jsx').Statement} Statement * @typedef {import('estree-jsx').VariableDeclarator} VariableDeclarator * @@ -222,7 +223,7 @@ export function recmaJsxRewrite(options) { } }, leave(node) { - /** @type {Array} */ + /** @type {Array} */ const defaults = [] /** @type {Array} */ const actual = [] @@ -300,24 +301,17 @@ export function recmaJsxRewrite(options) { } if (defaults.length > 0 || parameters.length > 1) { - parameters.unshift({ - type: 'ObjectExpression', - properties: defaults - }) + for (const parameter of parameters) { + defaults.push({type: 'SpreadElement', argument: parameter}) + } } // If we’re getting components from several sources, merge them. /** @type {Expression} */ let componentsInit = - parameters.length > 1 - ? { - type: 'CallExpression', - callee: toIdOrMemberExpression(['Object', 'assign']), - arguments: parameters, - optional: false - } - : parameters[0].type === 'MemberExpression' - ? // If we’re only getting components from `props.components`, + defaults.length > 0 + ? {type: 'ObjectExpression', properties: defaults} + : // If we’re only getting components from `props.components`, // make sure it’s defined. { type: 'LogicalExpression', @@ -325,7 +319,6 @@ export function recmaJsxRewrite(options) { left: parameters[0], right: {type: 'ObjectExpression', properties: []} } - : parameters[0] /** @type {ObjectPattern | undefined} */ let componentsPattern diff --git a/packages/mdx/readme.md b/packages/mdx/readme.md index 826ed66fe..0fb3c01e1 100644 --- a/packages/mdx/readme.md +++ b/packages/mdx/readme.md @@ -92,7 +92,10 @@ import {Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs} from 'react/jsx-runti export const Thing = () => _jsx(_Fragment, {children: 'World'}) function _createMdxContent(props) { - const _components = Object.assign({h1: 'h1'}, props.components) + const _components = { + h1: 'h1', + ...props.components + } return _jsxs(_components.h1, { children: ['Hello ', _jsx(Thing, {})] }) @@ -533,14 +536,20 @@ compile(file, {providerImportSource: '@mdx-js/react'}) export const Thing = () => _jsx(_Fragment, {children: 'World!'}) function _createMdxContent(props) { -- const _components = Object.assign({h1: 'h1'}, props.components) -+ const _components = Object.assign({h1: 'h1'}, _provideComponents(), props.components) + const _components = { + h1: 'h1', ++ ..._provideComponents(), + ...props.components + } return _jsxs(_components.h1, {children: ['Hello ', _jsx(Thing, {})]}) } export default function MDXContent(props = {}) { - const {wrapper: MDXLayout} = props.components || {} -+ const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components) ++ const {wrapper: MDXLayout} = { ++ ..._provideComponents(), ++ ...props.components ++ } return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {children: _jsx(_createMdxContent, {})})) @@ -574,7 +583,10 @@ compile(file, {jsx: true}) +export const Thing = () => <>World! function _createMdxContent(props) { - const _components = Object.assign({h1: 'h1'}, props.components) + const _components = { + h1: 'h1', + ...props.components + } - return _jsxs(_components.h1, {children: ['Hello ', _jsx(Thing, {})]}) + return <_components.h1>{"Hello "} } diff --git a/packages/mdx/test/compile.js b/packages/mdx/test/compile.js index 15233c077..3e4f58e8a 100644 --- a/packages/mdx/test/compile.js +++ b/packages/mdx/test/compile.js @@ -895,10 +895,11 @@ test('jsx', async (t) => { [ '/*@jsxRuntime automatic @jsxImportSource react*/', 'function _createMdxContent(props) {', - ' const _components = Object.assign({', + ' const _components = {', ' em: "em",', - ' p: "p"', - ' }, props.components);', + ' p: "p",', + ' ...props.components', + ' };', ' return <_components.p><_components.em>{"a"};', '}', 'function MDXContent(props = {}) {', @@ -978,9 +979,10 @@ test('jsx', async (t) => { [ '/*@jsxRuntime automatic @jsxImportSource react*/', 'function _createMdxContent(props) {', - ' const _components = Object.assign({', - ' "a-b": "a-b"', - ' }, props.components), _component0 = _components["a-b"];', + ' const _components = {', + ' "a-b": "a-b",', + ' ...props.components', + ' }, _component0 = _components["a-b"];', ' return <>{<_component0>};', '}', 'function MDXContent(props = {}) {', @@ -999,9 +1001,10 @@ test('jsx', async (t) => { [ '/*@jsxRuntime automatic @jsxImportSource react*/', 'function _createMdxContent(props) {', - ' const _components = Object.assign({', - ' p: "p"', - ' }, props.components);', + ' const _components = {', + ' p: "p",', + ' ...props.components', + ' };', ' return <_components.p>{"Hello "}{props.name};', '}', 'function MDXContent(props = {}) {', @@ -1030,9 +1033,10 @@ test('jsx', async (t) => { ' return
;', '};', 'function _createMdxContent(props) {', - ' const _components = Object.assign({', - ' p: "p"', - ' }, props.components);', + ' const _components = {', + ' p: "p",', + ' ...props.components', + ' };', ' return <_components.p>{"a"};', '}', 'function MDXContent(props = {}) {', @@ -1045,6 +1049,42 @@ test('jsx', async (t) => { } ) + await t.test( + 'should combine passing `components` w/ props and a provider', + () => { + assert.equal( + String( + compileSync('a', { + jsx: true, + providerImportSource: '@mdx-js/react' + }) + ), + [ + '/*@jsxRuntime automatic @jsxImportSource react*/', + 'import {useMDXComponents as _provideComponents} from "@mdx-js/react";', + 'function _createMdxContent(props) {', + ' const _components = {', + ' p: "p",', + ' ..._provideComponents(),', + ' ...props.components', + ' };', + ' return <_components.p>{"a"};', + '}', + 'function MDXContent(props = {}) {', + ' const {wrapper: MDXLayout} = {', + ' ..._provideComponents(),', + ' ...props.components', + ' };', + ' return MDXLayout ? <_createMdxContent {...props} /> : _createMdxContent(props);', + + '}', + 'export default MDXContent;', + '' + ].join('\n') + ) + } + ) + await t.test('should serialize double quotes in attribute values', () => { assert.match( String(compileSync("{}", {jsx: true})), diff --git a/packages/rollup/test/index.js b/packages/rollup/test/index.js index b8326137b..bb6d905e9 100644 --- a/packages/rollup/test/index.js +++ b/packages/rollup/test/index.js @@ -34,7 +34,7 @@ test('@mdx-js/rollup', async () => { assert.equal( output[0].map ? output[0].map.mappings : undefined, - ';;;MAAaA,OAAU,GAAA,MAAAC,GAAA,CAAAC,QAAA,EAAA;AAAQ,EAAA,QAAA,EAAA,QAAA;;;;;;;AAE7B,IAAA,QAAA,EAAA,CAAA,SAAA,EAAAD,GAAA,CAAA,OAAA,EAAA,EAAA,CAAA,CAAA;;;;;;;;;;;;', + ';;;MAAaA,OAAU,GAAA,MAAAC,GAAA,CAAAC,QAAA,EAAA;AAAQ,EAAA,QAAA,EAAA,QAAA;;;;;;;;AAE7B,IAAA,QAAA,EAAA,CAAA,SAAA,EAAAD,GAAA,CAAA,OAAA,EAAA,EAAA,CAAA,CAAA;;;;;;;;;;;;', 'should add a source map' )