From 7f8987085c9c5bdcd39b9a6700303e9b9f76b9f2 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Fri, 28 Oct 2022 22:42:37 +0800 Subject: [PATCH] Support rendering `@motionone/solid` components (#5233) --- .changeset/four-donuts-reply.md | 5 +++++ .../astro/src/runtime/server/render/astro.ts | 2 +- .../astro/src/runtime/server/render/component.ts | 11 +++++++++-- .../src/components/ProxyComponent.jsx | 16 ++++++++++++++++ .../solid-component/src/pages/index.astro | 2 ++ packages/astro/test/solid-component.test.js | 14 ++++++++++++++ 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 .changeset/four-donuts-reply.md create mode 100644 packages/astro/test/fixtures/solid-component/src/components/ProxyComponent.jsx diff --git a/.changeset/four-donuts-reply.md b/.changeset/four-donuts-reply.md new file mode 100644 index 000000000000..5c15ad63002c --- /dev/null +++ b/.changeset/four-donuts-reply.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Support rendering `@motionone/solid` components diff --git a/packages/astro/src/runtime/server/render/astro.ts b/packages/astro/src/runtime/server/render/astro.ts index cd1c04885b2a..d6da03007e42 100644 --- a/packages/astro/src/runtime/server/render/astro.ts +++ b/packages/astro/src/runtime/server/render/astro.ts @@ -57,7 +57,7 @@ export function isAstroComponent(obj: any): obj is AstroComponent { } export function isAstroComponentFactory(obj: any): obj is AstroComponentFactory { - return obj == null ? false : !!obj.isAstroComponentFactory; + return obj == null ? false : obj.isAstroComponentFactory === true; } export async function* renderAstroComponent( diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts index 0b6c90ebeba2..54dfb372f8f8 100644 --- a/packages/astro/src/runtime/server/render/component.ts +++ b/packages/astro/src/runtime/server/render/component.ts @@ -56,7 +56,7 @@ export async function renderComponent( _props: Record, slots: any = {} ): Promise { - Component = await Component; + Component = (await Component) ?? Component; switch (getComponentType(Component)) { case 'fragment': { @@ -133,7 +133,14 @@ Did you mean to add ${formatList(probableRendererNames.map((r) => '`' + r + '`') // If this component ran through `__astro_tag_component__`, we already know // which renderer to match to and can skip the usual `check` calls. // This will help us throw most relevant error message for modules with runtime errors - if (Component && (Component as any)[Renderer]) { + let isTagged = false; + try { + isTagged = Component && (Component as any)[Renderer]; + } catch { + // Accessing `Component[Renderer]` may throw if `Component` is a Proxy that doesn't + // return the actual read-only value. In this case, ignore. + } + if (isTagged) { const rendererName = (Component as any)[Renderer]; renderer = renderers.find(({ name }) => name === rendererName); } diff --git a/packages/astro/test/fixtures/solid-component/src/components/ProxyComponent.jsx b/packages/astro/test/fixtures/solid-component/src/components/ProxyComponent.jsx new file mode 100644 index 000000000000..9132c9a6cd9a --- /dev/null +++ b/packages/astro/test/fixtures/solid-component/src/components/ProxyComponent.jsx @@ -0,0 +1,16 @@ +import { Dynamic } from 'solid-js/web' + +const BaseComponent = ({ tag } = {}) => { + return Hello world; +} + +// Motion uses a Proxy to support syntax like `` and `` etc +// https://cdn.jsdelivr.net/npm/@motionone/solid@10.14.2/dist/source/motion.jsx +const ProxyComponent = new Proxy(BaseComponent, { + get: (_, tag) => (props) => { + delete props.tag + return ; + } +}) + +export default ProxyComponent; diff --git a/packages/astro/test/fixtures/solid-component/src/pages/index.astro b/packages/astro/test/fixtures/solid-component/src/pages/index.astro index 06c48e18a68d..a484a6b8d248 100644 --- a/packages/astro/test/fixtures/solid-component/src/pages/index.astro +++ b/packages/astro/test/fixtures/solid-component/src/pages/index.astro @@ -2,6 +2,7 @@ import Hello from '../components/Hello.jsx'; import WithNewlines from '../components/WithNewlines.jsx'; import { Router } from "@solidjs/router"; +import ProxyComponent from '../components/ProxyComponent.jsx'; --- Solid @@ -10,6 +11,7 @@ import { Router } from "@solidjs/router"; + diff --git a/packages/astro/test/solid-component.test.js b/packages/astro/test/solid-component.test.js index 0a05118eb08d..ed3af45e8883 100644 --- a/packages/astro/test/solid-component.test.js +++ b/packages/astro/test/solid-component.test.js @@ -22,6 +22,9 @@ describe('Solid component', () => { // test 1: Works expect($('.hello')).to.have.lengthOf(1); + + // test 2: Support rendering proxy components + expect($('#proxy-component').text()).to.be.equal('Hello world'); }); }); @@ -38,6 +41,17 @@ describe('Solid component', () => { await devServer.stop(); }); + it('Can load a component', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + + // test 1: Works + expect($('.hello')).to.have.lengthOf(1); + + // test 2: Support rendering proxy components + expect($('#proxy-component').text()).to.be.equal('Hello world'); + }); + it('scripts proxy correctly', async () => { const html = await fixture.fetch('/').then((res) => res.text()); const $ = cheerio.load(html);