Repository navigation
JavaScript Executors
In modern web automation, standard Selenium commands are often not enough to handle complex tasks like precise visibility checks, finding random clickable points, or analyzing the viewport.
The javascript executor package provides a unified layer for running pre-written, highly optimized JavaScript snippets in the browser, regardless of whether you are using a synchronous or asynchronous (Trio) driver.
The package is built using an abstraction layer to ensure that the developer interface remains identical across architectures.
-
AbstractJSExecutor: Defines the required methods (the "contract") for all JS executors. -
UnifiedJSExecutor: Contains the internal implementation logic. It bridges Python calls to actual JavaScript execution. -
Implementation Classes:
-
sync.JSExecutor: Executes scripts immediately. -
trio_threads.JSExecutor: Executes scripts in worker threads to prevent blocking the async loop. -
trio_bidi.JSExecutor: Executes viaTrioBiDiMixin, routing calls through the BiDi Mapping layer (mapping toscript.callFunctionorscript.evaluatevia the connection pool).
-
Instead of hardcoding JavaScript as long strings inside Python files, osn-selenium stores scripts as individual .js files in the osn_seelnium/javascript/scripts/ directory. This ensures the same script is guaranteed to run in Sync, Trio, and BiDi modes.
The function get_js_scripts() automatically reads all files from the osn_seelnium/javascript/scripts folder and maps them to the JS_Scripts model. This allows for:
- Better Syntax Highlighting: Writing pure JS files is easier and less error-prone.
- Caching: Scripts are loaded and validated once at runtime.
- Consistency: The same script is guaranteed to run in both Sync and Trio modes.
The JS executor provides several powerful methods out of the box that extend beyond standard Selenium capabilities:
| Method | Description |
|---|---|
check_element_in_viewport |
Returns True only if the element is currently visible within the user's viewable area. |
get_random_element_point |
Finds a random |
get_viewport_rect |
Returns the exact dimensions and scroll offsets of the browser viewport. |
get_element_css_style |
Retrieves all computed CSS properties for an element at once. |
stop_window_loading |
Immediately stops the browser from loading further resources (useful for speed). |
start_fingerprint_detection |
Injects the stealth logic and hooks into the browser APIs. |
Access the executor through the javascript property of your driver.
# Synchronous Example
style = driver.javascript.get_element_css_style(element)
print(style['background-color'])
# Asynchronous Example (Trio)
is_visible = await driver.javascript.check_element_in_viewport(element)
if is_visible:
# Get a random point within the element for a natural click
point = await driver.javascript.get_random_element_point(element)
await driver.action_chains().hm_move(start_point, point).click().perform()Under the hood, the library uses a specialized bridge to handle data transfer between Python and the browser's V8 engine:
A utility that translates Python data structures into their JavaScript equivalents:
-
None$\rightarrow$ null -
True/False$\rightarrow$ true/false -
dict$\rightarrow$ Object -
list/tuple$\rightarrow$ Array
This bridge ensures that when a script returns a DOM element, it is automatically wrapped in the framework's own WebElement class (Sync or TrioThread), maintaining architectural integrity.