Closed Bug 1702860 Opened 4 years ago Closed 2 years ago

CDP: Runtime.evaluate(awaitPromise) fails with ProtocolError on rejected promise

Categories

(Remote Protocol :: CDP, defect, P3)

Firefox 89
defect

Tracking

(firefox112 fixed)

RESOLVED FIXED
112 Branch
Tracking Status
firefox112 --- fixed

People

(Reporter: martin, Assigned: canadahonk)

References

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0

Steps to reproduce:

Set up a sandbox with https://www.npmjs.com/package/chrome-remote-interface :

mkdir /tmp/test; cd /tmp/test
npm install chrome-remote-interface
node_modules/.bin/chrome-remote-interface inspect

Start firefox current nightly (both 88.0a1 from two weeks ago as well as today's 89.0a1 2021-04-02 64 bit) in a temporary home dir:

HOME=/tmp/h firefox --remote-debugging-port=9222 localhost &

Enter Chrome DevTools interactive shell:

node_modules/.bin/chrome-remote-interface inspect

Visit a page to initialize CDP, and make sure it works:

Page.navigate({url: "https://www.mozilla.org"})
{ frameId: '19', loaderId: '41044854964409' }

Runtime.evaluate({expression: "window.location.toString()"})
{ result: { type: 'string', value: 'https://www.mozilla.org/en-US/' } }

(this may take a few iterations, Firefox often fails with "can't access property "evaluate", context is null" -- but this isn't the issue here).

Do simple promise evaluation (this works fine):

Runtime.evaluate({expression: "new Promise((resolve, reject) => resolve('moo'))", awaitPromise: true})
{ result: { type: 'string', value: 'moo' } }
Runtime.evaluate({expression: "new Promise((resolve, reject) => reject(new Error('moo')))", awaitPromise: true})
{ exceptionDetails: { text: 'moo' } }

Do a slightly more complicated promise rejection evaluation where the rejection is delayed:

Runtime.evaluate({expression: "new Promise((resolve, reject) => window.setTimeout(() => reject(new Error('moo')), 500))", awaitPromise: true})

Actual results:

Uncaught:
ProtocolError: Debugger: expected Debugger.Object, got Proxy (_returnError@chrome://remote/content/cdp/domains/content/runtime/ExecutionContext.jsm:193:22
evaluate@chrome://remote/content/cdp/domains/content/runtime/ExecutionContext.jsm:173:23
setTimeout handlerSentry</an.prototype.qt/<@https://www.mozilla.org/media/js/BUNDLES/sentry.d4a49ae2b9e1.js:1:48985
@debugger eval code:1:41
@debugger eval code:1:1
evaluate@chrome://remote/content/cdp/domains/content/runtime/ExecutionContext.jsm:147:29
evaluate@chrome://remote/content/cdp/domains/content/Runtime.jsm:279:20
execute@chrome://remote/content/cdp/domains/DomainCache.jsm:101:25
receiveMessage@chrome://remote/content/cdp/sessions/ContentProcessSession.jsm:84:45
)
at /tmp/test/node_modules/chrome-remote-interface/lib/chrome.js:94:35
at Chrome._handleMessage (/tmp/test/node_modules/chrome-remote-interface/lib/chrome.js:257:17) {
request: {
method: 'Runtime.evaluate',
params: {
expression: "new Promise((resolve, reject) => window.setTimeout(() => reject(new Error('moo')), 500))",
awaitPromise: true
},
sessionId: undefined
},
response: {
message: 'Debugger: expected Debugger.Object, got Proxy',
data: '_returnError@chrome://remote/content/cdp/domains/content/runtime/ExecutionContext.jsm:193:22\n' +
'evaluate@chrome://remote/content/cdp/domains/content/runtime/ExecutionContext.jsm:173:23\n' +
'setTimeout handler
Sentry</an.prototype.qt/<@https://www.mozilla.org/media/js/BUNDLES/sentry.d4a49ae2b9e1.js:1:48985\n' +
'@debugger eval code:1:41\n' +
'@debugger eval code:1:1\n' +
'evaluate@chrome://remote/content/cdp/domains/content/runtime/ExecutionContext.jsm:147:29\n' +
'evaluate@chrome://remote/content/cdp/domains/content/Runtime.jsm:279:20\n' +
'execute@chrome://remote/content/cdp/domains/DomainCache.jsm:101:25\n' +
'receiveMessage@chrome://remote/content/cdp/sessions/ContentProcessSession.jsm:84:45\n'
}
}

Expected results:

I expect the same output as with the "straight away reject", i.e. something like

{ exceptionDetails: { text: 'moo' } }

For comparison, when doing this with chromium:

rm -rf /tmp/h; HOME=/tmp/h chromium-browser --remote-debugging-port=9222 about:blank &

you get something like

{
result: {
type: 'object',
subtype: 'error',
className: 'Error',
description: 'Error: moo\n' +
' at <anonymous>:1:41\n' +
' at new Promise (<anonymous>)\n' +
' at <anonymous>:1:1',
objectId: '4319001542793249506.1.4'
},
exceptionDetails: {
exceptionId: 2,
text: 'Uncaught (in promise) Error: moo',
lineNumber: 0,
columnNumber: 0,
exception: {
type: 'object',
subtype: 'error',
className: 'Error',
description: 'Error: moo\n' +
' at <anonymous>:1:41\n' +
' at new Promise (<anonymous>)\n' +
' at <anonymous>:1:1',
objectId: '4319001542793249506.1.5'
}
}
}

The Bugbug bot thinks this bug should belong to the 'DevTools::General' component, and is moving the bug to that component. Please revert this change in case you think the bot is wrong.

Component: Untriaged → General
Product: Firefox → DevTools
Summary: DevTools protocol: Runtime.evaluate(awaitPromise) fails with ProtocolError on rejected promise → CDP: Runtime.evaluate(awaitPromise) fails with ProtocolError on rejected promise
Component: General → CDP
Product: DevTools → Remote Protocol

Interesting. We have actually a test for a delayed resolved promise via restrict, but there we only return a value and don't throw an error:

https://searchfox.org/mozilla-central/rev/0b90e582d2f592a30713bafc55bfeb0e39e1a1fa/remote/cdp/test/browser/runtime/browser_evaluate.js#73-87

So something is probably wrong here with returning errors.

Points: --- → 3
Priority: -- → P3
Severity: -- → S3

For the record, this is still true with Firefox 106.

Happy to work on this.

Fix an internal error causing a ProtocolError when a Promise ran using
Runtime.evaluate and rejects with an Error(), while using the
awaitPromise option. Also added test for such a case.

When a rejected Error happens, that Error (or a Proxy representing)
is thrown and caught internally instead of a Debugger.Object, unsure why.
instanceof was not working internally so requires checking if
a key exists instead. Happy to change if a better solution is found.

Assignee: nobody → oj
Status: NEW → ASSIGNED
Attachment #9313473 - Attachment description: Bug 1702860 - [cdp] Fix ProtocolError on Runtime.evaluate returning a rejected Error with awaitPromise → Bug 1702860 - [cdp] Fix ProtocolError on returning a rejected Error with awaitPromise
Pushed by hskupin@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/1c1997148ad4 [cdp] Fix ProtocolError on returning a rejected Error with awaitPromise r=webdriver-reviewers,whimboo
Status: ASSIGNED → RESOLVED
Closed: 2 years ago
Resolution: --- → FIXED
Target Milestone: --- → 112 Branch
Points: 3 → ---
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: