@@ -138,6 +138,11 @@ class DDGRuntimeChecks extends HTMLElement {
138
138
* @returns {Proxy }
139
139
*/
140
140
function constructProxy ( scope , outputs ) {
141
+ if ( Object . is ( scope ) ) {
142
+ // Should not happen, but just in case fail safely
143
+ console . error ( 'Runtime checks: Scope must be an object' , scope , outputs )
144
+ return scope
145
+ }
141
146
return new Proxy ( scope , {
142
147
get ( target , property , receiver ) {
143
148
const targetObj = target [ property ]
@@ -157,32 +162,55 @@ class DDGRuntimeChecks extends HTMLElement {
157
162
158
163
let prepend = ''
159
164
const aggregatedLookup = new Map ( )
165
+ let currentScope = null
160
166
/* Convert the config into a map of scopePath -> { key: value } */
161
167
for ( const [ key , value ] of Object . entries ( processedConfig ) ) {
162
168
const path = key . split ( '.' )
163
- const scopePath = path . slice ( 0 , - 1 ) . join ( '.' )
169
+
170
+ currentScope = aggregatedLookup
164
171
const pathOut = path [ path . length - 1 ]
165
- if ( aggregatedLookup . has ( scopePath ) ) {
166
- aggregatedLookup . get ( scopePath ) [ pathOut ] = value
167
- } else {
168
- aggregatedLookup . set ( scopePath , {
169
- [ pathOut ] : value
170
- } )
171
- }
172
+ // Traverse the path and create the nested objects
173
+ path . slice ( 0 , - 1 ) . forEach ( ( pathPart , index ) => {
174
+ if ( ! currentScope . has ( pathPart ) ) {
175
+ currentScope . set ( pathPart , new Map ( ) )
176
+ }
177
+ currentScope = currentScope . get ( pathPart )
178
+ } )
179
+ currentScope . set ( pathOut , value )
172
180
}
173
181
174
- for ( const [ key , value ] of aggregatedLookup ) {
175
- const path = key . split ( '.' )
176
- if ( path . length !== 1 ) {
177
- console . error ( 'Invalid config, currently only one layer depth is supported' )
178
- continue
182
+ /**
183
+ * Output scope variable definitions to arbitrary depth
184
+ */
185
+ function stringifyScope ( scope , scopePath ) {
186
+ let output = ''
187
+ for ( const [ key , value ] of scope ) {
188
+ const varOutName = [ ...scopePath , key ] . join ( '_' )
189
+ if ( value instanceof Map ) {
190
+ const keys = Array . from ( value . keys ( ) )
191
+ output += stringifyScope ( value , [ ...scopePath , key ] )
192
+ const proxyOut = keys . map ( ( keyName ) => `${ keyName } : ${ [ ...scopePath , key , keyName ] . join ( '_' ) } ` )
193
+ output += `
194
+ let ${ varOutName } = constructProxy(${ scopePath . join ( '.' ) } .${ key } , {${ proxyOut . join ( ', ' ) } });
195
+ `
196
+ // If we're at the top level, we need to add the window and globalThis variables (Eg: let navigator = parentScope_navigator)
197
+ if ( scopePath . length === 1 ) {
198
+ output += `
199
+ let ${ key } = ${ varOutName } ;
200
+ `
201
+ }
202
+ } else {
203
+ output += `
204
+ let ${ varOutName } = ${ JSON . stringify ( value ) } ;
205
+ `
206
+ }
179
207
}
180
- const scopeName = path [ 0 ]
181
- prepend += `
182
- let ${ scopeName } = constructProxy(parentScope.${ scopeName } , ${ JSON . stringify ( value ) } );
183
- `
208
+ return output
184
209
}
185
- const keysOut = [ ...aggregatedLookup . keys ( ) ] . join ( ',\n' )
210
+
211
+ prepend += stringifyScope ( aggregatedLookup , [ 'parentScope' ] )
212
+ // Stringify top level keys
213
+ const keysOut = [ ...aggregatedLookup . keys ( ) ] . map ( ( keyName ) => `${ keyName } : parentScope_${ keyName } ` ) . join ( ',\n' )
186
214
prepend += `
187
215
const window = constructProxy(parentScope, {
188
216
${ keysOut }
0 commit comments