summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/tall-files-smash.md5
-rw-r--r--packages/astro/src/jsx-runtime/index.ts4
-rw-r--r--packages/astro/src/runtime/server/jsx.ts4
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-infinite-loop/astro.config.ts6
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-infinite-loop/package.json10
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/components/Test.js3
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/doc.mdx6
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/index.astro5
-rw-r--r--packages/integrations/mdx/test/mdx-infinite-loop.test.js30
-rw-r--r--pnpm-lock.yaml12
10 files changed, 84 insertions, 1 deletions
diff --git a/.changeset/tall-files-smash.md b/.changeset/tall-files-smash.md
new file mode 100644
index 000000000..537fe49f5
--- /dev/null
+++ b/.changeset/tall-files-smash.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix MDX error handling, preventing a memory leak
diff --git a/packages/astro/src/jsx-runtime/index.ts b/packages/astro/src/jsx-runtime/index.ts
index 20630a82a..f0a476f82 100644
--- a/packages/astro/src/jsx-runtime/index.ts
+++ b/packages/astro/src/jsx-runtime/index.ts
@@ -1,9 +1,10 @@
-import { Fragment, markHTMLString } from '../runtime/server/index.js';
+import { Renderer, Fragment, markHTMLString } from '../runtime/server/index.js';
const AstroJSX = 'astro:jsx';
const Empty = Symbol('empty');
export interface AstroVNode {
+ [Renderer]: string;
[AstroJSX]: boolean;
type: string | ((...args: any) => any);
props: Record<string, any>;
@@ -74,6 +75,7 @@ function transformSetDirectives(vnode: AstroVNode) {
function createVNode(type: any, props: Record<string, any>) {
const vnode: AstroVNode = {
+ [Renderer]: 'astro:jsx',
[AstroJSX]: true,
type,
props: props ?? {},
diff --git a/packages/astro/src/runtime/server/jsx.ts b/packages/astro/src/runtime/server/jsx.ts
index 3e5816f28..6ee12a406 100644
--- a/packages/astro/src/runtime/server/jsx.ts
+++ b/packages/astro/src/runtime/server/jsx.ts
@@ -38,6 +38,10 @@ export async function renderJSX(result: SSRResult, vnode: any): Promise<any> {
}
if (isVNode(vnode)) {
switch (true) {
+ case !vnode.type: {
+ throw new Error(`Unable to render ${result._metadata.pathname} because it contains an undefined Component!
+Did you forget to import the component or is it possible there is a typo?`)
+ }
case (vnode.type as any) === Symbol.for('astro:fragment'):
return renderJSX(result, vnode.props.children);
case (vnode.type as any).isAstroComponentFactory: {
diff --git a/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/astro.config.ts b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/astro.config.ts
new file mode 100644
index 000000000..75a2b5f3a
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/astro.config.ts
@@ -0,0 +1,6 @@
+import mdx from '@astrojs/mdx';
+import preact from '@astrojs/preact';
+
+export default {
+ integrations: [mdx(), preact()]
+}
diff --git a/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/package.json b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/package.json
new file mode 100644
index 000000000..5d1ab5632
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "@test/mdx-infinite-loop",
+ "type": "module",
+ "dependencies": {
+ "@astrojs/mdx": "workspace:*",
+ "@astrojs/preact": "workspace:*",
+ "preact": "^10.7.3",
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/components/Test.js b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/components/Test.js
new file mode 100644
index 000000000..831fb327c
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/components/Test.js
@@ -0,0 +1,3 @@
+export default function () {
+ return 'Hello world'
+}
diff --git a/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/doc.mdx b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/doc.mdx
new file mode 100644
index 000000000..8b8dc5e07
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/doc.mdx
@@ -0,0 +1,6 @@
+import Test, { Missing } from '../components/Test';
+
+# Hello page!
+
+<Test />
+<Missing />
diff --git a/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/index.astro b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/index.astro
new file mode 100644
index 000000000..11f7af385
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/mdx-infinite-loop/src/pages/index.astro
@@ -0,0 +1,5 @@
+---
+const files = await Astro.glob('./**/*.mdx')
+---
+
+{files.map((file: any) => <file.Content />)}
diff --git a/packages/integrations/mdx/test/mdx-infinite-loop.test.js b/packages/integrations/mdx/test/mdx-infinite-loop.test.js
new file mode 100644
index 000000000..c76c24270
--- /dev/null
+++ b/packages/integrations/mdx/test/mdx-infinite-loop.test.js
@@ -0,0 +1,30 @@
+import mdx from '@astrojs/mdx';
+
+import { expect } from 'chai';
+import { loadFixture } from '../../../astro/test/test-utils.js';
+
+describe('MDX Infinite Loop', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: new URL('./fixtures/mdx-infinite-loop/', import.meta.url),
+ integrations: [mdx()],
+ });
+ });
+
+ describe('build', () => {
+ let err;
+ before(async () => {
+ try {
+ await fixture.build();
+ } catch (e) {
+ err = e;
+ }
+ });
+
+ it('does not hang forever if an error is thrown', async () => {
+ expect(!!err).to.be.true;
+ });
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a25d9fea1..e47fe2fda 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2729,6 +2729,18 @@ importers:
reading-time: 1.5.0
unist-util-visit: 4.1.1
+ packages/integrations/mdx/test/fixtures/mdx-infinite-loop:
+ specifiers:
+ '@astrojs/mdx': workspace:*
+ '@astrojs/preact': workspace:*
+ astro: workspace:*
+ preact: ^10.7.3
+ dependencies:
+ '@astrojs/mdx': link:../../..
+ '@astrojs/preact': link:../../../../preact
+ astro: link:../../../../../astro
+ preact: 10.11.0
+
packages/integrations/mdx/test/fixtures/mdx-namespace:
specifiers:
'@astrojs/mdx': workspace:*