Skip to content

Commit 0dbb752

Browse files
committed
Merge branch 'feat/trail' of https://github.com/jycouet/kit into pr/jycouet/15027
2 parents 4d04c98 + 972ac24 commit 0dbb752

File tree

6 files changed

+75
-2
lines changed

6 files changed

+75
-2
lines changed

.changeset/thick-spiders-invite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: Correctly handle shared memory when decoding binary form data

packages/kit/src/core/adapt/builder.spec.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { existsSync, rmSync } from 'node:fs';
1+
import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync } from 'node:fs';
22
import { join, dirname } from 'node:path';
33
import { fileURLToPath } from 'node:url';
44
import { assert, expect, test } from 'vitest';
@@ -72,3 +72,40 @@ test('compress files', async () => {
7272
assert.ok(existsSync(target + '.br'));
7373
assert.ok(existsSync(target + '.gz'));
7474
});
75+
76+
test('instrument generates facade with posix paths', () => {
77+
const fixtureDir = join(__dirname, 'fixtures/instrument');
78+
const dest = join(__dirname, 'output');
79+
80+
rmSync(dest, { recursive: true, force: true });
81+
mkdirSync(join(dest, 'server'), { recursive: true });
82+
copyFileSync(join(fixtureDir, 'index.js'), join(dest, 'index.js'));
83+
copyFileSync(
84+
join(fixtureDir, 'server/instrumentation.server.js'),
85+
join(dest, 'server/instrumentation.server.js')
86+
);
87+
88+
const entrypoint = join(dest, 'index.js');
89+
const instrumentation = join(dest, 'server', 'instrumentation.server.js');
90+
91+
// @ts-expect-error - we don't need the whole config for this test
92+
const builder = create_builder({ route_data: [] });
93+
94+
builder.instrument({
95+
entrypoint,
96+
instrumentation,
97+
module: { exports: ['default'] }
98+
});
99+
100+
// Read the generated facade
101+
const facade = readFileSync(entrypoint, 'utf-8');
102+
103+
// Verify it uses forward slashes (not backslashes)
104+
// On Windows, path.relative() returns 'server\instrumentation.server.js'
105+
// The fix ensures this becomes 'server/instrumentation.server.js'
106+
expect(facade).toContain("import './server/instrumentation.server.js'");
107+
expect(facade).not.toContain('\\');
108+
109+
// Cleanup
110+
rmSync(dest, { recursive: true, force: true });
111+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default {};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {};

packages/kit/src/runtime/form-utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ export async function deserialize_binary_form(request) {
220220
`Could not deserialize binary form: got version ${header[0]}, expected version ${BINARY_FORM_VERSION}`
221221
);
222222
}
223-
const header_view = new DataView(header.buffer);
223+
const header_view = new DataView(header.buffer, header.byteOffset, header.byteLength);
224224
const data_length = header_view.getUint32(1, true);
225225
const file_offsets_length = header_view.getUint16(5, true);
226226

packages/kit/src/runtime/form-utils.spec.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,4 +213,33 @@ describe('binary form serializer', () => {
213213
expect(await world_slice.text()).toBe('World');
214214
expect(world_slice.type).toBe(file.type);
215215
});
216+
217+
// Regression test for https://github.com/sveltejs/kit/issues/14971
218+
test('DataView offset for shared memory', async () => {
219+
const { blob } = serialize_binary_form({ a: 1 }, {});
220+
const chunk = new Uint8Array(await blob.arrayBuffer());
221+
// Simulate a stream that has extra bytes at the start in the underlying buffer
222+
const stream = new ReadableStream({
223+
start(controller) {
224+
const offset_buffer = new Uint8Array(chunk.byteLength + 10);
225+
offset_buffer.fill(255);
226+
offset_buffer.set(chunk, 10);
227+
controller.enqueue(offset_buffer.subarray(10));
228+
}
229+
});
230+
231+
const res = await deserialize_binary_form(
232+
new Request('http://test', {
233+
method: 'POST',
234+
body: stream,
235+
// @ts-expect-error duplex required in node
236+
duplex: 'half',
237+
headers: {
238+
'Content-Type': BINARY_FORM_CONTENT_TYPE
239+
}
240+
})
241+
);
242+
243+
expect(res.data).toEqual({ a: 1 });
244+
});
216245
});

0 commit comments

Comments
 (0)