1- export const isIframe = window !== window . top ;
2- export const isPopup = window . opener !== null ;
1+ const isIframe = window !== window . top ;
2+ const isPopup = window . opener !== null ;
33export const canLoadReactScan = ! isIframe && ! isPopup ;
44
5- export const IS_CLIENT = typeof window !== ' undefined' ;
5+ const IS_CLIENT = typeof window !== " undefined" ;
66
77export const isInternalUrl = ( url : string ) : boolean => {
88 if ( ! url ) return false ;
99
10- const allowedProtocols = [ ' http:' , ' https:' , ' file:' ] ;
10+ const allowedProtocols = [ " http:" , " https:" , " file:" ] ;
1111 return ! allowedProtocols . includes ( new URL ( url ) . protocol ) ;
1212} ;
1313
@@ -26,26 +26,42 @@ const ReactDetection = {
2626 limits : {
2727 MAX_DEPTH : 10 ,
2828 MAX_ELEMENTS : 30 ,
29- ELEMENTS_PER_LEVEL : 5
29+ ELEMENTS_PER_LEVEL : 5 ,
3030 } ,
3131 nonVisualTags : new Set ( [
3232 // Document level
33- 'HTML' , 'HEAD' , 'META' , 'TITLE' , 'BASE' ,
33+ "HTML" ,
34+ "HEAD" ,
35+ "META" ,
36+ "TITLE" ,
37+ "BASE" ,
3438 // Scripts and styles
35- 'SCRIPT' , 'STYLE' , 'LINK' , 'NOSCRIPT' ,
39+ "SCRIPT" ,
40+ "STYLE" ,
41+ "LINK" ,
42+ "NOSCRIPT" ,
3643 // Media and embeds
37- 'SOURCE' , 'TRACK' , 'EMBED' , 'OBJECT' , 'PARAM' ,
44+ "SOURCE" ,
45+ "TRACK" ,
46+ "EMBED" ,
47+ "OBJECT" ,
48+ "PARAM" ,
3849 // Special elements
39- 'TEMPLATE' , 'PORTAL' , 'SLOT' ,
50+ "TEMPLATE" ,
51+ "PORTAL" ,
52+ "SLOT" ,
4053 // Others
41- 'AREA' , 'XML' , 'DOCTYPE' , 'COMMENT'
54+ "AREA" ,
55+ "XML" ,
56+ "DOCTYPE" ,
57+ "COMMENT" ,
4258 ] ) ,
4359 reactMarkers : {
44- root : ' _reactRootContainer' ,
45- fiber : ' __reactFiber' ,
46- instance : ' __reactInternalInstance$' ,
47- container : ' __reactContainer$'
48- }
60+ root : " _reactRootContainer" ,
61+ fiber : " __reactFiber" ,
62+ instance : " __reactInternalInstance$" ,
63+ container : " __reactContainer$" ,
64+ } ,
4965} as const ;
5066
5167const childrenCache = new WeakMap < Element , Element [ ] > ( ) ;
@@ -81,8 +97,8 @@ export const hasReactFiber = (): boolean => {
8197 const rootContainer = elementWithRoot . _reactRootContainer ;
8298
8399 const hasLegacyRoot = rootContainer ?. _internalRoot ?. current ?. child != null ;
84- const hasContainerRoot = Object . keys ( elementWithRoot ) . some ( key =>
85- key . startsWith ( ReactDetection . reactMarkers . container )
100+ const hasContainerRoot = Object . keys ( elementWithRoot ) . some ( ( key ) =>
101+ key . startsWith ( ReactDetection . reactMarkers . container ) ,
86102 ) ;
87103
88104 return hasLegacyRoot || hasContainerRoot ;
@@ -133,59 +149,6 @@ export const saveLocalStorage = <T>(storageKey: string, state: T): void => {
133149 } catch { }
134150} ;
135151
136- export const removeLocalStorage = ( storageKey : string ) : void => {
137- if ( ! IS_CLIENT ) return ;
138-
139- try {
140- window . localStorage . removeItem ( storageKey ) ;
141- } catch { }
142- } ;
143-
144- export const debounce = < T extends ( enabled : boolean | null ) => Promise < void > > (
145- fn : T ,
146- wait : number ,
147- options : { leading ?: boolean ; trailing ?: boolean } = { } ,
148- ) => {
149- let timeoutId : number | undefined ;
150- let lastArg : boolean | null | undefined ;
151- let isLeadingInvoked = false ;
152-
153- const debounced = ( enabled : boolean | null ) => {
154- lastArg = enabled ;
155-
156- if ( options . leading && ! isLeadingInvoked ) {
157- isLeadingInvoked = true ;
158- fn ( enabled ) ;
159- return ;
160- }
161-
162- if ( timeoutId !== undefined ) {
163- clearTimeout ( timeoutId ) ;
164- }
165-
166- if ( options . trailing !== false ) {
167- timeoutId = setTimeout ( ( ) => {
168- isLeadingInvoked = false ;
169- timeoutId = undefined ;
170- if ( lastArg !== undefined ) {
171- fn ( lastArg ) ;
172- }
173- } , wait ) ;
174- }
175- } ;
176-
177- debounced . cancel = ( ) => {
178- if ( timeoutId !== undefined ) {
179- clearTimeout ( timeoutId ) ;
180- timeoutId = undefined ;
181- isLeadingInvoked = false ;
182- lastArg = undefined ;
183- }
184- } ;
185-
186- return debounced ;
187- } ;
188-
189152type EventCallback < T = unknown > = ( data : T ) => void ;
190153const eventBus = new Map < string , Set < EventCallback > > ( ) ;
191154
@@ -220,14 +183,16 @@ export const sleep = (ms: number): Promise<void> => {
220183 return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
221184} ;
222185
223- export const storageGetItem = async < T > (
224- storageKey : string ,
225- key : string ,
226- ) : Promise < T | null > => {
186+ const isStorageRecord = ( value : unknown ) : value is Record < string , unknown > =>
187+ typeof value === "object" && value !== null ;
188+
189+ export const storageGetItem = async < T > ( storageKey : string , key : string ) : Promise < T | null > => {
227190 try {
228191 const result = await chrome . storage . local . get ( storageKey ) ;
229192 const data = result [ storageKey ] ;
230- return data ?. [ key ] ?? null ;
193+ if ( ! isStorageRecord ( data ) ) return null ;
194+ const value = data [ key ] ;
195+ return value === undefined ? null : ( value as T ) ;
231196 } catch {
232197 return null ;
233198 }
@@ -240,9 +205,11 @@ export const storageSetItem = async <T>(
240205) : Promise < void > => {
241206 try {
242207 const result = await chrome . storage . local . get ( storageKey ) ;
243- const data = result [ storageKey ] || { } ;
244- data [ key ] = value ;
245- await chrome . storage . local . set ( { [ storageKey ] : data } ) ;
246- } catch {
247- }
208+ const data = result [ storageKey ] ;
209+ const updatedData = {
210+ ...( isStorageRecord ( data ) ? data : { } ) ,
211+ [ key ] : value ,
212+ } ;
213+ await chrome . storage . local . set ( { [ storageKey ] : updatedData } ) ;
214+ } catch { }
248215} ;
0 commit comments