Skip to content

Commit e2717c7

Browse files
committed
Merge branch 'main' into lgarron/csp-trusted-types
2 parents 302221b + 538b108 commit e2717c7

File tree

1 file changed

+26
-15
lines changed

1 file changed

+26
-15
lines changed

src/index.ts

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
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

37
function 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

Comments
 (0)