diff --git a/lib/cea/cea608_memory.js b/lib/cea/cea608_memory.js index a30d8e8073..751141a39f 100644 --- a/lib/cea/cea608_memory.js +++ b/lib/cea/cea608_memory.js @@ -184,6 +184,10 @@ shaka.cea.Cea608Memory = class { * @param {number} count Count of rows to move. */ moveRows(dst, src, count) { + if (src < 0 || dst < 0) { + return; + } + if (dst >= src) { for (let i = count-1; i >= 0; i--) { this.rows_[dst + i] = this.rows_[src + i].map((e) => e); diff --git a/test/cea/cea608_memory_unit.js b/test/cea/cea608_memory_unit.js index 4105b0bd41..b7858c414c 100644 --- a/test/cea/cea608_memory_unit.js +++ b/test/cea/cea608_memory_unit.js @@ -295,5 +295,93 @@ describe('Cea608Memory', () => { const caption = memory.forceEmit(startTime, endTime); expect(caption).toEqual(expectedCaption); }); + + it('does not move rows if source row index is negative', () => { + const startTime = 1; + const endTime = 2; + const text = 'test'; + + // Add the text to the buffer, each character on separate rows. + // At this point, the memory looks like: + // [1]: t + // [2]: e + // [3]: s + // [4]: t + for (const c of text) { + memory.addChar(CharSet.BASIC_NORTH_AMERICAN, + c.charCodeAt(0)); + memory.setRow(memory.getRow() + 1); // increment row + } + + const srcRowIdx = -1; + const dstRowIdx = 2; + const rowsToMove = 3; + memory.moveRows(dstRowIdx, srcRowIdx, rowsToMove); + + // Expected text is 't\ne\ns\nt' + const topLevelCue = new shaka.text.Cue(startTime, endTime, ''); + topLevelCue.nestedCues = [ + CeaUtils.createDefaultCue(startTime, endTime, 't'), + CeaUtils.createLineBreakCue(startTime, endTime), + CeaUtils.createDefaultCue(startTime, endTime, 'e'), + CeaUtils.createLineBreakCue(startTime, endTime), + CeaUtils.createDefaultCue(startTime, endTime, 's'), + CeaUtils.createLineBreakCue(startTime, endTime), + CeaUtils.createDefaultCue(startTime, endTime, 't'), + ]; + + const expectedCaption = { + stream, + cue: topLevelCue, + }; + + // Force out the new memory. + const caption = memory.forceEmit(startTime, endTime); + expect(caption).toEqual(expectedCaption); + }); + + it('does not move rows if destination row index is negative', () => { + const startTime = 1; + const endTime = 2; + const text = 'test'; + + // Add the text to the buffer, each character on separate rows. + // At this point, the memory looks like: + // [1]: t + // [2]: e + // [3]: s + // [4]: t + for (const c of text) { + memory.addChar(CharSet.BASIC_NORTH_AMERICAN, + c.charCodeAt(0)); + memory.setRow(memory.getRow() + 1); // increment row + } + + const srcRowIdx = 1; + const dstRowIdx = -2; + const rowsToMove = 3; + memory.moveRows(dstRowIdx, srcRowIdx, rowsToMove); + + // Expected text is 't\ne\ns\nt' + const topLevelCue = new shaka.text.Cue(startTime, endTime, ''); + topLevelCue.nestedCues = [ + CeaUtils.createDefaultCue(startTime, endTime, 't'), + CeaUtils.createLineBreakCue(startTime, endTime), + CeaUtils.createDefaultCue(startTime, endTime, 'e'), + CeaUtils.createLineBreakCue(startTime, endTime), + CeaUtils.createDefaultCue(startTime, endTime, 's'), + CeaUtils.createLineBreakCue(startTime, endTime), + CeaUtils.createDefaultCue(startTime, endTime, 't'), + ]; + + const expectedCaption = { + stream, + cue: topLevelCue, + }; + + // Force out the new memory. + const caption = memory.forceEmit(startTime, endTime); + expect(caption).toEqual(expectedCaption); + }); }); });