question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Returning const in execute_script results in Exception

See original GitHub issue

🐛 Bug Report

Global objects that are accessible via Firefox Console cannot be accessed with selenium. This only affects const it seems, i.e. var are visible to selenium. When trying to return these values using the execute_script function, a JavascriptException is thrown. The issue is specific to using the geckodriver. It works as expected using the chromedriver.

To Reproduce

  1. In Python, create a driver instance and navigate to any website.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(https://google.com)
  1. Add const via Firefox console:
const test_val = 'test'
function return_test_val() {
  return test_val;
}
  1. In Python, execute the following:
driver.execute_script("return test_val;")   # This will result in a JavaScriptException
driver.execute_script("function return_test_val() {return test_val} return return_test_val;")  # This will result in the same Exception
driver.execute_script("return return_test_val();")  # This is working (function defined in Firefox console)

The exception raised:

---------------------------------------------------------------------------
JavascriptException                       Traceback (most recent call last)
<ipython-input-35-aa126bcc64f7> in <module>
----> 1 driver.execute_script('return test_val;')

~/miniconda3/envs/AutoTest/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py in execute_script(self, script, *args)
    632             command = Command.EXECUTE_SCRIPT
    633 
--> 634         return self.execute(command, {
    635             'script': script,
    636             'args': converted_args})['value']

~/miniconda3/envs/AutoTest/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py in execute(self, driver_command, params)
    319         response = self.command_executor.execute(driver_command, params)
    320         if response:
--> 321             self.error_handler.check_response(response)
    322             response['value'] = self._unwrap_value(
    323                 response.get('value', None))

~/miniconda3/envs/AutoTest/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py in check_response(self, response)
    240                 alert_text = value['alert'].get('text')
    241             raise exception_class(message, screen, stacktrace, alert_text)
--> 242         raise exception_class(message, screen, stacktrace)
    243 
    244     def _value_or_default(self, obj, key, default):

JavascriptException: Message: ReferenceError: test_val is not defined

Implications:

  • const values that are globally accessible via Firefox console cannot be retrieved with selenium
  • There is no way to access global consts unless writing a helper function in the Firefox console which contradicts the automatisation.

Expected behavior

driver.execute_script("return test_val") should return the const test_val. It should not result in an exception.

Environment

OS: Debian Buster Browser: Firefox Browser version: 78.10.0esr (64-bit) Browser Driver version: GeckoDriver 0.29.0 Language Bindings version: Python 3.9.4, selenium 3.141.0 selenium-wire 4.2.4 Selenium Grid version (if applicable): -

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
AutomatedTestercommented, May 14, 2021

So after speaking to the Mozilla team there appears to be https://github.com/mozilla/geckodriver/issues/1067 that is raised for this issue. There are links to Bugzilla from there so there is not much we can do from the Selenium side.

0reactions
picciamacommented, May 13, 2021

I can reproduce this with Windows 10 and Firefox 88.

I noticed though that we might have a misunderstanding here: While you created a global const cheese, you didn’t call it as you created a local const within the scope of execute_script: https://github.com/SeleniumHQ/selenium/commit/e9c738de8a587dc6bc86b55949c57b8574ec68bb#diff-6d75ecf37273e7973aeac782de0ca2876d6cfaa7b36971f811b385cc7dcb7a61R288 This is working as expected but it doesn’t access the global const.

Your second attempt in which you call the global function makeMeA is working too, as it is a globally defined function that’s already in the document. If it isn’t your website though, you annot just modify the served HTML of course an add this function.

What doesn’t but should work is this: driver.execute_script("return cheese") which should return the global const cheese, I’m very sure you will be able to reproduce it.

I found a workaround though:

driver.execute_script("""
  let scr = document.createElement('script');
  scr.id='injected_function';
  scr.innerHTML='function makeMeA(sandwich){return cheese + sandwich}';
  document.head.appendChild(scr);
"""
)
driver.execute_script("return makeMeA('sandwich');")

This way, I can inject javascript by adding a child script to the document head. This is equivalent to your example in which this function is already defined in the HTML.

What remains though are the following questions:

  1. Why doesn’t driver.execute_script("return cheese") work (and why does it in chromedriver)?
  2. Why doesn’t it work if the above javascript isn’t explicitly added to a new script element in the document (i.e. only defining it within the enclosing scope of execute_script?
  3. Why does this affect only consts but not var or function?
  4. Could it be that is sth. to do with the read only property of const?

As I see it, global consts cannot be accessed directly from within execute_script at the moment, even with the newest Firefox and geckodriver versions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Selenium IJavaScriptExecutor `ExecuteScript()` method ...
I have created a method to click some page objects using javascript(very legacy application). I am getting exception when I try to pass...
Read more >
Call web-side code from native-side code - Microsoft Learn
The script returns a string that ExecuteScript JSON-encodes for you. If you call JSON.stringify from your script, then the result is doubly ...
Read more >
ExecuteScript | CloverDX 5.16.1 Documentation
A component input and results of a script run. Records for scripts that cannot run or return 1. Any ...
Read more >
Selenium JavaScript - Tools QA
resultType: A constant that specifies the desired result type to be returned as a result of the evaluation. The most commonly passed ...
Read more >
10.5.4 MySQLCursor.execute() Method
It returns an iterator that enables processing the result of each statement. However, using parameters does not work well in this case, and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found