Fixes
- A self-extracting archive opened from the filesystem reads itself when the browser allows it. The whole-file read every other scheme uses was skipped outright for
file://URLs, leaving only the embedded recovery payload — so an archive saved without one, which is the default, could not be opened from disk at all. Firefox performs the read and now opens those archives; Chromium and Safari refuse it and fall back to the previous behaviour unchanged - An iframe holding an SVG document keeps its content. Such a document has no
body, and the nesting check readbody.tagNamebefore anything else, so the frame threw and silently contributed nothing to the save - A sandboxed
srcdociframe is saved as it renders. The frame answers for itself, but its answer was discarded because the parent had already fallen back to re-parsing thesrcdocattribute, which no script has run against - Only the winning
@font-facerule is embedded when a page declares the same face more than once. Rules were de-duplicated by family and source together, so the same family, style and weight declared twice with different sources embedded both fonts, although the cascade only ever uses the last one. A source repeated inside a single rule is also embedded once, in the position its later declaration gives it - A
@font-facerule left with no usable source is removed, instead of being written out assrc:with nothing after it, which is an invalid declaration - Alternative font sources are narrowed by content type again. The font resources were not passed to the code that reads them, so a face whose sources carry no
format()kept every alternative in the archive instead of the best one - A BMP or a GIF87a served without a content type is stored with its real extension. Both signatures were wrong,
"NM"instead of"BM"and"GIF8;a"instead of"GIF87a", so neither format was ever recognised. The AVI signature was the one for WAV - With the mixed content option enabled, a resource at a
blob:URL is kept on an https page. The check compared the scheme againsthttps:and a blob URL starts withblob:, although it inherits the origin of the page that created it - An image whose
srcsetcould not be saved no longer keeps an emptysrcsetandsizespair. Both attributes are removed, so the browser falls back tosrcinstead of resolving an empty candidate list - A canvas displaying its captured drawing pins
background-attachment, so a page rule setting it tofixedno longer stretches or crops the image - A frame the save leaves empty no longer carries a
sandboxattribute that can no longer apply to anything - A resource fetched through the frame fallback carries the referrer of the page it belongs to
- A resource the page could not fetch itself falls back to the direct fetch again. The rejection carried no
Error, so the code deciding what to retry never recognised it; the listener waiting for the answer was also left behind on that path Imagekeeps a stable identity while a page is captured. The hook installed a getter that built a new function on every read, soImage === Imagewas false,instanceof Imagefailed for images the page had created, andImage.toString()revealed the wrapper.Element.prototype.getBoundingClientRect,CSS.paintWorklet.addModuleand the hookedIntersectionObserver,FontFace,CSSStyleSheetanddocument.fontsfunctions report their native name, arity and source text as well
Changes
- The budget for data appended after a self-extracting archive now defaults to 16361 bytes, down from 65535. Readers tolerate trailing bytes only as far back as their end-of-archive scan reaches, and that varies by an order of magnitude: 65557 bytes for Python
zipfile, 32768 for perlArchive::Zip, but 16383 for libarchive. The previous budget assumed the widest window, so archives that fit it were still unreadable by the narrowest. Payloads over the budget are relocated ahead of the archive, as they already were above the old limit