@@ -17,6 +17,7 @@ import (
1717 "encoding/json"
1818 "fmt"
1919 "math"
20+ "math/rand"
2021 "reflect"
2122 "runtime/debug"
2223 "sync"
@@ -216,7 +217,9 @@ func (s *Session) Initialize(ctx context.Context, taintTemplate, taintConfig str
216217 runActionsFunc : s .RunActions ,
217218 }
218219 }
219- s .interactor = NewInteractor (s .logger .Named ("interactor_fallback" ), nil , stabilizeFn , s , s .ctx )
220+ // Use non-deterministic RNG for fallback
221+ rng := rand .New (rand .NewSource (time .Now ().UnixNano ()))
222+ s .interactor = NewInteractor (s .logger .Named ("interactor_fallback" ), rng , nil , stabilizeFn , s , s .ctx )
220223 }
221224 }
222225 } else {
@@ -495,8 +498,12 @@ func (s *Session) initializeControllers() error {
495498 // in stabilize() addresses race conditions related to delayed JS execution.
496499 return s .stabilize (stabCtx , 500 * time .Millisecond )
497500 }
501+
502+ // FIX: Initialize RNG for production use (non-deterministic)
503+ rng := rand .New (rand .NewSource (time .Now ().UnixNano ()))
504+
498505 // Pass 's' (as ActionExecutor) and s.ctx to NewInteractor.
499- s .interactor = NewInteractor (s .logger .Named ("interactor" ), s .humanoid , stabilizeFn , s , s .ctx )
506+ s .interactor = NewInteractor (s .logger .Named ("interactor" ), rng , s .humanoid , stabilizeFn , s , s .ctx )
500507 s .logger .Debug ("Interactor initialized." )
501508 return nil
502509}
@@ -1241,7 +1248,33 @@ func (s *Session) convertJSToGoType(jsArg interface{}, goType reflect.Type) (ref
12411248 return reflect.Value {}, fmt .Errorf ("JS argument was map-like but not map[string]interface{}" )
12421249 }
12431250
1244- // TODO: Add case for []interface{} from JS to Go slice/array if needed.
1251+ // Handle Slice/Array conversion (JS Array -> Go Slice/Array)
1252+ if (goType .Kind () == reflect .Slice || goType .Kind () == reflect .Array ) && jsType .Kind () == reflect .Slice {
1253+ s .logger .Debug ("Attempting slice/array conversion." , zap .String ("from" , jsType .String ()), zap .String ("to" , goType .String ()))
1254+ jsLength := jsVal .Len ()
1255+ var newCollection reflect.Value
1256+
1257+ if goType .Kind () == reflect .Slice {
1258+ newCollection = reflect .MakeSlice (goType , jsLength , jsLength )
1259+ } else { // It's an array
1260+ goLength := goType .Len ()
1261+ if jsLength != goLength {
1262+ return reflect.Value {}, fmt .Errorf ("cannot convert JS array of length %d to Go array of fixed size %d" , jsLength , goLength )
1263+ }
1264+ newCollection = reflect .New (goType ).Elem ()
1265+ }
1266+
1267+ elemType := goType .Elem ()
1268+ for i := 0 ; i < jsLength ; i ++ {
1269+ elemVal := jsVal .Index (i ).Interface ()
1270+ convElem , err := s .convertJSToGoType (elemVal , elemType )
1271+ if err != nil {
1272+ return reflect.Value {}, fmt .Errorf ("failed to convert collection element at index %d: %w" , i , err )
1273+ }
1274+ newCollection .Index (i ).Set (convElem )
1275+ }
1276+ return newCollection , nil
1277+ }
12451278
12461279 return reflect.Value {}, fmt .Errorf ("incompatible type: cannot convert JS type %s to Go type %s" , jsType .String (), goType .String ())
12471280}
@@ -1273,18 +1306,34 @@ func (s *Session) InjectScriptPersistently(ctx context.Context, script string) e
12731306//
12741307// Updated signature to match schemas.SessionContext interface (InvalidIfaceAssign error).
12751308func (s * Session ) ExecuteScript (ctx context.Context , script string , args []interface {}) (json.RawMessage , error ) {
1276- // Chromedp's Evaluate does not directly support passing arguments easily.
1277- if len (args ) > 0 {
1278- // Log a warning as implementing robust argument passing requires complex IIFE wrapping and JSON handling.
1279- s .logger .Warn ("Session.ExecuteScript: passing arguments via 'args' parameter is not fully supported with current chromedp backend implementation." )
1280- }
1281-
12821309 var res json.RawMessage
1310+
12831311 // Use RunActions for context safety.
1284- err := s .RunActions (ctx , chromedp .Evaluate (script , & res , func (p * runtime.EvaluateParams ) * runtime.EvaluateParams {
1285- // Ensure promises are awaited and actual value is returned, suppress exceptions in JS
1286- return p .WithAwaitPromise (true ).WithReturnByValue (true ).WithSilent (true )
1287- }))
1312+ // Session delegates to runActions directly, no internal timeout logic like cdp_executor here (relies on ctx).
1313+ var err error
1314+ if len (args ) > 0 {
1315+ // FIX: Use Evaluate with JSON injection instead of CallFunctionOn.
1316+ // CallFunctionOn requires an ObjectId (target), which we don't have here.
1317+ // We marshal the args to JSON and apply them to the function.
1318+ jsonArgs , marshalErr := json .Marshal (args )
1319+ if marshalErr != nil {
1320+ return nil , fmt .Errorf ("failed to marshal args for script execution: %w" , marshalErr )
1321+ }
1322+
1323+ // Construct a script that executes the user's function with the provided arguments.
1324+ // We use .apply(null, args) to pass the array of arguments as individual parameters.
1325+ // The user's script is wrapped in a function to ensure 'arguments' is available if they use it.
1326+ wrappedScript := fmt .Sprintf (`(function() { %s }).apply(null, %s)` , script , string (jsonArgs ))
1327+
1328+ err = s .RunActions (ctx , chromedp .Evaluate (wrappedScript , & res , func (p * runtime.EvaluateParams ) * runtime.EvaluateParams {
1329+ return p .WithAwaitPromise (true ).WithReturnByValue (true ).WithSilent (true )
1330+ }))
1331+ } else {
1332+ err = s .RunActions (ctx , chromedp .Evaluate (script , & res , func (p * runtime.EvaluateParams ) * runtime.EvaluateParams {
1333+ // Ensure promises are awaited and actual value is returned, suppress exceptions in JS
1334+ return p .WithAwaitPromise (true ).WithReturnByValue (true ).WithSilent (true )
1335+ }))
1336+ }
12881337
12891338 return res , err
12901339}
0 commit comments