summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/astro/src/jsx/server.ts32
-rw-r--r--packages/integrations/mdx/src/index.ts3
-rw-r--r--packages/integrations/mdx/test/fixtures/invalid-mdx-component/src/pages/invalid-content.mdx7
-rw-r--r--packages/integrations/mdx/test/invalid-mdx-component.test.js40
-rw-r--r--pnpm-lock.yaml9
5 files changed, 90 insertions, 1 deletions
diff --git a/packages/astro/src/jsx/server.ts b/packages/astro/src/jsx/server.ts
index a666d2030..6374b1ebd 100644
--- a/packages/astro/src/jsx/server.ts
+++ b/packages/astro/src/jsx/server.ts
@@ -17,7 +17,20 @@ export async function check(
try {
const result = await Component({ ...props, ...slots, children });
return result[AstroJSX];
- } catch (e) {}
+ } catch (e) {
+ const error = e as Error;
+ // if the exception is from an mdx component
+ // throw an error
+ if (Component[Symbol.for('mdx-component')]) {
+ throw createFormattedError({
+ message: error.message,
+ title: error.name,
+ hint: `This issue often occurs when your MDX component encounters runtime errors.`,
+ name: error.name,
+ stack: error.stack,
+ });
+ }
+ }
return false;
}
@@ -38,6 +51,23 @@ export async function renderToStaticMarkup(
return { html };
}
+type FormatErrorOptions = {
+ message: string;
+ name: string;
+ stack?: string;
+ hint: string;
+ title: string;
+};
+// TODO: Remove this function and use `AstroError` when we refactor it to be usable without error codes
+function createFormattedError({ message, name, stack, hint }: FormatErrorOptions) {
+ const error = new Error(message);
+ error.name = name;
+ error.stack = stack;
+ // @ts-expect-error - hint is not part of the Error interface but it will be picked up by the error overlay
+ error.hint = hint;
+ return error;
+}
+
export default {
check,
renderToStaticMarkup,
diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts
index 18c9aceca..1d0320213 100644
--- a/packages/integrations/mdx/src/index.ts
+++ b/packages/integrations/mdx/src/index.ts
@@ -165,6 +165,9 @@ export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroI
export default Content;`;
}
+ // mark the component as an MDX component
+ code += `\nContent[Symbol.for('mdx-component')] = true`;
+
// Ensures styles and scripts are injected into a `<head>`
// When a layout is not applied
code += `\nContent[Symbol.for('astro.needsHeadRendering')] = !Boolean(frontmatter.layout);`;
diff --git a/packages/integrations/mdx/test/fixtures/invalid-mdx-component/src/pages/invalid-content.mdx b/packages/integrations/mdx/test/fixtures/invalid-mdx-component/src/pages/invalid-content.mdx
new file mode 100644
index 000000000..9ebaa695b
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/invalid-mdx-component/src/pages/invalid-content.mdx
@@ -0,0 +1,7 @@
+---
+title: Hello, World
+---
+
+# {A.VALID.JAVASCRIPT.EXPRESSION.THAT.RESULTS.IN.A.RUNTIME.ERROR}
+
+Invalid content in the frontmatter
diff --git a/packages/integrations/mdx/test/invalid-mdx-component.test.js b/packages/integrations/mdx/test/invalid-mdx-component.test.js
new file mode 100644
index 000000000..a07401c60
--- /dev/null
+++ b/packages/integrations/mdx/test/invalid-mdx-component.test.js
@@ -0,0 +1,40 @@
+import { expect } from "chai";
+import { loadFixture } from "../../../astro/test/test-utils.js";
+import mdx from "../dist/index.js";
+
+const FIXTURE_ROOT = new URL(
+ "./fixtures/invalid-mdx-component/",
+ import.meta.url,
+);
+
+describe("MDX component with runtime error", () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: FIXTURE_ROOT,
+ integrations: [mdx()],
+ });
+ });
+
+ describe("build", () => {
+ /** @type {Error | null} */
+ let error;
+
+ before(async () => {
+ error = null;
+ try {
+ await fixture.build();
+ } catch (e) {
+ error = e;
+ }
+ });
+
+ it("Throws the right error", async () => {
+ expect(error).to.exist;
+ expect(error?.hint).to.match(
+ /This issue often occurs when your MDX component encounters runtime errors/,
+ );
+ });
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f4d222da1..e0c2e5d89 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4231,6 +4231,15 @@ importers:
specifier: 0.2.3
version: 0.2.3
+ packages/integrations/mdx/test/fixtures/invalid-mdx-component:
+ dependencies:
+ '@astrojs/mdx':
+ specifier: workspace:*
+ version: link:../../..
+ astro:
+ specifier: workspace:*
+ version: link:../../../../../astro
+
packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection:
dependencies:
'@astrojs/mdx':