Repository navigation
feat(html): load the later chunks of a sheet on demand - #1255
Merged
Merged
Conversation
`HtmlConfig::lazy_loading` now also writes each chunk of rows of a sheet after the first as a script of its own, `sheet<n>-chunks/<m>.js`. It applies to a read-only render, on the decode as it is. - `translate_sheet` splits into the layout of the rows (`SheetRows`), one row (`write_row`), and a chunk alone (`sheet_chunk`). - The page writes the rows of a loading chunk to nothing, because that is where it finds the chunk to end, and writes an empty table there. A request renders the rows again, with inline styles, because the head of the page has gone out by then. - The document service serves the scripts from the resources that `warmup` collects. `bring_offline` writes them beside the page. - `spreadsheet.js` builds its position map again after a chunk fills. It offers no sort while rows are still to load. With the default config, every sheet page is byte for byte what it was. The sheet of 500 K cells in `efficiency-big-1.ods` becomes a page of 370 KB and 122 scripts, and paints after 107 ms. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017QtawyvLP2SCnoBtnVfFed
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017QtawyvLP2SCnoBtnVfFed
The page writes the rows of a chunk that loads later to a null writer, to find where the chunk ends. Their resources went into a list that nothing read. So with `embed_images` off, or an external image, `bring_offline` did not write an image of such a row, and the chunk script linked a file that did not exist. The null writer now adds to the page's resources. Also: - All the chunks of a sheet share one copy of `HtmlConfig`. - Give every member of `SheetRows` a default value. A designated initializer that left them out failed -Werror with -Wmissing-designated-field-initializers. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YHNzLmVv1mFWfPitHASucN
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.
🤖 Generated with Claude Code
Refs #764.
Summary
This is level 3 of
docs/design/lazy-loading.mdfor sheets, the page side only, as decided. The decode stays as it is.HtmlConfig::lazy_loadingnow also writes each chunk of rows after the first as a script,sheet<n>-chunks/<m>.js. It applies to a read-only render withlazy_layout. The script callsodr.chunks.fill("<n>-<m>", html), and its html is the chunk'scols andtbody.translate_sheetsplits into three parts:SheetRows: the rows' layout, shared with the chunk resources.write_row: one row, which carries the running merge state in aRowCursor.sheet_chunk: a row range alone. A chunk starts where no merge is open, so a fresh cursor at its first row is right.--odr-chunk-height, which keeps the height of the rows.warmupcollects, andbring_offlinewrites them beside the page. No server change.viewport.jsraisesodr-chunk-filledafter a fill.spreadsheet.jsbuilds its position map again after a fill, keeps a chunk that is still to load, and offers no sort while rows are still to load, because a sort needs every row.spreadsheet.css,spreadsheet.jsandviewport.js.OpenDocument.core#1254, because that number was taken while I worked; they belong to this PR.Measured: the 500 K-cell sheet of
efficiency-big-1.odswithlazy_loading, fromfile://in headless Chrome, is a page of 370 KB (14.9 MB inline) and 122 scripts. It paints its first frame after 107 ms. After a scroll to the middle, rows 3996–4022 have loaded and line up with the ruler. The decode still peaks at 669 MB, which is the core question deferred in the design doc.Test
html.a_sheet_loads_its_later_chunks, a 300 × 20 csv:Review fixes
embed_imagesoff, or with an external image,bring_offlinedid not write the image, and the chunk script linked a file that did not exist. The null writer now adds to the page's resources.html.a_sheet_lists_the_images_of_a_chunk_that_loads_laterfails without the fix.SheetRows rows{.sheet = sheet}left members out of a designated initializer, which fails with-Wmissing-designated-field-initializers(Homebrew clang, as CI). Every member ofSheetRowsnow has a default value.HtmlConfig, where each chunk resource held a copy.-Werrorcheck and the local clang-tidy are clean ondocument_element.cpp.mainof their output repos.