@@ -96,7 +96,11 @@ interface MockCdnOptions {
9696 * When set, the manifest entry advertises a compressed artifact; the .zst
9797 * URL serves `payload` (null → 404, a CDN without the artifact yet).
9898 */
99- readonly compressed ?: { readonly payload : Buffer | null ; readonly checksum ?: string } ;
99+ readonly compressed ?: {
100+ readonly payload : Buffer | null ;
101+ readonly checksum ?: string ;
102+ readonly field ?: 'compressed' | 'zstd' ;
103+ } ;
100104}
101105
102106function mockCdnFetch ( options : MockCdnOptions ) : typeof fetch {
@@ -106,11 +110,13 @@ function mockCdnFetch(options: MockCdnOptions): typeof fetch {
106110 checksum : options . checksum ?? sha256Hex ( options . payload ) ,
107111 } ;
108112 if ( options . compressed !== undefined ) {
109- platformEntry [ 'compressed' ] = {
110- filename : COMPRESSED_FILENAME ,
111- checksum :
112- options . compressed . checksum ?? sha256Hex ( options . compressed . payload ?? Buffer . alloc ( 0 ) ) ,
113- } ;
113+ const checksum =
114+ options . compressed . checksum ?? sha256Hex ( options . compressed . payload ?? Buffer . alloc ( 0 ) ) ;
115+ if ( options . compressed . field === 'zstd' ) {
116+ platformEntry [ 'zstd' ] = { file : COMPRESSED_FILENAME , sha256 : checksum } ;
117+ } else {
118+ platformEntry [ 'compressed' ] = { filename : COMPRESSED_FILENAME , checksum } ;
119+ }
114120 }
115121 const manifestBody = JSON . stringify ( {
116122 version,
@@ -201,10 +207,10 @@ describe('stageNativeUpdate', () => {
201207 expect ( leftovers ) . toEqual ( [ ] ) ;
202208 } ) ;
203209
204- it ( ' downloads the compressed artifact and stages the decompressed binary', async ( ) => {
210+ it . each ( [ 'compressed' , 'zstd' ] as const ) ( ' downloads the %s artifact and stages the decompressed binary', async ( field ) => {
205211 const fetchImpl = mockCdnFetch ( {
206212 payload : PAYLOAD ,
207- compressed : { payload : zstdCompressSync ( PAYLOAD ) } ,
213+ compressed : { payload : zstdCompressSync ( PAYLOAD ) , field } ,
208214 } ) ;
209215 const result = await stageNativeUpdate ( {
210216 version : VERSION ,
@@ -232,11 +238,11 @@ describe('stageNativeUpdate', () => {
232238 expect ( leftovers ) . toEqual ( [ ] ) ;
233239 } ) ;
234240
235- it ( ' falls back to the bare binary when the compressed artifact is missing', async ( ) => {
241+ it . each ( [ 'compressed' , 'zstd' ] as const ) ( ' falls back to the bare binary when the compressed artifact is missing (%s) ', async ( field ) => {
236242 vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
237243 const fetchImpl = mockCdnFetch ( {
238244 payload : PAYLOAD ,
239- compressed : { payload : null } ,
245+ compressed : { payload : null , field } ,
240246 } ) ;
241247 const result = await stageNativeUpdate ( {
242248 version : VERSION ,
@@ -255,12 +261,12 @@ describe('stageNativeUpdate', () => {
255261 expect ( exeBytes . equals ( PAYLOAD ) ) . toBe ( true ) ;
256262 } ) ;
257263
258- it ( ' falls back to the bare binary when the compressed artifact fails verification', async ( ) => {
264+ it . each ( [ 'compressed' , 'zstd' ] as const ) ( ' falls back to the bare binary when the compressed artifact fails verification (%s) ', async ( field ) => {
259265 vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
260266 const fetchImpl = mockCdnFetch ( {
261267 payload : PAYLOAD ,
262268 // The .zst bytes do not hash to the advertised compressed checksum.
263- compressed : { payload : zstdCompressSync ( PAYLOAD ) , checksum : 'f' . repeat ( 64 ) } ,
269+ compressed : { payload : zstdCompressSync ( PAYLOAD ) , checksum : 'f' . repeat ( 64 ) , field } ,
264270 } ) ;
265271 const result = await stageNativeUpdate ( {
266272 version : VERSION ,
@@ -279,13 +285,13 @@ describe('stageNativeUpdate', () => {
279285 expect ( exeBytes . equals ( PAYLOAD ) ) . toBe ( true ) ;
280286 } ) ;
281287
282- it ( ' falls back to the bare binary when the decompressed content fails verification', async ( ) => {
288+ it . each ( [ 'compressed' , 'zstd' ] as const ) ( ' falls back to the bare binary when the decompressed content fails verification (%s) ', async ( field ) => {
283289 vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
284290 // The .zst verifies against its own checksum but inflates to something
285291 // other than the bare binary the manifest checksum covers.
286292 const fetchImpl = mockCdnFetch ( {
287293 payload : PAYLOAD ,
288- compressed : { payload : zstdCompressSync ( Buffer . from ( 'other-content' ) ) } ,
294+ compressed : { payload : zstdCompressSync ( Buffer . from ( 'other-content' ) ) , field } ,
289295 } ) ;
290296 const result = await stageNativeUpdate ( {
291297 version : VERSION ,
@@ -301,6 +307,47 @@ describe('stageNativeUpdate', () => {
301307 expect ( exeBytes . equals ( PAYLOAD ) ) . toBe ( true ) ;
302308 } ) ;
303309
310+ it ( 'prefers zstd when both manifest formats are present' , async ( ) => {
311+ const compressedPayload = zstdCompressSync ( PAYLOAD ) ;
312+ const fetchImpl = mockCdnFetch ( {
313+ payload : PAYLOAD ,
314+ compressed : { payload : compressedPayload , field : 'zstd' } ,
315+ } ) ;
316+ vi . mocked ( fetchImpl ) . mockResolvedValueOnce ( new Response ( JSON . stringify ( {
317+ version : VERSION ,
318+ platforms : {
319+ 'linux-x64' : {
320+ filename : BINARY_FILENAME ,
321+ checksum : sha256Hex ( PAYLOAD ) ,
322+ zstd : { file : COMPRESSED_FILENAME , sha256 : sha256Hex ( compressedPayload ) } ,
323+ compressed : { filename : 'legacy.zst' , checksum : 'a' . repeat ( 64 ) } ,
324+ } ,
325+ } ,
326+ } ) ) ) ;
327+
328+ const result = await stageNativeUpdate ( {
329+ version : VERSION ,
330+ exePath,
331+ platform : 'linux' ,
332+ arch : 'x64' ,
333+ fetchImpl,
334+ } ) ;
335+
336+ expect ( await readFile ( stagedExePath ( exePath , result . staged ) ) ) . toEqual ( PAYLOAD ) ;
337+ expect ( fetchImpl ) . toHaveBeenCalledWith (
338+ nativeBinaryUrl ( VERSION , COMPRESSED_FILENAME ) ,
339+ expect . anything ( ) ,
340+ ) ;
341+ expect ( fetchImpl ) . not . toHaveBeenCalledWith (
342+ nativeBinaryUrl ( VERSION , 'legacy.zst' ) ,
343+ expect . anything ( ) ,
344+ ) ;
345+ expect ( fetchImpl ) . not . toHaveBeenCalledWith (
346+ nativeBinaryUrl ( VERSION , BINARY_FILENAME ) ,
347+ expect . anything ( ) ,
348+ ) ;
349+ } ) ;
350+
304351 it ( 'marks the staged exe executable' , async ( ) => {
305352 const result = await stageNativeUpdate ( {
306353 version : VERSION ,
0 commit comments