diff --git a/packages/mdx/lib/plugin/recma-document.js b/packages/mdx/lib/plugin/recma-document.js index 8ff1db329..2777d975b 100644 --- a/packages/mdx/lib/plugin/recma-document.js +++ b/packages/mdx/lib/plugin/recma-document.js @@ -602,9 +602,33 @@ export function recmaDocument(options) { argument = argument.children[0] } + let awaitExpression = false + + walk(argument, { + enter(node) { + if ( + node.type === 'ArrowFunctionExpression' || + node.type === 'FunctionDeclaration' || + node.type === 'FunctionExpression' + ) { + return this.skip() + } + + if ( + node.type === 'AwaitExpression' || + /* c8 ignore next 2 -- can only occur in a function (which then can + * only be async, so skipped it) */ + (node.type === 'ForOfStatement' && node.await) + ) { + awaitExpression = true + } + } + }) + return [ { type: 'FunctionDeclaration', + async: awaitExpression, id: {type: 'Identifier', name: '_createMdxContent'}, params: [{type: 'Identifier', name: 'props'}], body: { diff --git a/packages/mdx/test/compile.js b/packages/mdx/test/compile.js index 5908b97f0..e43920751 100644 --- a/packages/mdx/test/compile.js +++ b/packages/mdx/test/compile.js @@ -973,6 +973,42 @@ test('@mdx-js/mdx: compile', async function (t) { } ) + await t.test( + 'should support an `await` expression in content (GH-2242)', + async function () { + const element = React.createElement( + await run(await compile('{await Promise.resolve(42)}')) + ) + + try { + // Not supported yet by React, so it throws. + renderToStaticMarkup(element) + assert.fail() + } catch (error) { + assert.match( + String(error), + /Objects are not valid as a React child \(found: \[object Promise]\)/ + ) + } + } + ) + + await t.test( + 'should not detect `await` inside functions (GH-2242)', + async function () { + const value = `{(function () { + return 21 + + async function unused() { + await Promise.resolve(42) + } +})()}` + const element = React.createElement(await run(await compile(value))) + + assert.equal(renderToStaticMarkup(element), '21') + } + ) + await t.test('should support source maps', async function () { const base = new URL('context/', import.meta.url) const url = new URL('sourcemap.js', base)