1- const privateData = new WeakMap ( )
1+ interface CachedData {
2+ src : string
3+ data : Promise < string | CSPTrustedHTMLToStringable | Error >
4+ }
5+ const privateData = new WeakMap < IncludeFragmentElement , CachedData > ( )
26
37function isWildcard ( accept : string | null ) {
48 return accept && ! ! accept . split ( ',' ) . find ( x => x . match ( / ^ \s * \* \/ \* / ) )
@@ -63,8 +67,8 @@ export default class IncludeFragmentElement extends HTMLElement {
6367 }
6468
6569 // TODO: Should this return a TrustedHTML if available, or always a string?
66- get data ( ) : Promise < string > {
67- return this . #getStringData ( )
70+ get data ( ) : Promise < string | Error > {
71+ return this . #getStringOrErrorData ( )
6872 }
6973
7074 #busy = false
@@ -115,9 +119,8 @@ export default class IncludeFragmentElement extends HTMLElement {
115119 } )
116120 }
117121
118- // TODO: Should this return `this.#getData()` directly?
119- load ( ) : Promise < string > {
120- return this . #getStringData( )
122+ load ( ) : Promise < string | Error > {
123+ return this . #getStringOrErrorData( )
121124 }
122125
123126 fetch ( request : RequestInfo ) : Promise < Response > {
@@ -152,15 +155,18 @@ export default class IncludeFragmentElement extends HTMLElement {
152155 this . #busy = true
153156 this . #observer. unobserve ( this )
154157 try {
155- const html = await this . #getData( )
158+ const data = await this . #getData( )
159+ if ( data instanceof Error ) {
160+ throw data
161+ }
156162 // Until TypeScript is natively compatible with CSP trusted types, we
157163 // have to treat this as a string here.
158164 // https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1246
159- const htmlTreatedAsString = html as string
165+ const dataTreatedAsString = data as string
160166
161167 const template = document . createElement ( 'template' )
162168 // eslint-disable-next-line github/no-inner-html
163- template . innerHTML = htmlTreatedAsString
169+ template . innerHTML = dataTreatedAsString
164170 const fragment = document . importNode ( template . content , true )
165171 const canceled = ! this . dispatchEvent (
166172 new CustomEvent ( 'include-fragment-replace' , { cancelable : true , detail : { fragment} } )
@@ -173,12 +179,13 @@ export default class IncludeFragmentElement extends HTMLElement {
173179 }
174180 }
175181
176- #getData( ) : Promise < string | CSPTrustedHTMLToStringable > {
182+ async #getData( ) : Promise < string | CSPTrustedHTMLToStringable | Error > {
177183 const src = this . src
178- let data = privateData . get ( this )
179- if ( data && data . src === src ) {
180- return data . data
184+ const cachedData = privateData . get ( this )
185+ if ( cachedData && cachedData . src === src ) {
186+ return cachedData . data
181187 } else {
188+ let data : Promise < string | CSPTrustedHTMLToStringable | Error >
182189 if ( src ) {
183190 data = this . #fetchDataWithEvents( )
184191 } else {
@@ -189,8 +196,12 @@ export default class IncludeFragmentElement extends HTMLElement {
189196 }
190197 }
191198
192- async #getStringData( ) : Promise < string > {
193- return ( await this . #getData( ) ) . toString ( )
199+ async #getStringOrErrorData( ) : Promise < string | Error > {
200+ const data = await this . #getData( )
201+ if ( data instanceof Error ) {
202+ return data
203+ }
204+ return data . toString ( )
194205 }
195206
196207 // Functional stand in for the W3 spec "queue a task" paradigm
0 commit comments