@@ -21,10 +21,9 @@ const observer = new IntersectionObserver(entries => {
21
21
} )
22
22
23
23
24
- function fire ( name : string , target : Element ) {
25
- setTimeout ( function ( ) {
26
- target . dispatchEvent ( new Event ( name ) )
27
- } , 0 )
24
+ // Functional stand in for the W3 spec "queue a task" paradigm
25
+ function task ( ) : Promise < void > {
26
+ return new Promise ( resolve => setTimeout ( resolve , 0 ) )
28
27
}
29
28
30
29
async function handleData ( el : IncludeFragmentElement ) {
@@ -148,9 +147,12 @@ export default class IncludeFragmentElement extends HTMLElement {
148
147
149
148
load ( ) : Promise < string > {
150
149
observer . unobserve ( this )
151
- return Promise . resolve ( )
150
+ // We mimic the same event order as <img>, including the spec
151
+ // which states events must be dispatched after "queue a task".
152
+ // https://www.w3.org/TR/html52/semantics-embedded-content.html#the-img-element
153
+ return task ( )
152
154
. then ( ( ) => {
153
- fire ( 'loadstart' , this )
155
+ this . dispatchEvent ( new Event ( 'loadstart' ) )
154
156
return this . fetch ( this . request ( ) )
155
157
} )
156
158
. then ( response => {
@@ -161,21 +163,27 @@ export default class IncludeFragmentElement extends HTMLElement {
161
163
if ( ! isWildcard ( this . accept ) && ( ! ct || ! ct . includes ( this . accept ? this . accept : 'text/html' ) ) ) {
162
164
throw new Error ( `Failed to load resource: expected ${ this . accept || 'text/html' } but was ${ ct } ` )
163
165
}
164
- return response
166
+ return response . text ( )
167
+ } )
168
+ . then ( data => {
169
+ // Dispatch `load` and `loadend` async to allow
170
+ // the `load()` promise to resolve _before_ these
171
+ // events are fired.
172
+ task ( ) . then ( ( ) => {
173
+ this . dispatchEvent ( new Event ( 'load' ) )
174
+ this . dispatchEvent ( new Event ( 'loadend' ) )
175
+ } )
176
+ return data
177
+ } , error => {
178
+ // Dispatch `error` and `loadend` async to allow
179
+ // the `load()` promise to resolve _before_ these
180
+ // events are fired.
181
+ task ( ) . then ( ( ) => {
182
+ this . dispatchEvent ( new Event ( 'error' ) )
183
+ this . dispatchEvent ( new Event ( 'loadend' ) )
184
+ } )
185
+ throw error
165
186
} )
166
- . then ( response => response . text ( ) )
167
- . then (
168
- data => {
169
- fire ( 'load' , this )
170
- fire ( 'loadend' , this )
171
- return data
172
- } ,
173
- error => {
174
- fire ( 'error' , this )
175
- fire ( 'loadend' , this )
176
- throw error
177
- }
178
- )
179
187
}
180
188
181
189
fetch ( request : RequestInfo ) : Promise < Response > {
0 commit comments