diff --git a/.changeset/tired-views-turn.md b/.changeset/tired-views-turn.md new file mode 100644 index 0000000000..bbc7aab977 --- /dev/null +++ b/.changeset/tired-views-turn.md @@ -0,0 +1,5 @@ +--- +'livekit-client': patch +--- + +Ensure that sortPresets does NOT mutate values passed in via options into Room diff --git a/src/room/participant/publishUtils.test.ts b/src/room/participant/publishUtils.test.ts index 1580084e4e..e04c3f9f89 100644 --- a/src/room/participant/publishUtils.test.ts +++ b/src/room/participant/publishUtils.test.ts @@ -174,6 +174,12 @@ describe('customSimulcastLayers', () => { expect(sortedPresets[1].encoding.maxFramerate).toBe(15); expect(sortedPresets[2].encoding.maxFramerate).toBe(20); }); + it('does not mutate the passed-in array', () => { + const presets = [VideoPresets.h1440, VideoPresets.h360, VideoPresets.h1080, VideoPresets.h90]; + const original = [...presets]; + sortPresets(presets); + expect(presets).toEqual(original); + }); }); describe('screenShareSimulcastDefaults', () => { diff --git a/src/room/participant/publishUtils.ts b/src/room/participant/publishUtils.ts index 3d5d64862b..4e6c92ae9c 100644 --- a/src/room/participant/publishUtils.ts +++ b/src/room/participant/publishUtils.ts @@ -419,7 +419,10 @@ function encodingsFromPresets( /** @internal */ export function sortPresets(presets: Array | undefined) { if (!presets) return; - return presets.sort((a, b) => { + // Sort a copy so we don't mutate the caller's array in place. Mutating the + // passed-in simulcast layers can cause consumers that compare options by value + // (e.g. components-react's useLiveKitRoom) to detect a spurious change. + return presets.slice().sort((a, b) => { const { encoding: aEnc } = a; const { encoding: bEnc } = b;