Repository navigation
Three small fixes: EventEmitter listeners, the MP4 append queue, Panopto's label - #578
Merged
Andrews54757 merged 3 commits intoOct 9, 2026
Merged
Conversation
emit() walked the listener list, and the emitter its context list, while they changed under it. A once() listener, or a handler that destroys its own context (VideoAnalyzer, AudioAnalyzer and PreviewFrameExtractor do on the player's events), removed itself at the place the walk was on; the next one moved into that place and never heard that event. Both walks now go over a copy, as Node's EventEmitter does. Tested with vitest against this module: two once() listeners on one event, and a context that destroys itself in its handler; before the change the second listener and the second context were skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
player_source_accelpanopto was only in en, so the other 15 locales showed
the English label in the Sources browser's mode menu, every build printed
"Missing keys" for each of them, and combined-locales.json did not have the
key. Each locale's label follows its own "Accelerated Vimeo" with the name
swapped. Also fixes the German Vimeo label's typo ("Beschleunigtest" ->
"Beschleunigtes"). `node localescript.mjs` reports no missing keys now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SourceBufferWrapper runs MP4Player's appends and removals one at a time, each after the previous updateend. A remove() that threw (InvalidStateError once the MediaSource closed, say) still set `updating`: no update had started, so no updateend came, and every later append and removal stayed queued for good. An appendBuffer() that threw (QuotaExceededError) left the operation at the head of the queue, so every later call ran it again and was rejected with its error. A throw from either call now rejects that operation, drops it and runs the next one. Nothing changes when nothing throws. Tested with vitest against a stand-in SourceBuffer: a remove that throws, an append that throws, and operations queued behind two throws in a row; all three failed before. Accelerated MP4 playback and a seek far ahead play the same as before in Firefox 157. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three independent fixes, one commit each. Each commit applies to
mainon its own.1. EventEmitter: an event reaches every listener when one removes itself
emit()walks the listener list withevery()while listeners change it. The emitter also walks its context list that way. Aonce()listener removes itself at the index the walk is on, so the next listener moves into that index and is skipped. A handler that destroys its own context does the same to the next context. VideoAnalyzer, AudioAnalyzer and PreviewFrameExtractor destroy their contexts like this on the player's events.Both walks now go over a copy, as Node's EventEmitter does. Two consequences:
emit()is not called for that event. That was already true, becauseevery()stops at the length it started with.emit()still hears that event. This matches Node.2. MP4: a SourceBuffer call that throws no longer stops the queue
SourceBufferWrapperruns MP4Player's appends and removals one at a time, each after the previousupdateend. There were two problems:remove()that threw (InvalidStateErroronce the MediaSource closed, for example) still setupdating. No update had started, so noupdateendcame, and every later append and removal stayed queued for good.appendBuffer()that threw (QuotaExceededError) left the operation at the head of the queue. Every later call ran it again and was rejected with its error.A throw from either call now rejects that operation, drops it and runs the next one. Nothing changes when nothing throws.
3. Locales: translate "Accelerated Panopto"
player_source_accelpanoptoexists only inen. The other 15 locales show the English label in the Sources browser's mode menu, the build prints "Missing keys" for each of them, andcombined-locales.jsonlacks the key. Each locale's label now follows its own "Accelerated Vimeo", with the name swapped. This commit also fixes a typo in the German Vimeo label ("Beschleunigtest" → "Beschleunigtes").Verification
Commits 1 and 2: the real modules from
mainand from this branch, run in Node. SourceBufferWrapper gets a stand-in SourceBuffer that throws on request.mainonce()listeners on one eventremove()throws, then an append is queuednpm ci+npm run build: all three targets build, and the build prints no "Missing keys".eslinton the changed files: no problems.🤖 Generated with Claude Code