File tree 8 files changed +59
-40
lines changed
8 files changed +59
-40
lines changed Original file line number Diff line number Diff line change
1
+ ---
2
+ ' @sveltejs/kit ' : patch
3
+ ---
4
+
5
+ fix: properly decode base64 strings inside ` read `
Original file line number Diff line number Diff line change 1
1
import { read_implementation , manifest } from '__sveltekit/server' ;
2
2
import { base } from '__sveltekit/paths' ;
3
3
import { DEV } from 'esm-env' ;
4
+ import { b64_decode } from '../../utils.js' ;
4
5
5
6
/**
6
7
* Read the contents of an imported asset from the filesystem
@@ -30,7 +31,18 @@ export function read(asset) {
30
31
const [ prelude , data ] = asset . split ( ';' ) ;
31
32
const type = prelude . slice ( 5 ) || 'application/octet-stream' ;
32
33
33
- const decoded = data . startsWith ( 'base64,' ) ? atob ( data . slice ( 7 ) ) : decodeURIComponent ( data ) ;
34
+ if ( data . startsWith ( 'base64,' ) ) {
35
+ const decoded = b64_decode ( data . slice ( 7 ) ) ;
36
+
37
+ return new Response ( decoded , {
38
+ headers : {
39
+ 'Content-Length' : decoded . byteLength . toString ( ) ,
40
+ 'Content-Type' : type
41
+ }
42
+ } ) ;
43
+ }
44
+
45
+ const decoded = decodeURIComponent ( data ) ;
34
46
35
47
return new Response ( decoded , {
36
48
headers : {
Original file line number Diff line number Diff line change 1
1
import { BROWSER , DEV } from 'esm-env' ;
2
2
import { hash } from '../hash.js' ;
3
+ import { b64_decode } from '../utils.js' ;
3
4
4
5
let loading = 0 ;
5
6
@@ -77,22 +78,6 @@ if (DEV && BROWSER) {
77
78
78
79
const cache = new Map ( ) ;
79
80
80
- /**
81
- * @param {string } text
82
- * @returns {ArrayBufferLike }
83
- */
84
- function b64_decode ( text ) {
85
- const d = atob ( text ) ;
86
-
87
- const u8 = new Uint8Array ( d . length ) ;
88
-
89
- for ( let i = 0 ; i < d . length ; i ++ ) {
90
- u8 [ i ] = d . charCodeAt ( i ) ;
91
- }
92
-
93
- return u8 . buffer ;
94
- }
95
-
96
81
/**
97
82
* Should be called on the initial run of load functions that hydrate the page.
98
83
* Saves any requests with cache-control max-age to the cache.
Original file line number Diff line number Diff line change 1
1
import { DEV } from 'esm-env' ;
2
2
import { disable_search , make_trackable } from '../../../utils/url.js' ;
3
3
import { validate_depends } from '../../shared.js' ;
4
+ import { b64_encode } from '../../utils.js' ;
4
5
5
6
/**
6
7
* Calls the user's server `load` function.
@@ -207,25 +208,6 @@ export async function load_data({
207
208
return result ?? null ;
208
209
}
209
210
210
- /**
211
- * @param {ArrayBuffer } buffer
212
- * @returns {string }
213
- */
214
- function b64_encode ( buffer ) {
215
- if ( globalThis . Buffer ) {
216
- return Buffer . from ( buffer ) . toString ( 'base64' ) ;
217
- }
218
-
219
- const little_endian = new Uint8Array ( new Uint16Array ( [ 1 ] ) . buffer ) [ 0 ] > 0 ;
220
-
221
- // The Uint16Array(Uint8Array(...)) ensures the code points are padded with 0's
222
- return btoa (
223
- new TextDecoder ( little_endian ? 'utf-16le' : 'utf-16be' ) . decode (
224
- new Uint16Array ( new Uint8Array ( buffer ) )
225
- )
226
- ) ;
227
- }
228
-
229
211
/**
230
212
* @param {Pick<import('@sveltejs/kit').RequestEvent, 'fetch' | 'url' | 'request' | 'route'> } event
231
213
* @param {import('types').SSRState } state
Original file line number Diff line number Diff line change
1
+ /**
2
+ * @param {string } text
3
+ * @returns {ArrayBufferLike }
4
+ */
5
+ export function b64_decode ( text ) {
6
+ const d = atob ( text ) ;
7
+
8
+ const u8 = new Uint8Array ( d . length ) ;
9
+
10
+ for ( let i = 0 ; i < d . length ; i ++ ) {
11
+ u8 [ i ] = d . charCodeAt ( i ) ;
12
+ }
13
+
14
+ return u8 . buffer ;
15
+ }
16
+
17
+ /**
18
+ * @param {ArrayBuffer } buffer
19
+ * @returns {string }
20
+ */
21
+ export function b64_encode ( buffer ) {
22
+ if ( globalThis . Buffer ) {
23
+ return Buffer . from ( buffer ) . toString ( 'base64' ) ;
24
+ }
25
+
26
+ const little_endian = new Uint8Array ( new Uint16Array ( [ 1 ] ) . buffer ) [ 0 ] > 0 ;
27
+
28
+ // The Uint16Array(Uint8Array(...)) ensures the code points are padded with 0's
29
+ return btoa (
30
+ new TextDecoder ( little_endian ? 'utf-16le' : 'utf-16be' ) . decode (
31
+ new Uint16Array ( new Uint8Array ( buffer ) )
32
+ )
33
+ ) ;
34
+ }
Original file line number Diff line number Diff line change 1
- Imported without ?url
1
+ Imported without ?url 😎
Original file line number Diff line number Diff line change 1
- Imported with ?url
1
+ Imported with ?url 😎
Original file line number Diff line number Diff line change @@ -713,8 +713,9 @@ test.describe('$app/server', () => {
713
713
const auto = await page . textContent ( '[data-testid="auto"]' ) ;
714
714
const url = await page . textContent ( '[data-testid="url"]' ) ;
715
715
716
- expect ( auto . trim ( ) ) . toBe ( 'Imported without ?url' ) ;
717
- expect ( url . trim ( ) ) . toBe ( 'Imported with ?url' ) ;
716
+ // the emoji is there to check that base64 decoding works correctly
717
+ expect ( auto . trim ( ) ) . toBe ( 'Imported without ?url 😎' ) ;
718
+ expect ( url . trim ( ) ) . toBe ( 'Imported with ?url 😎' ) ;
718
719
} ) ;
719
720
} ) ;
720
721
You can’t perform that action at this time.
0 commit comments