@@ -62,6 +62,8 @@ export type LoadScriptOptions = {
6262// Promise cache for script sources
6363const SCRIPT_CACHE = new Map < string , Promise < HTMLScriptElement > > ( ) ;
6464
65+ const isBrowser = ( ) => typeof window !== "undefined" && typeof window . document !== "undefined" ;
66+
6567export const __resetScriptCache = ( ) => {
6668 SCRIPT_CACHE . clear ( ) ;
6769} ;
@@ -87,7 +89,7 @@ export const __resetScriptCache = () => {
8789export const loadScript = async (
8890 src : string ,
8991 options : LoadScriptOptions = { } ,
90- container : HTMLElement | null = document . head ,
92+ container ? : HTMLElement | null ,
9193) : Promise < HTMLScriptElement > => {
9294 const {
9395 id,
@@ -107,8 +109,19 @@ export const loadScript = async (
107109 ...attributes
108110 } = options ;
109111
110- // 1. Reject if no src provided
111- if ( ! src ) return Promise . reject ( new Error ( 'No "src" provided to loadScript' ) ) ;
112+ // 1. Reject if not in browser
113+ if ( ! isBrowser ( ) ) {
114+ const error = new Error ( "loadScript can only be used in the browser" ) ;
115+ error . name = "NotBrowserEnvironmentError" ;
116+ return Promise . reject ( error ) ;
117+ }
118+
119+ // 2. Reject if no src provided
120+ if ( ! src ) {
121+ const error = new Error ( 'No "src" provided to loadScript' ) ;
122+ error . name = "NoSrcProvidedError" ;
123+ return Promise . reject ( error ) ;
124+ }
112125
113126 // We strictly consider scripts with innerHTML as non-cacheable, since they are not guaranteed to be idempotent.
114127 // Note: We intentionally ignore Solid reactivity here, since this logic is static and not part of a reactive execution context.
@@ -121,25 +134,24 @@ export const loadScript = async (
121134 // the script from the DOM but we still have the promise for it cached.
122135 const existingTag = document . querySelector ( `script[src="${ src } "]` ) as HTMLScriptElement | null ;
123136
124- // 2 . Check if script already exists in cache
137+ // 3 . Check if script already exists in cache
125138 if ( SCRIPT_CACHE . has ( src ) ) {
126- // 2a . If script exists in cache and is still in the DOM, return the cached promise
139+ // 3a . If script exists in cache and is still in the DOM, return the cached promise
127140 if ( document . contains ( existingTag ) ) return SCRIPT_CACHE . get ( src ) ! ;
128141
129- // 2b . Script element was removed from DOM — evict from cache
142+ // 3b . Script element was removed from DOM — evict from cache
130143 SCRIPT_CACHE . delete ( src ) ;
131144 }
132145
133- // 3 . Check if script already exists (may have been added externally not via this hook)
146+ // 4 . Check if script already exists (may have been added externally not via this hook)
134147 if ( existingTag ) return Promise . resolve ( existingTag ) ;
135148 }
136149
137- // 4 . Create new script element
150+ // 5 . Create new script element
138151 const promise = new Promise < HTMLScriptElement > ( ( resolve , reject ) => {
139152 const script = document . createElement ( "script" ) ;
140153
141- const _container = container ?? document . head ;
142- _container . appendChild ( script ) ;
154+ ( container ?? document . head ) . appendChild ( script ) ;
143155
144156 script . src = src ;
145157 script . type = type ;
0 commit comments