@@ -209,17 +209,48 @@ function preprocessPlayer(data, solvedCache) {
209209 }
210210 if ( ! probeBody ) probeBody = '/* no candidates found */' ;
211211
212- // --- Inject _df assignments at chain boundaries ---
213- // These capture functions before they get overwritten later in execution.
214- // Used as fallback when direct-by-name fails (player ran to completion).
212+ // --- Inject _df captures using multiple strategies ---
215213 var modified = data ;
216214 if ( candidates && candidates . length > 0 ) {
217- var injections = [ ] ;
215+ // Strategy 1: Comma injection inside var chains (most reliable)
216+ // Injects ,_dfN=funcName right after function's closing }
217+ // Only safe when string table delimiter is NOT } (brace matching works)
218+ var tableDelimiter = null ;
219+ var delimMatch = data . substring ( 0 , 2000 ) . match ( / \. s p l i t \( ( [ ' " ] ) ( .) ( \1) \) / ) ;
220+ if ( delimMatch ) tableDelimiter = delimMatch [ 2 ] ;
221+
222+ if ( tableDelimiter !== '}' ) {
223+ var commaInjections = [ ] ;
224+ for ( var i = 0 ; i < candidates . length ; i ++ ) {
225+ var c = candidates [ i ] ;
226+ var defIdx = modified . indexOf ( c . funcName + '=function(' ) ;
227+ if ( defIdx === - 1 ) continue ;
228+ var bodyStart = modified . indexOf ( '{' , defIdx ) ;
229+ if ( bodyStart === - 1 ) continue ;
230+ var depth = 0 , pos = bodyStart ;
231+ while ( pos < modified . length ) {
232+ if ( modified [ pos ] === '{' ) depth ++ ;
233+ else if ( modified [ pos ] === '}' ) { depth -- ; if ( depth === 0 ) break ; }
234+ pos ++ ;
235+ }
236+ if ( depth === 0 ) {
237+ commaInjections . push ( { pos : pos + 1 , code : ',_df' + i + '=' + c . funcName } ) ;
238+ }
239+ }
240+ commaInjections . sort ( function ( a , b ) { return b . pos - a . pos ; } ) ;
241+ for ( var j = 0 ; j < commaInjections . length ; j ++ ) {
242+ var inj = commaInjections [ j ] ;
243+ modified = modified . substring ( 0 , inj . pos ) + inj . code + modified . substring ( inj . pos ) ;
244+ }
245+ }
246+
247+ // Strategy 2: Chain-boundary injection (fallback for } delimiter players)
248+ // Injects _dfN=funcName; after ;\nfunction or ;\nvar boundaries
249+ var chainInjections = [ ] ;
218250 for ( var i = 0 ; i < candidates . length ; i ++ ) {
219251 var c = candidates [ i ] ;
220252 var defIdx = modified . indexOf ( c . funcName + '=function(' ) ;
221253 if ( defIdx === - 1 ) continue ;
222- // Find chain boundary: ;\n followed by function or var at line start
223254 var searchFrom = defIdx ;
224255 var chainEnd = - 1 ;
225256 while ( searchFrom < modified . length ) {
@@ -233,15 +264,14 @@ function preprocessPlayer(data, solvedCache) {
233264 searchFrom = nextSemiNl + 2 ;
234265 }
235266 if ( chainEnd !== - 1 ) {
236- injections . push ( { pos : chainEnd , code : '\ntry{_df' + i + '=' + c . funcName + ';}catch(e){}' } ) ;
267+ chainInjections . push ( { pos : chainEnd , code : '\ntry{_df' + i + '=' + c . funcName + ';}catch(e){}' } ) ;
237268 }
238269 }
239- // Merge and inject (descending order)
240270 var mergedByPos = { } ;
241- for ( var j = 0 ; j < injections . length ; j ++ ) {
242- var p = injections [ j ] . pos ;
271+ for ( var j = 0 ; j < chainInjections . length ; j ++ ) {
272+ var p = chainInjections [ j ] . pos ;
243273 if ( ! mergedByPos [ p ] ) mergedByPos [ p ] = '' ;
244- mergedByPos [ p ] += injections [ j ] . code ;
274+ mergedByPos [ p ] += chainInjections [ j ] . code ;
245275 }
246276 var sorted = Object . keys ( mergedByPos ) . map ( Number ) . sort ( function ( a , b ) { return b - a ; } ) ;
247277 for ( var j = 0 ; j < sorted . length ; j ++ ) {
0 commit comments