@@ -2,6 +2,14 @@ import type { QwikSymbolEvent, QwikVisibleEvent } from './core/render/jsx/types/
2
2
import type { QContainerElement } from './core/container/container' ;
3
3
import type { QContext } from './core/state/context' ;
4
4
5
+ type qWindow = Window & {
6
+ qwikevents : {
7
+ events : Set < string > ;
8
+ roots : Set < Node > ;
9
+ push : ( ...e : ( string | ( EventTarget & ParentNode ) ) [ ] ) => void ;
10
+ } ;
11
+ } ;
12
+
5
13
/**
6
14
* Set up event listening for browser.
7
15
*
@@ -11,31 +19,14 @@ import type { QContext } from './core/state/context';
11
19
* @param doc - Document to use for setting up global listeners, and to determine all the browser
12
20
* supported events.
13
21
*/
14
- export const qwikLoader = (
15
- doc : Document & { __q_context__ ?: [ Element , Event , URL ] | 0 } ,
16
- hasInitialized ?: number
17
- ) => {
18
- const Q_CONTEXT = '__q_context__' ;
19
- type qWindow = Window & {
20
- qwikevents : {
21
- events : Set < string > ;
22
- roots : Set < Node > ;
23
- push : ( ...e : ( string | ( EventTarget & ParentNode ) ) [ ] ) => void ;
24
- } ;
25
- } ;
22
+ ( ( ) => {
23
+ const doc = document as Document & { __q_context__ ?: [ Element , Event , URL ] | 0 } ;
26
24
const win = window as unknown as qWindow ;
27
25
const events = new Set < string > ( ) ;
28
26
const roots = new Set < EventTarget & ParentNode > ( [ doc ] ) ;
29
27
30
- // Some shortenings for minification
31
- const replace = 'replace' ;
32
- const forEach = 'forEach' ;
33
- const target = 'target' ;
34
- const getAttribute = 'getAttribute' ;
35
- const isConnected = 'isConnected' ;
36
- const qvisible = 'qvisible' ;
37
- const Q_JSON = '_qwikjson_' ;
38
- const qContainerAttr = '[q\\:container]' ;
28
+ let hasInitialized : number ;
29
+
39
30
const nativeQuerySelectorAll = ( root : ParentNode , selector : string ) =>
40
31
Array . from ( root . querySelectorAll ( selector ) ) ;
41
32
const querySelectorAll = ( query : string ) => {
@@ -54,19 +45,19 @@ export const qwikLoader = (
54
45
const isPromise = ( promise : Promise < any > ) => promise && typeof promise . then === 'function' ;
55
46
56
47
const broadcast = ( infix : string , ev : Event , type = ev . type ) => {
57
- querySelectorAll ( '[on' + infix + '\\:' + type + ']' ) [ forEach ] ( ( el ) =>
48
+ querySelectorAll ( '[on' + infix + '\\:' + type + ']' ) . forEach ( ( el ) =>
58
49
dispatch ( el , infix , ev , type )
59
50
) ;
60
51
} ;
61
52
62
53
const resolveContainer = ( containerEl : QContainerElement ) => {
63
- if ( containerEl [ Q_JSON ] === undefined ) {
54
+ if ( containerEl . _qwikjson_ === undefined ) {
64
55
const parentJSON = containerEl === doc . documentElement ? doc . body : containerEl ;
65
56
let script = parentJSON . lastElementChild ;
66
57
while ( script ) {
67
- if ( script . tagName === 'SCRIPT' && script [ getAttribute ] ( 'type' ) === 'qwik/json' ) {
68
- containerEl [ Q_JSON ] = JSON . parse (
69
- script . textContent ! [ replace ] ( / \\ x 3 C ( \/ ? s c r i p t ) / gi, '<$1' )
58
+ if ( script . tagName === 'SCRIPT' && script . getAttribute ( 'type' ) === 'qwik/json' ) {
59
+ containerEl . _qwikjson_ = JSON . parse (
60
+ script . textContent ! . replace ( / \\ x 3 C ( \/ ? s c r i p t ) / gi, '<$1' )
70
61
) ;
71
62
break ;
72
63
}
@@ -93,12 +84,12 @@ export const qwikLoader = (
93
84
if ( element . hasAttribute ( 'stoppropagation:' + eventName ) ) {
94
85
ev . stopPropagation ( ) ;
95
86
}
96
- const ctx = element [ ' _qc_' ] ;
87
+ const ctx = element . _qc_ ;
97
88
const relevantListeners = ctx && ctx . li . filter ( ( li ) => li [ 0 ] === attrName ) ;
98
89
if ( relevantListeners && relevantListeners . length > 0 ) {
99
90
for ( const listener of relevantListeners ) {
100
91
// listener[1] holds the QRL
101
- const results = listener [ 1 ] . getFn ( [ element , ev ] , ( ) => element [ isConnected ] ) ( ev , element ) ;
92
+ const results = listener [ 1 ] . getFn ( [ element , ev ] , ( ) => element . isConnected ) ( ev , element ) ;
102
93
const cancelBubble = ev . cancelBubble ;
103
94
if ( isPromise ( results ) ) {
104
95
await results ;
@@ -110,17 +101,17 @@ export const qwikLoader = (
110
101
}
111
102
return ;
112
103
}
113
- const attrValue = element [ getAttribute ] ( attrName ) ;
104
+ const attrValue = element . getAttribute ( attrName ) ;
114
105
if ( attrValue ) {
115
- const container = element . closest ( qContainerAttr ) ! as QContainerElement ;
116
- const qBase = container [ getAttribute ] ( 'q:base' ) ! ;
117
- const qVersion = container [ getAttribute ] ( 'q:version' ) || 'unknown' ;
118
- const qManifest = container [ getAttribute ] ( 'q:manifest-hash' ) || 'dev' ;
106
+ const container = element . closest ( '[q\\:container]' ) ! as QContainerElement ;
107
+ const qBase = container . getAttribute ( 'q:base' ) ! ;
108
+ const qVersion = container . getAttribute ( 'q:version' ) || 'unknown' ;
109
+ const qManifest = container . getAttribute ( 'q:manifest-hash' ) || 'dev' ;
119
110
const base = new URL ( qBase , doc . baseURI ) ;
120
111
for ( const qrl of attrValue . split ( '\n' ) ) {
121
112
const url = new URL ( qrl , base ) ;
122
113
const href = url . href ;
123
- const symbol = url . hash [ replace ] ( / ^ # ? ( [ ^ ? [ | ] * ) .* $ / , '$1' ) || 'default' ;
114
+ const symbol = url . hash . replace ( / ^ # ? ( [ ^ ? [ | ] * ) .* $ / , '$1' ) || 'default' ;
124
115
const reqTime = performance . now ( ) ;
125
116
let handler : undefined | any ;
126
117
let importError : undefined | 'sync' | 'async' | 'no-symbol' ;
@@ -132,7 +123,7 @@ export const qwikLoader = (
132
123
handler = ( ( doc as any ) [ 'qFuncs_' + hash ] || [ ] ) [ Number . parseInt ( symbol ) ] ;
133
124
if ( ! handler ) {
134
125
importError = 'sync' ;
135
- error = new Error ( 'sync handler error for symbol: ' + symbol ) ;
126
+ error = new Error ( 'sym: ' + symbol ) ;
136
127
}
137
128
} else {
138
129
const uri = url . href . split ( '#' ) [ 0 ] ;
@@ -155,10 +146,10 @@ export const qwikLoader = (
155
146
// break out of the loop if handler is not found
156
147
break ;
157
148
}
158
- const previousCtx = doc [ Q_CONTEXT ] ;
159
- if ( element [ isConnected ] ) {
149
+ const previousCtx = doc . __q_context__ ;
150
+ if ( element . isConnected ) {
160
151
try {
161
- doc [ Q_CONTEXT ] = [ element , ev , url ] ;
152
+ doc . __q_context__ = [ element , ev , url ] ;
162
153
isSync || emitEvent < QwikSymbolEvent > ( 'qsymbol' , { ...eventData } ) ;
163
154
const results = handler ( ev , element ) ;
164
155
// only await if there is a promise returned
@@ -168,7 +159,7 @@ export const qwikLoader = (
168
159
} catch ( error ) {
169
160
emitEvent ( 'qerror' , { error, ...eventData } ) ;
170
161
} finally {
171
- doc [ Q_CONTEXT ] = previousCtx ;
162
+ doc . __q_context__ = previousCtx ;
172
163
}
173
164
}
174
165
}
@@ -179,7 +170,7 @@ export const qwikLoader = (
179
170
doc . dispatchEvent ( createEvent < T > ( eventName , detail ) ) ;
180
171
} ;
181
172
182
- const camelToKebab = ( str : string ) => str [ replace ] ( / ( [ A - Z ] ) / g, ( a ) => '-' + a . toLowerCase ( ) ) ;
173
+ const camelToKebab = ( str : string ) => str . replace ( / ( [ A - Z ] ) / g, ( a ) => '-' + a . toLowerCase ( ) ) ;
183
174
184
175
/**
185
176
* Event handler responsible for processing browser events.
@@ -192,10 +183,10 @@ export const qwikLoader = (
192
183
const processDocumentEvent = async ( ev : Event ) => {
193
184
// eslint-disable-next-line prefer-const
194
185
let type = camelToKebab ( ev . type ) ;
195
- let element = ev [ target ] as Element | null ;
186
+ let element = ev . target as Element | null ;
196
187
broadcast ( '-document' , ev , type ) ;
197
188
198
- while ( element && element [ getAttribute ] ) {
189
+ while ( element && element . getAttribute ) {
199
190
const results = dispatch ( element , '' , ev , type ) ;
200
191
let cancelBubble = ev . cancelBubble ;
201
192
if ( isPromise ( results ) ) {
@@ -223,17 +214,17 @@ export const qwikLoader = (
223
214
const riC = win . requestIdleCallback ?? win . setTimeout ;
224
215
riC . bind ( win ) ( ( ) => emitEvent ( 'qidle' ) ) ;
225
216
226
- if ( events . has ( qvisible ) ) {
227
- const results = querySelectorAll ( '[on\\:' + qvisible + ' ]') ;
217
+ if ( events . has ( ' qvisible' ) ) {
218
+ const results = querySelectorAll ( '[on\\:qvisible]' ) ;
228
219
const observer = new IntersectionObserver ( ( entries ) => {
229
220
for ( const entry of entries ) {
230
221
if ( entry . isIntersecting ) {
231
- observer . unobserve ( entry [ target ] ) ;
232
- dispatch ( entry [ target ] , '' , createEvent < QwikVisibleEvent > ( qvisible , entry ) ) ;
222
+ observer . unobserve ( entry . target ) ;
223
+ dispatch ( entry . target , '' , createEvent < QwikVisibleEvent > ( ' qvisible' , entry ) ) ;
233
224
}
234
225
}
235
226
} ) ;
236
- results [ forEach ] ( ( el ) => observer . observe ( el ) ) ;
227
+ results . forEach ( ( el ) => observer . observe ( el ) ) ;
237
228
}
238
229
}
239
230
} ;
@@ -270,9 +261,9 @@ export const qwikLoader = (
270
261
}
271
262
} ;
272
263
273
- if ( ! ( Q_CONTEXT in doc ) ) {
264
+ if ( ! ( '__q_context__' in doc ) ) {
274
265
// Mark qwik-loader presence but falsy
275
- doc [ Q_CONTEXT ] = 0 ;
266
+ doc . __q_context__ = 0 ;
276
267
const qwikevents = win . qwikevents ;
277
268
// If `qwikEvents` is an array, process it.
278
269
if ( Array . isArray ( qwikevents ) ) {
@@ -287,8 +278,4 @@ export const qwikLoader = (
287
278
addEventListener ( doc , 'readystatechange' , processReadyStateChange ) ;
288
279
processReadyStateChange ( ) ;
289
280
}
290
- } ;
291
-
292
- export interface QwikLoaderMessage extends MessageEvent {
293
- data : string [ ] ;
294
- }
281
+ } ) ( ) ;
0 commit comments