Migrate scrabble module to Conductor#792
Conversation
scrabble exports four static word/letter lists rather than functions, so there's nothing for the usual exportedNames/@moduleMethod closure path to wrap. Exposes them via DataType.OPAQUE (opaque_make in an initialise() override) instead of DataType.ARRAY, since array_make has no bulk constructor and the full word list is 172,820 entries. Also drops the two full-array snapshot tests (scrabble_words/ scrabble_letters) - snapshotting 172,820 entries produced a multi-million-line .snap file that hung vitest's serializer. The existing index spot-checks already cover the full arrays; only the ~1,728-entry _tiny variants are snapshotted now. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request refactors the scrabble bundle to export a ScrabbleModulePlugin extending BaseModulePlugin instead of directly exporting the word lists. The word lists are now exposed as opaque values asynchronously during initialization. Additionally, snapshot tests for the full-sized word lists were removed to prevent test runner hangs, and a new test was added to verify the plugin's initialization behavior. Feedback is provided to optimize the initialization performance by executing the asynchronous opaque_make calls concurrently using Promise.all instead of sequentially.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
The four exports are independent, so awaiting them one at a time added needless latency. Addresses gemini-code-assist review comment on source-academy#792. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Description
Fixes #782
Migrates the
scrabblemodule to be Conductor-ready.scrabblehas no tab/visualization component, so this is scoped entirely tosrc/bundles/scrabble/.Unlike
repeat/binary_tree/midi, scrabble exports four static word/letter lists, not functions - there's nothing for the usualexportedNames/@moduleMethodclosure path to wrap.index.tsis now aBaseModulePluginsubclass that pushes all four exports in aninitialise()override, wrapped viaDataType.OPAQUE(opaque_make(value, true)) rather thanDataType.ARRAY.DataType.ARRAYwas the other option, butIDataHandler.array_makehas no bulk constructor - it fills with a singleinitvalue, so populating it requires onearray_setcall per element.scrabble_wordsis 172,820 entries;scrabble_letters(nested arrays of single-character strings) would be closer to 1.9M calls. No module anywhere in this migration has usedarray_makefor real data yet.opaque_makeis a single call regardless of the underlying value's size, same patternruneuses for its whole Rune object.functions.tsis untouched - it's pure data derivation (map/filter over the word list), nothing conductor-specific about it.Tradeoff worth flagging
Opaque values are only "manipulated by modules," not natively indexable by Source/Python code, so direct indexing like
scrabble_words[12]will no longer work once this ships. Happy to add accessor functions (e.g.scrabble_word_at) as a follow-up if that's needed, but held off since it wasn't clear that's wanted and it's easy to add later without touching the OPAQUE plumbing.Unrelated bug fixed along the way
The existing
scrabble_words matches snapshot/scrabble_letters matches snapshottests hung vitest indefinitely - confirmed via bisection againstrepeat's suite (clean, 1.2s) and this module's new test in isolation via.only(clean, 2.76s). Snapshotting a 172,820-entry array (and the nestedscrabble_letters) produced a 2.1M-line.snapfile that vitest's serializer choked on. Dropped those two tests and deleted the stale snapshot file; the existing index spot-checks (scrabble_words[12],scrabble_letters[100000]) already cover the full arrays cheaply, and the_tinyvariants (~1,728 entries) still get proper snapshots (regenerated, 2 written).Testing
yarn workspace @sourceacademy/bundle-scrabble run tsc- passesyarn workspace @sourceacademy/bundle-scrabble run lint- passesyarn workspace @sourceacademy/bundle-scrabble run test- 5/5 passing, against@sourceacademy/modules-testplugin'sTestDataHandleryarn workspace @sourceacademy/bundle-scrabble run build- producesbuild/bundles/scrabble.jsChecklist