summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/early-melons-thank.md5
-rw-r--r--packages/astro/src/content/runtime.ts7
-rw-r--r--packages/astro/test/content-collections.test.js22
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/astro.config.mjs6
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/package.json9
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/src/content/blog/first.md6
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/src/content/blog/second.md6
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/src/content/blog/third.md6
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/src/content/config.ts16
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/src/pages/another_page.astro25
-rw-r--r--packages/astro/test/fixtures/content-collections-mutation/src/pages/index.astro25
-rw-r--r--pnpm-lock.yaml9
12 files changed, 139 insertions, 3 deletions
diff --git a/.changeset/early-melons-thank.md b/.changeset/early-melons-thank.md
new file mode 100644
index 000000000..c12a20de4
--- /dev/null
+++ b/.changeset/early-melons-thank.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Updates `getCollection()` to always return a cloned array
diff --git a/packages/astro/src/content/runtime.ts b/packages/astro/src/content/runtime.ts
index 21af34e1d..484fe6a8d 100644
--- a/packages/astro/src/content/runtime.ts
+++ b/packages/astro/src/content/runtime.ts
@@ -79,8 +79,7 @@ export function createGetCollection({
// Cache `getCollection()` calls in production only
// prevents stale cache in development
if (!import.meta.env?.DEV && cacheEntriesByCollection.has(collection)) {
- // Always return a new instance so consumers can safely mutate it
- entries = [...cacheEntriesByCollection.get(collection)!];
+ entries = cacheEntriesByCollection.get(collection)!;
} else {
const limit = pLimit(10);
entries = await Promise.all(
@@ -115,7 +114,9 @@ export function createGetCollection({
if (typeof filter === 'function') {
return entries.filter(filter);
} else {
- return entries;
+ // Clone the array so users can safely mutate it.
+ // slice() is faster than ...spread for large arrays.
+ return entries.slice();
}
};
}
diff --git a/packages/astro/test/content-collections.test.js b/packages/astro/test/content-collections.test.js
index b7f5abb07..7996f1161 100644
--- a/packages/astro/test/content-collections.test.js
+++ b/packages/astro/test/content-collections.test.js
@@ -370,4 +370,26 @@ describe('Content Collections', () => {
assert.equal($('script').attr('src').startsWith('/docs'), true);
});
});
+
+ describe('Mutation', () => {
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/content-collections-mutation/',
+ });
+ await fixture.build();
+ });
+
+ it('Does not mutate cached collection', async () => {
+ const html = await fixture.readFile('/index.html');
+ const index = cheerio.load(html)('h2:first').text();
+ const html2 = await fixture.readFile('/another_page/index.html');
+ const anotherPage = cheerio.load(html2)('h2:first').text();
+
+ assert.equal(index, anotherPage);
+ });
+
+ });
+
});
diff --git a/packages/astro/test/fixtures/content-collections-mutation/astro.config.mjs b/packages/astro/test/fixtures/content-collections-mutation/astro.config.mjs
new file mode 100644
index 000000000..d69e57975
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/astro.config.mjs
@@ -0,0 +1,6 @@
+import mdx from '@astrojs/mdx';
+import { defineConfig } from 'astro/config';
+
+export default defineConfig({
+ integrations: [mdx()],
+});
diff --git a/packages/astro/test/fixtures/content-collections-mutation/package.json b/packages/astro/test/fixtures/content-collections-mutation/package.json
new file mode 100644
index 000000000..288dc2562
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/content-collections-mutation",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*",
+ "@astrojs/mdx": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/first.md b/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/first.md
new file mode 100644
index 000000000..0ecb2d858
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/first.md
@@ -0,0 +1,6 @@
+---
+title: "First Blog"
+date: 2024-04-05
+---
+
+First blog content.
diff --git a/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/second.md b/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/second.md
new file mode 100644
index 000000000..dcded99cc
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/second.md
@@ -0,0 +1,6 @@
+---
+title: "Second Blog"
+date: 2024-04-06
+---
+
+Second blog content.
diff --git a/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/third.md b/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/third.md
new file mode 100644
index 000000000..1adee3173
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/src/content/blog/third.md
@@ -0,0 +1,6 @@
+---
+title: "Third Blog"
+date: 2024-04-07
+---
+
+Third blog content.
diff --git a/packages/astro/test/fixtures/content-collections-mutation/src/content/config.ts b/packages/astro/test/fixtures/content-collections-mutation/src/content/config.ts
new file mode 100644
index 000000000..601b05cca
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/src/content/config.ts
@@ -0,0 +1,16 @@
+// 1. Import utilities from `astro:content`
+import { z, defineCollection } from "astro:content";
+
+// 2. Define a `type` and `schema` for each collection
+const blogCollection = defineCollection({
+ type: "content", // v2.5.0 and later
+ schema: z.object({
+ title: z.string(),
+ date: z.date(),
+ }),
+});
+
+// 3. Export a single `collections` object to register your collection(s)
+export const collections = {
+ blog: blogCollection,
+};
diff --git a/packages/astro/test/fixtures/content-collections-mutation/src/pages/another_page.astro b/packages/astro/test/fixtures/content-collections-mutation/src/pages/another_page.astro
new file mode 100644
index 000000000..447b2cf07
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/src/pages/another_page.astro
@@ -0,0 +1,25 @@
+---
+import { getCollection } from "astro:content";
+const blogs = await getCollection("blog");
+blogs.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); // sort by date most recent first
+const latestBlog = blogs.splice(0, 1)[0]; // modifies the collection
+---
+
+<html>
+ <body>
+ <a href="/">home</a>
+ <h1>Latest Blog</h1>
+ <h2>{latestBlog.data.title}</h2>
+ <p>posted: {latestBlog.data.date.toLocaleString()}</p>
+ <br />
+ <h2>Older blogs</h2>
+ {
+ blogs.map((b) => (
+ <>
+ <h3>{b.data.title}</h3>
+ <p>posted: {b.data.date.toLocaleString()}</p>
+ </>
+ ))
+ }
+ </body>
+</html>
diff --git a/packages/astro/test/fixtures/content-collections-mutation/src/pages/index.astro b/packages/astro/test/fixtures/content-collections-mutation/src/pages/index.astro
new file mode 100644
index 000000000..6b24144d9
--- /dev/null
+++ b/packages/astro/test/fixtures/content-collections-mutation/src/pages/index.astro
@@ -0,0 +1,25 @@
+---
+import { getCollection } from "astro:content";
+const blogs = await getCollection("blog");
+blogs.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); // sort by date most recent first
+const latestBlog = blogs.splice(0, 1)[0]; // modifies the collection
+---
+
+<html>
+ <body>
+ <a href="/another_page">other page</a>
+ <h1>Latest Blog</h1>
+ <h2>{latestBlog.data.title}</h2>
+ <p>posted: {latestBlog.data.date.toLocaleString()}</p>
+ <br />
+ <h2>Older blogs</h2>
+ {
+ blogs.map((b) => (
+ <>
+ <h3>{b.data.title}</h3>
+ <p>posted: {b.data.date.toLocaleString()}</p>
+ </>
+ ))
+ }
+ </body>
+</html>
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 40e008fd3..91b6cf92c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2599,6 +2599,15 @@ importers:
specifier: workspace:*
version: link:../../..
+ packages/astro/test/fixtures/content-collections-mutation:
+ dependencies:
+ '@astrojs/mdx':
+ specifier: workspace:*
+ version: link:../../../../integrations/mdx
+ astro:
+ specifier: workspace:*
+ version: link:../../..
+
packages/astro/test/fixtures/content-collections-with-config-mjs:
dependencies:
astro: