mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 01:35:35 +00:00
Bug 1370850 - Serialise undefined script evaluation return value to null; r=maja_zf
When a call through the content frame proxy is interrupted by the dialogueObserver, the synchronous promise that is meant to wait for a response from the frame script is resolved immediately with an undefined return value. When an undefined value is assigned to the response body, it gets dropped during JSON serialisation. To ensure the "value" field expected from the Execute Script and Execute Async Script commands is populated, we need to assign a null value to resp.body.value. We can treat undefined as null by calling evaluate.toJSON again on the return value from the proxied frame script call. This effectively means we serialise it twice, since it first needs to be serialised to cross the IPC border, though the second computation only looks at primitives and no known web element store is required. It would be nicer if the content frame script itself would be able to return early with null by installing a user prompt notification event, but this is not possible because the tabmodal dialogue that appears blocks script execution. This means we need to rely on the dialogueObserver in testing/marionette/proxy.js to take care of the dialogue for us. MozReview-Commit-ID: D14TA2TYYXI --HG-- extra : rebase_source : 3b2405111b0f027b1fd6281d075ab6dbb2259591
This commit is contained in:
parent
d382c7e1f3
commit
239a225f5a
@ -871,11 +871,13 @@ GeckoDriver.prototype.execute_ = function (script, args, timeout, opts = {}) {
|
||||
case Context.CONTENT:
|
||||
// evaluate in content with lasting side-effects
|
||||
if (!opts.sandboxName) {
|
||||
return this.listener.execute(script, args, timeout, opts);
|
||||
return this.listener.execute(script, args, timeout, opts)
|
||||
.then(evaluate.toJSON);
|
||||
|
||||
// evaluate in content with sandbox
|
||||
} else {
|
||||
return this.listener.executeInSandbox(script, args, timeout, opts);
|
||||
return this.listener.executeInSandbox(script, args, timeout, opts)
|
||||
.then(evaluate.toJSON);
|
||||
}
|
||||
|
||||
case Context.CHROME:
|
||||
@ -887,8 +889,8 @@ GeckoDriver.prototype.execute_ = function (script, args, timeout, opts = {}) {
|
||||
|
||||
opts.timeout = timeout;
|
||||
let wargs = evaluate.fromJSON(args, this.curBrowser.seenEls, sb.window);
|
||||
let evaluatePromise = evaluate.sandbox(sb, script, wargs, opts);
|
||||
return evaluatePromise.then(res => evaluate.toJSON(res, this.curBrowser.seenEls));
|
||||
return evaluate.sandbox(sb, script, wargs, opts)
|
||||
.then(res => evaluate.toJSON(res, this.curBrowser.seenEls));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@ import os
|
||||
import urllib
|
||||
|
||||
from marionette_driver import By, errors
|
||||
from marionette_driver.marionette import HTMLElement
|
||||
from marionette_driver.marionette import Alert, HTMLElement
|
||||
from marionette_driver.wait import Wait
|
||||
|
||||
from marionette_harness import MarionetteTestCase, skip_if_mobile, WindowManagerMixin
|
||||
@ -31,6 +31,23 @@ globals = set([
|
||||
|
||||
class TestExecuteContent(MarionetteTestCase):
|
||||
|
||||
def alert_present(self):
|
||||
try:
|
||||
Alert(self.marionette).text
|
||||
return True
|
||||
except errors.NoAlertPresentException:
|
||||
return False
|
||||
|
||||
def wait_for_alert_closed(self, timeout=None):
|
||||
Wait(self.marionette, timeout=timeout).until(
|
||||
lambda _: not self.alert_present())
|
||||
|
||||
def tearDown(self):
|
||||
if self.alert_present():
|
||||
alert = self.marionette.switch_to_alert()
|
||||
alert.dismiss()
|
||||
self.wait_for_alert_closed()
|
||||
|
||||
def assert_is_defined(self, property, sandbox="default"):
|
||||
self.assertTrue(self.marionette.execute_script(
|
||||
"return typeof arguments[0] != 'undefined'", [property], sandbox=sandbox),
|
||||
@ -340,6 +357,11 @@ class TestExecuteContent(MarionetteTestCase):
|
||||
sandbox=None)
|
||||
self.assert_is_web_element(el)
|
||||
|
||||
def test_return_value_on_alert(self):
|
||||
res = self.marionette._send_message("executeScript", {"script": "alert()"})
|
||||
self.assertIn("value", res)
|
||||
self.assertIsNone(res)
|
||||
|
||||
|
||||
class TestExecuteChrome(WindowManagerMixin, TestExecuteContent):
|
||||
|
||||
@ -408,6 +430,9 @@ class TestExecuteChrome(WindowManagerMixin, TestExecuteContent):
|
||||
def test_access_chrome_objects_in_event_listeners(self):
|
||||
pass
|
||||
|
||||
def test_return_value_on_alert(self):
|
||||
pass
|
||||
|
||||
|
||||
class TestElementCollections(MarionetteTestCase):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user