Skip to content

Commit c23377c

Browse files
authored
Fix getCollection return new instance in prod (#8022)
1 parent 86bee28 commit c23377c

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

.changeset/smart-nails-push.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Always return a new array instance from `getCollection` in prod

packages/astro/src/content/runtime.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ export function createGetCollection({
6969
// Cache `getCollection()` calls in production only
7070
// prevents stale cache in development
7171
if (import.meta.env.PROD && cacheEntriesByCollection.has(collection)) {
72-
entries = cacheEntriesByCollection.get(collection)!;
72+
// Always return a new instance so consumers can safely mutate it
73+
entries = [...cacheEntriesByCollection.get(collection)!]
7374
} else {
7475
entries = await Promise.all(
7576
lazyImports.map(async (lazyImport) => {

packages/astro/test/content-collections-render.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,22 @@ describe('Content Collections - render()', () => {
168168
expect(h2).to.have.a.lengthOf(1);
169169
expect(h2.attr('data-components-export-applied')).to.equal('true');
170170
});
171+
172+
it('getCollection should return new instances of the array to be mutated safely', async () => {
173+
const app = await fixture.loadTestAdapterApp();
174+
175+
let request = new Request('http://example.com/sort-blog-collection');
176+
let response = await app.render(request);
177+
let html = await response.text();
178+
let $ = cheerio.load(html);
179+
expect($('li').first().text()).to.equal('With Layout Prop');
180+
181+
request = new Request('http://example.com/');
182+
response = await app.render(request);
183+
html = await response.text();
184+
$ = cheerio.load(html);
185+
expect($('li').first().text()).to.equal('Hello world');
186+
})
171187
});
172188

173189
describe('Dev - SSG', () => {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
import { getCollection } from 'astro:content';
3+
4+
const blog = await getCollection('blog');
5+
6+
// Sort descending by title, make sure mutating `blog` doesn't mutate other pages that call `getCollection` too
7+
blog.sort((a, b) => a.data.title < b.data.title ? 1 : -1)
8+
---
9+
<html>
10+
<head>
11+
<title>Index</title>
12+
</head>
13+
<body>
14+
<h1>Blog Posts</h1>
15+
16+
<ul>
17+
{blog.map(post => (
18+
<li>{ post.data.title }</li>
19+
))}
20+
</ul>
21+
</body>
22+
</html>

0 commit comments

Comments
 (0)