summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Bjorn Lu <bjornlu.dev@gmail.com> 2023-02-15 09:49:57 +0100
committerGravatar GitHub <noreply@github.com> 2023-02-15 16:49:57 +0800
commit1c678f7ebff6b8ea843bf4b49ab73ca942a2a755 (patch)
treed05ca779876080f7196f7559d97706c9d4300422
parentac3649bb589a3ee1deab4ba73c06a36a45e2cee5 (diff)
downloadastro-1c678f7ebff6b8ea843bf4b49ab73ca942a2a755.tar.gz
astro-1c678f7ebff6b8ea843bf4b49ab73ca942a2a755.tar.zst
astro-1c678f7ebff6b8ea843bf4b49ab73ca942a2a755.zip
Fix hydration path for circular imports (#6244)
-rw-r--r--.changeset/selfish-frogs-tell.md5
-rw-r--r--packages/astro/e2e/fixtures/solid-circular/astro.config.mjs7
-rw-r--r--packages/astro/e2e/fixtures/solid-circular/package.json12
-rw-r--r--packages/astro/e2e/fixtures/solid-circular/src/components/ContextProvider.tsx12
-rw-r--r--packages/astro/e2e/fixtures/solid-circular/src/components/SimpleDiv.tsx8
-rw-r--r--packages/astro/e2e/fixtures/solid-circular/src/env.d.ts1
-rw-r--r--packages/astro/e2e/fixtures/solid-circular/src/pages/index.astro15
-rw-r--r--packages/astro/e2e/solid-circular.test.js23
-rw-r--r--packages/astro/src/core/render/dev/environment.ts2
-rw-r--r--packages/astro/src/core/render/dev/resolve.ts6
-rw-r--r--packages/astro/src/core/util.ts10
-rw-r--r--pnpm-lock.yaml11
12 files changed, 106 insertions, 6 deletions
diff --git a/.changeset/selfish-frogs-tell.md b/.changeset/selfish-frogs-tell.md
new file mode 100644
index 000000000..0ed5b0b16
--- /dev/null
+++ b/.changeset/selfish-frogs-tell.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix hydrate loading path to prevent multiple instance loaded for circular imports
diff --git a/packages/astro/e2e/fixtures/solid-circular/astro.config.mjs b/packages/astro/e2e/fixtures/solid-circular/astro.config.mjs
new file mode 100644
index 000000000..a6c39b853
--- /dev/null
+++ b/packages/astro/e2e/fixtures/solid-circular/astro.config.mjs
@@ -0,0 +1,7 @@
+import { defineConfig } from 'astro/config';
+import solid from '@astrojs/solid-js';
+
+// https://astro.build/config
+export default defineConfig({
+ integrations: [solid()],
+});
diff --git a/packages/astro/e2e/fixtures/solid-circular/package.json b/packages/astro/e2e/fixtures/solid-circular/package.json
new file mode 100644
index 000000000..a354ec9ec
--- /dev/null
+++ b/packages/astro/e2e/fixtures/solid-circular/package.json
@@ -0,0 +1,12 @@
+{
+ "name": "@e2e/solid-circular",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/solid-js": "workspace:*",
+ "astro": "workspace:*"
+ },
+ "devDependencies": {
+ "solid-js": "^1.4.3"
+ }
+}
diff --git a/packages/astro/e2e/fixtures/solid-circular/src/components/ContextProvider.tsx b/packages/astro/e2e/fixtures/solid-circular/src/components/ContextProvider.tsx
new file mode 100644
index 000000000..191a4cf8c
--- /dev/null
+++ b/packages/astro/e2e/fixtures/solid-circular/src/components/ContextProvider.tsx
@@ -0,0 +1,12 @@
+import { Component, createContext } from 'solid-js';
+import { SimpleDiv } from './SimpleDiv';
+
+export const ApplicationContext = createContext([{ lng: 'en' }, {}]);
+
+export const ContextProvider: Component = () => {
+ return (
+ <ApplicationContext.Provider value={[{ lng: 'fr' }]}>
+ <SimpleDiv />
+ </ApplicationContext.Provider>
+ );
+};
diff --git a/packages/astro/e2e/fixtures/solid-circular/src/components/SimpleDiv.tsx b/packages/astro/e2e/fixtures/solid-circular/src/components/SimpleDiv.tsx
new file mode 100644
index 000000000..0607149c4
--- /dev/null
+++ b/packages/astro/e2e/fixtures/solid-circular/src/components/SimpleDiv.tsx
@@ -0,0 +1,8 @@
+import { Component, useContext } from 'solid-js';
+import { ApplicationContext } from './ContextProvider';
+
+export const SimpleDiv: Component = () => {
+ const [context] = useContext(ApplicationContext);
+
+ return <div id="context">{context.lng}</div>;
+};
diff --git a/packages/astro/e2e/fixtures/solid-circular/src/env.d.ts b/packages/astro/e2e/fixtures/solid-circular/src/env.d.ts
new file mode 100644
index 000000000..8c34fb45e
--- /dev/null
+++ b/packages/astro/e2e/fixtures/solid-circular/src/env.d.ts
@@ -0,0 +1 @@
+/// <reference types="astro/client" /> \ No newline at end of file
diff --git a/packages/astro/e2e/fixtures/solid-circular/src/pages/index.astro b/packages/astro/e2e/fixtures/solid-circular/src/pages/index.astro
new file mode 100644
index 000000000..cafe1df49
--- /dev/null
+++ b/packages/astro/e2e/fixtures/solid-circular/src/pages/index.astro
@@ -0,0 +1,15 @@
+---
+import { ContextProvider } from "../components/ContextProvider.tsx";
+---
+
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width" />
+ </head>
+ <body>
+ <main>
+ <ContextProvider client:only />
+ </main>
+ </body>
+</html>
diff --git a/packages/astro/e2e/solid-circular.test.js b/packages/astro/e2e/solid-circular.test.js
new file mode 100644
index 000000000..57e3fc5aa
--- /dev/null
+++ b/packages/astro/e2e/solid-circular.test.js
@@ -0,0 +1,23 @@
+import { expect } from '@playwright/test';
+import { testFactory } from './test-utils.js';
+
+const test = testFactory({ root: './fixtures/solid-circular/' });
+
+let devServer;
+
+test.beforeAll(async ({ astro }) => {
+ devServer = await astro.startDevServer();
+});
+
+test.afterAll(async () => {
+ await devServer.stop();
+});
+
+test.describe('Circular imports with Solid', () => {
+ test('Context', async ({ astro, page }) => {
+ await page.goto('/');
+
+ const wrapper = page.locator('#context');
+ await expect(wrapper, 'context should not be duplicated').toHaveText('fr');
+ });
+});
diff --git a/packages/astro/src/core/render/dev/environment.ts b/packages/astro/src/core/render/dev/environment.ts
index 1704c6f29..7f9fe3195 100644
--- a/packages/astro/src/core/render/dev/environment.ts
+++ b/packages/astro/src/core/render/dev/environment.ts
@@ -29,7 +29,7 @@ export function createDevelopmentEnvironment(
mode,
// This will be overridden in the dev server
renderers: [],
- resolve: createResolve(loader),
+ resolve: createResolve(loader, settings.config.root),
routeCache: new RouteCache(logging, mode),
site: settings.config.site,
ssr: settings.config.output === 'server',
diff --git a/packages/astro/src/core/render/dev/resolve.ts b/packages/astro/src/core/render/dev/resolve.ts
index b51e577fc..164333cdc 100644
--- a/packages/astro/src/core/render/dev/resolve.ts
+++ b/packages/astro/src/core/render/dev/resolve.ts
@@ -1,17 +1,17 @@
import type { ModuleLoader } from '../../module-loader/index';
import { resolveIdToUrl } from '../../util.js';
-export function createResolve(loader: ModuleLoader) {
+export function createResolve(loader: ModuleLoader, root: URL) {
// Resolves specifiers in the inline hydrated scripts, such as:
// - @astrojs/preact/client.js
// - @/components/Foo.vue
// - /Users/macos/project/src/Foo.vue
// - C:/Windows/project/src/Foo.vue (normalized slash)
return async function (s: string) {
- const url = await resolveIdToUrl(loader, s);
+ const url = await resolveIdToUrl(loader, s, root);
// Vite does not resolve .jsx -> .tsx when coming from hydration script import,
// clip it so Vite is able to resolve implicitly.
- if (url.startsWith('/@fs') && url.endsWith('.jsx')) {
+ if (url.startsWith('/') && url.endsWith('.jsx')) {
return url.slice(0, -4);
} else {
return url;
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index f80eb5fe7..a7152e41a 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -161,7 +161,7 @@ export function emoji(char: string, fallback: string) {
*/
// NOTE: `/@id/` should only be used when the id is fully resolved
// TODO: Export a helper util from Vite
-export async function resolveIdToUrl(loader: ModuleLoader, id: string) {
+export async function resolveIdToUrl(loader: ModuleLoader, id: string, root?: URL) {
let resultId = await loader.resolveId(id, undefined);
// Try resolve jsx to tsx
if (!resultId && id.endsWith('.jsx')) {
@@ -171,7 +171,13 @@ export async function resolveIdToUrl(loader: ModuleLoader, id: string) {
return VALID_ID_PREFIX + id;
}
if (path.isAbsolute(resultId)) {
- return '/@fs' + prependForwardSlash(resultId);
+ const normalizedRoot = root && normalizePath(fileURLToPath(root));
+ // Convert to root-relative path if path is inside root
+ if (normalizedRoot && resultId.startsWith(normalizedRoot)) {
+ return resultId.slice(normalizedRoot.length - 1);
+ } else {
+ return '/@fs' + prependForwardSlash(resultId);
+ }
}
return VALID_ID_PREFIX + resultId;
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6d665afdb..95cac6a47 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1014,6 +1014,17 @@ importers:
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
+ packages/astro/e2e/fixtures/solid-circular:
+ specifiers:
+ '@astrojs/solid-js': workspace:*
+ astro: workspace:*
+ solid-js: ^1.4.3
+ dependencies:
+ '@astrojs/solid-js': link:../../../../integrations/solid
+ astro: link:../../..
+ devDependencies:
+ solid-js: 1.6.10
+
packages/astro/e2e/fixtures/solid-component:
specifiers:
'@astrojs/mdx': workspace:*