summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.changeset/great-pants-chew.md5
-rw-r--r--packages/astro/src/runtime/server/response.ts14
-rw-r--r--packages/astro/test/fixtures/large-array/astro.config.mjs7
-rw-r--r--packages/astro/test/fixtures/large-array/package.json9
-rw-r--r--packages/astro/test/fixtures/large-array/src/components/Counter.jsx18
-rw-r--r--packages/astro/test/fixtures/large-array/src/pages/index.astro32
-rw-r--r--packages/astro/test/ssr-large-array.test.js35
-rw-r--r--pnpm-lock.yaml8
8 files changed, 125 insertions, 3 deletions
diff --git a/.changeset/great-pants-chew.md b/.changeset/great-pants-chew.md
new file mode 100644
index 000000000..189d09bd3
--- /dev/null
+++ b/.changeset/great-pants-chew.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes response.arrayBuffer() handling in large pages
diff --git a/packages/astro/src/runtime/server/response.ts b/packages/astro/src/runtime/server/response.ts
index 184d00a32..35be53442 100644
--- a/packages/astro/src/runtime/server/response.ts
+++ b/packages/astro/src/runtime/server/response.ts
@@ -34,11 +34,19 @@ function createResponseClass() {
async arrayBuffer(): Promise<ArrayBuffer> {
if (this.#isStream && isNodeJS) {
let body = this.#body as AsyncIterable<Uint8Array>;
- let chunks: number[] = [];
+ let chunks: Uint8Array[] = [];
+ let len = 0;
for await (let chunk of body) {
- chunks.push(...chunk);
+ chunks.push(chunk);
+ len += chunk.length;
}
- return Uint8Array.from(chunks);
+ let ab = new Uint8Array(len);
+ let offset = 0;
+ for(const chunk of chunks) {
+ ab.set(chunk, offset);
+ offset += chunk.length;
+ }
+ return ab;
}
return super.arrayBuffer();
}
diff --git a/packages/astro/test/fixtures/large-array/astro.config.mjs b/packages/astro/test/fixtures/large-array/astro.config.mjs
new file mode 100644
index 000000000..a6c39b853
--- /dev/null
+++ b/packages/astro/test/fixtures/large-array/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/test/fixtures/large-array/package.json b/packages/astro/test/fixtures/large-array/package.json
new file mode 100644
index 000000000..c8e001365
--- /dev/null
+++ b/packages/astro/test/fixtures/large-array/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/large-array-solid",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "@astrojs/solid-js": "workspace:*",
+ "astro": "workspace:*"
+ }
+}
diff --git a/packages/astro/test/fixtures/large-array/src/components/Counter.jsx b/packages/astro/test/fixtures/large-array/src/components/Counter.jsx
new file mode 100644
index 000000000..fb8706e03
--- /dev/null
+++ b/packages/astro/test/fixtures/large-array/src/components/Counter.jsx
@@ -0,0 +1,18 @@
+import { createSignal } from 'solid-js';
+
+export default function Counter({ children, largeProp }) {
+ const [count, setCount] = createSignal(0);
+ const add = () => setCount(count() + 1);
+ const subtract = () => setCount(count() - 1);
+
+ return (
+ <>
+ <div class="counter">
+ <button onClick={subtract}>-</button>
+ <pre>{count()}</pre>
+ <button onClick={add}>+</button>
+ </div>
+ <div class="counter-message">{children}</div>
+ </>
+ );
+}
diff --git a/packages/astro/test/fixtures/large-array/src/pages/index.astro b/packages/astro/test/fixtures/large-array/src/pages/index.astro
new file mode 100644
index 000000000..1a77ebed6
--- /dev/null
+++ b/packages/astro/test/fixtures/large-array/src/pages/index.astro
@@ -0,0 +1,32 @@
+---
+import Counter from '../components/Counter.jsx';
+const largeArray = []
+for (let i = 0; i < 600; i++) {
+ largeArray.push({ a: 'abc', b: 'abc', c: 'abc', d: 'abc', e: 'abc', foo: 'bar' })
+}
+---
+
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width" />
+ <link rel="icon" type="image/x-icon" href="/favicon.ico" />
+ <style>
+ html,
+ body {
+ font-family: system-ui;
+ margin: 0;
+ }
+ body {
+ padding: 2rem;
+ }
+ </style>
+ </head>
+ <body>
+ <main>
+ <Counter client:visible largeProp={largeArray}>
+ <h1>Hello, Solid!</h1>
+ </Counter>
+ </main>
+ </body>
+</html>
diff --git a/packages/astro/test/ssr-large-array.test.js b/packages/astro/test/ssr-large-array.test.js
new file mode 100644
index 000000000..64a82222b
--- /dev/null
+++ b/packages/astro/test/ssr-large-array.test.js
@@ -0,0 +1,35 @@
+import { expect } from 'chai';
+import * as cheerio from 'cheerio';
+import { loadFixture } from './test-utils.js';
+import testAdapter from './test-adapter.js';
+
+describe('SSR with Large Array and client rendering', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/large-array/',
+ experimental: {
+ ssr: true,
+ },
+ adapter: testAdapter(),
+ });
+ await fixture.build();
+ });
+
+ it('Using response.arrayBuffer() gets the right HTML', async () => {
+ const app = await fixture.loadTestAdapterApp();
+ const request = new Request('http://example.com/');
+ const response = await app.render(request);
+ const data = await response.arrayBuffer();
+ const html = new TextDecoder().decode(data);
+
+ const $ = cheerio.load(html);
+ expect($('head meta[name="viewport"]')).to.have.a.lengthOf(1);
+ expect($('head link[rel="icon"]')).to.have.a.lengthOf(1);
+ expect($('main')).to.have.a.lengthOf(1);
+ expect($('astro-island')).to.have.a.lengthOf(1);
+ expect($('h1').text()).to.equal('Hello, Solid!');
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 59c1ec6a9..c2f047436 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1538,6 +1538,14 @@ importers:
'@astrojs/vue': link:../../../../integrations/vue
astro: link:../../..
+ packages/astro/test/fixtures/large-array:
+ specifiers:
+ '@astrojs/solid-js': workspace:*
+ astro: workspace:*
+ dependencies:
+ '@astrojs/solid-js': link:../../../../integrations/solid
+ astro: link:../../..
+
packages/astro/test/fixtures/legacy-build:
specifiers:
'@astrojs/vue': workspace:*