@@ -46,9 +46,11 @@ export class SnapshotRenderer {
4646 private _snapshot : FrameSnapshot ;
4747 private _callId : string ;
4848 private _screencastFrames : PageEntry [ 'screencastFrames' ] ;
49+ private _readSha1 : ( sha1 : string ) => Promise < Blob | undefined > ;
4950
50- constructor ( htmlCache : LRUCache < SnapshotRenderer , string > , resources : ResourceSnapshot [ ] , snapshots : FrameSnapshot [ ] , screencastFrames : PageEntry [ 'screencastFrames' ] , index : number ) {
51+ constructor ( htmlCache : LRUCache < SnapshotRenderer , string > , readSha1 : ( sha1 : string ) => Promise < Blob | undefined > , resources : ResourceSnapshot [ ] , snapshots : FrameSnapshot [ ] , screencastFrames : PageEntry [ 'screencastFrames' ] , index : number ) {
5152 this . _htmlCache = htmlCache ;
53+ this . _readSha1 = readSha1 ;
5254 this . _resources = resources ;
5355 this . _snapshots = snapshots ;
5456 this . _index = index ;
@@ -74,9 +76,9 @@ export class SnapshotRenderer {
7476 return closestFrame ?. sha1 ;
7577 }
7678
77- render ( ) : RenderedFrameSnapshot {
79+ async render ( ) : Promise < RenderedFrameSnapshot > {
7880 const result : string [ ] = [ ] ;
79- const visit = ( n : NodeSnapshot , snapshotIndex : number , parentTag : string | undefined , parentAttrs : [ string , string ] [ ] | undefined ) => {
81+ const visit = async ( n : NodeSnapshot , snapshotIndex : number , parentTag : string | undefined , parentAttrs : [ string , string ] [ ] | undefined ) => {
8082 // Text node.
8183 if ( typeof n === 'string' ) {
8284 // Best-effort Electron support: rewrite custom protocol in url() links in stylesheets.
@@ -92,7 +94,12 @@ export class SnapshotRenderer {
9294 // Node reference.
9395 const referenceIndex = snapshotIndex - n [ 0 ] [ 0 ] ;
9496 if ( referenceIndex >= 0 && referenceIndex <= snapshotIndex ) {
95- const nodes = snapshotNodes ( this . _snapshots [ referenceIndex ] ) ;
97+ const refSnapshot = this . _snapshots [ referenceIndex ] ;
98+ let nodes : NodeSnapshot [ ] = ( refSnapshot as any ) . _nodes ;
99+ if ( ! nodes ) {
100+ nodes = snapshotNodes ( await this . _ensureHtml ( refSnapshot ) ) ;
101+ ( refSnapshot as any ) . _nodes = nodes ;
102+ }
96103 const nodeIndex = n [ 0 ] [ 1 ] ;
97104 if ( nodeIndex >= 0 && nodeIndex < nodes . length )
98105 return visit ( nodes [ nodeIndex ] , referenceIndex , parentTag , parentAttrs ) ;
@@ -134,7 +141,7 @@ export class SnapshotRenderer {
134141 }
135142 result . push ( '>' ) ;
136143 for ( const child of children )
137- visit ( child , snapshotIndex , nodeName , attrs ) ;
144+ await visit ( child , snapshotIndex , nodeName , attrs ) ;
138145 if ( ! autoClosing . has ( nodeName ) )
139146 result . push ( '</' , nodeName , '>' ) ;
140147 return ;
@@ -145,8 +152,8 @@ export class SnapshotRenderer {
145152 } ;
146153
147154 const snapshot = this . _snapshot ;
148- const html = this . _htmlCache . getOrCompute ( this , ( ) => {
149- visit ( snapshot . html , this . _index , undefined , undefined ) ;
155+ const html = await this . _htmlCache . getOrCompute ( this , async ( ) => {
156+ await visit ( await this . _ensureHtml ( snapshot ) , this . _index , undefined , undefined ) ;
150157 const prefix = snapshot . doctype ? `<!DOCTYPE ${ snapshot . doctype } >` : '' ;
151158 const html = prefix + [
152159 // Hide the document in order to prevent flickering. We will unhide once script has processed shadow.
@@ -159,6 +166,19 @@ export class SnapshotRenderer {
159166 return { html, pageId : snapshot . pageId , frameId : snapshot . frameId , index : this . _index } ;
160167 }
161168
169+ private async _ensureHtml ( snapshot : FrameSnapshot ) : Promise < NodeSnapshot > {
170+ if ( ! snapshot . html ) {
171+ try {
172+ const blob = await this . _readSha1 ( snapshot . sha1 ! ) ;
173+ const text = await blob ! . text ( ) ;
174+ snapshot . html = JSON . parse ( text ) ;
175+ } catch {
176+ snapshot . html = [ 'html' ] ;
177+ }
178+ }
179+ return snapshot . html ! ;
180+ }
181+
162182 resourceByUrl ( url : string , method : string ) : ResourceSnapshot | undefined {
163183 const snapshot = this . _snapshot ;
164184 let sameFrameResource : ResourceSnapshot | undefined ;
@@ -193,12 +213,12 @@ export class SnapshotRenderer {
193213 let result = sameFrameResource ?? otherFrameResource ;
194214 if ( result && method . toUpperCase ( ) === 'GET' ) {
195215 // Patch override if necessary.
196- let override = snapshot . resourceOverrides . find ( o => o . url === url ) ;
216+ let override = snapshot . resourceOverrides ? .find ( o => o . url === url ) ;
197217 if ( override ?. ref ) {
198218 // "ref" means use the same content as "ref" snapshots ago.
199219 const index = this . _index - override . ref ;
200220 if ( index >= 0 && index < this . _snapshots . length )
201- override = this . _snapshots [ index ] . resourceOverrides . find ( o => o . url === url ) ;
221+ override = this . _snapshots [ index ] . resourceOverrides ? .find ( o => o . url === url ) ;
202222 }
203223 if ( override ?. sha1 ) {
204224 result = {
@@ -220,23 +240,20 @@ export class SnapshotRenderer {
220240
221241const autoClosing = new Set ( [ 'AREA' , 'BASE' , 'BR' , 'COL' , 'COMMAND' , 'EMBED' , 'HR' , 'IMG' , 'INPUT' , 'KEYGEN' , 'LINK' , 'MENUITEM' , 'META' , 'PARAM' , 'SOURCE' , 'TRACK' , 'WBR' ] ) ;
222242
223- function snapshotNodes ( snapshot : FrameSnapshot ) : NodeSnapshot [ ] {
224- if ( ! ( snapshot as any ) . _nodes ) {
225- const nodes : NodeSnapshot [ ] = [ ] ;
226- const visit = ( n : NodeSnapshot ) => {
227- if ( typeof n === 'string' ) {
228- nodes . push ( n ) ;
229- } else if ( isNodeNameAttributesChildNodesSnapshot ( n ) ) {
230- const [ , , ...children ] = n ;
231- for ( const child of children )
232- visit ( child ) ;
233- nodes . push ( n ) ;
234- }
235- } ;
236- visit ( snapshot . html ) ;
237- ( snapshot as any ) . _nodes = nodes ;
238- }
239- return ( snapshot as any ) . _nodes ;
243+ function snapshotNodes ( html : NodeSnapshot ) : NodeSnapshot [ ] {
244+ const nodes : NodeSnapshot [ ] = [ ] ;
245+ const visit = ( n : NodeSnapshot ) => {
246+ if ( typeof n === 'string' ) {
247+ nodes . push ( n ) ;
248+ } else if ( isNodeNameAttributesChildNodesSnapshot ( n ) ) {
249+ const [ , , ...children ] = n ;
250+ for ( const child of children )
251+ visit ( child ) ;
252+ nodes . push ( n ) ;
253+ }
254+ } ;
255+ visit ( html ) ;
256+ return nodes ;
240257}
241258
242259type ViewportSize = { width : number , height : number } ;
0 commit comments