diff options
-rw-r--r-- | .changeset/smart-nails-push.md | 5 | ||||
-rw-r--r-- | packages/astro/src/content/runtime.ts | 3 | ||||
-rw-r--r-- | packages/astro/test/content-collections-render.test.js | 16 | ||||
-rw-r--r-- | packages/astro/test/fixtures/content/src/pages/sort-blog-collection.astro | 22 |
4 files changed, 45 insertions, 1 deletions
diff --git a/.changeset/smart-nails-push.md b/.changeset/smart-nails-push.md new file mode 100644 index 000000000..3166e9f46 --- /dev/null +++ b/.changeset/smart-nails-push.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Always return a new array instance from `getCollection` in prod diff --git a/packages/astro/src/content/runtime.ts b/packages/astro/src/content/runtime.ts index a1afb2201..bb89c6099 100644 --- a/packages/astro/src/content/runtime.ts +++ b/packages/astro/src/content/runtime.ts @@ -69,7 +69,8 @@ export function createGetCollection({ // Cache `getCollection()` calls in production only // prevents stale cache in development if (import.meta.env.PROD && cacheEntriesByCollection.has(collection)) { - entries = cacheEntriesByCollection.get(collection)!; + // Always return a new instance so consumers can safely mutate it + entries = [...cacheEntriesByCollection.get(collection)!] } else { entries = await Promise.all( lazyImports.map(async (lazyImport) => { diff --git a/packages/astro/test/content-collections-render.test.js b/packages/astro/test/content-collections-render.test.js index e1107b10f..8bcc35817 100644 --- a/packages/astro/test/content-collections-render.test.js +++ b/packages/astro/test/content-collections-render.test.js @@ -168,6 +168,22 @@ describe('Content Collections - render()', () => { expect(h2).to.have.a.lengthOf(1); expect(h2.attr('data-components-export-applied')).to.equal('true'); }); + + it('getCollection should return new instances of the array to be mutated safely', async () => { + const app = await fixture.loadTestAdapterApp(); + + let request = new Request('http://example.com/sort-blog-collection'); + let response = await app.render(request); + let html = await response.text(); + let $ = cheerio.load(html); + expect($('li').first().text()).to.equal('With Layout Prop'); + + request = new Request('http://example.com/'); + response = await app.render(request); + html = await response.text(); + $ = cheerio.load(html); + expect($('li').first().text()).to.equal('Hello world'); + }) }); describe('Dev - SSG', () => { diff --git a/packages/astro/test/fixtures/content/src/pages/sort-blog-collection.astro b/packages/astro/test/fixtures/content/src/pages/sort-blog-collection.astro new file mode 100644 index 000000000..542606819 --- /dev/null +++ b/packages/astro/test/fixtures/content/src/pages/sort-blog-collection.astro @@ -0,0 +1,22 @@ +--- +import { getCollection } from 'astro:content'; + +const blog = await getCollection('blog'); + +// Sort descending by title, make sure mutating `blog` doesn't mutate other pages that call `getCollection` too +blog.sort((a, b) => a.data.title < b.data.title ? 1 : -1) +--- +<html> +<head> + <title>Index</title> +</head> +<body> + <h1>Blog Posts</h1> + + <ul> + {blog.map(post => ( + <li>{ post.data.title }</li> + ))} + </ul> +</body> +</html> |