Closed Bug 1771428 Opened 3 years ago Closed 3 years ago

.then getted twice when await in devtools console

Categories

(DevTools :: Console, defect, P3)

Firefox 102
defect

Tracking

(firefox103 verified)

VERIFIED FIXED
103 Branch
Tracking Status
firefox103 --- verified

People

(Reporter: alanas.00, Assigned: nchevobbe)

Details

Attachments

(1 file)

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

Steps to reproduce:

  1. open any web page like https://example.net/
  2. press Ctrl+Shift+I
  3. select "Console" tab
  4. type obj={get then(){console.log("get then")}} into console
  5. press enter
  6. type await obj
  7. press enter

Actual results:

get then appeared twice in console

Expected results:

get then appeared once in console (like if you run (async()=>{await obj})())

Summary: .then called twice when await in devtools console → .then getted twice when await in devtools console

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

Component: Untriaged → Console
Product: Firefox → DevTools

This seems to be a side-effect of the way we wrap top-level await expressions in the console:
https://searchfox.org/mozilla-central/rev/b462b11e71b500e084f51e61fbd9e19ea0122c78/devtools/client/debugger/src/workers/parser/mapAwaitExpression.js#181

Basically when we execute await obj in the Firefox DevTools webconsole, we actually run:

(async () => {
  return await obj;
})();
Status: UNCONFIRMED → NEW
Ever confirmed: true

To check with Nicolas after PTO

Severity: -- → S3
Priority: -- → P3
Whiteboard: [devtools-triage]

This is most likely going to be a technical limitation for now, but Nicolas might share more details.

Flags: needinfo?(nchevobbe)
Whiteboard: [devtools-triage]

As Julian pointed out in Comment 2 , await obj is transformed into

(async () => {
  return await obj;
})();

When this is evaluated, await obj does trigger the first call to then
And then, since await obj returns a thenable and given that the wrapping async function returns a Promise, it will also call then.

We should probably tweak our babel mapper to transform the expression into

(async () => {
  return obj;
})();

which should be enough for what we want to achieve (and won't call then twice)

Flags: needinfo?(nchevobbe)

We use to transform expression like await obj into

(async () => {
  return await obj;
})()
``

So we were basically returning the expression, wrapped in an async iife, adding
a `return` statement before the last statement.
But in the case the last statement is an `AwaitExpression`, we can simply return
the argument, stripping the `await` keyword.
This fixes an issue when awaiting for an object with a `then` getter would execute
the getter twice.
A test case is added in mochitest, and unit test are updated to reflect the new
output.
Assignee: nobody → nchevobbe
Status: NEW → ASSIGNED
Pushed by nchevobbe@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/fc9a5269e55c [devtools] Remove last statement AwaitExpression in mapTopLevelAwait. r=bomsy.
Status: ASSIGNED → RESOLVED
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → 103 Branch

Reproduced the issue in release 102.
Verified - Fixed in Beta 103.0b4 and the latest Nightly build 104.0a1 (2022-07-05) using Windows 10 and macOS 12. "get then" appeared only once in console.

Status: RESOLVED → VERIFIED
Flags: qe-verify+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: