MicrosoftEdge / DevTools

Feedback and discussions about Microsoft Edge Developer Tools
MIT License
151 stars 49 forks source link

Class private property evaluates as undefined in the Console in Edge, but not in Chrome #259

Open datvm opened 3 weeks ago

datvm commented 3 weeks ago

Please see this question here on Microsoft Learn where it's confirmed it is apparently a bug in Microsoft Edge.

I am encountering an issue where a variable is assigned a value, but the value is always undefined in Microsoft Edge. Strangely, the same code works as expected in Google Chrome. I have confirmed the assigned value is not undefined, and checked that the code does not have any way to assign undefined to the variable. Even though hovering over the variable in DevTools shows the correct value, evaluating the variable in the console still results in undefined. Here is the relevant code:

image

customElements.define("popup-page", class extends HTMLElement {
    // ...
    #lastDownload = 0;
    // ...

    async #download() {
        // ...
        this.#lastDownload = 0;
        // ...

            for (let i = 0; i < urls.length; i++) {
                // ...
                const id = el.downloadId = await this.#attemptItemAsync(url, maxCon, addDelay);
            }
    }

async #attemptItemAsync(url, maxCon, addDelay) {
        try {
            if (addDelay > 0) {
                const now = Date.now();
                if (now - this.#lastDownload < addDelay) {
                    await sleepAsync(now - this.#lastDownload);
                }
                this.#lastDownload = now;
            }

            // ...
        }
        catch {
            return;
        }
    }
});

I believe this is a bug in Microsoft Edge. When I sideloaded the same extension into Google Chrome, the bug did not occur. Please let me know if you need more information.

AB#52257933

captainbrosset commented 2 weeks ago

Thank you for reporting this here. I have two questions:

  1. Does the bug only appear in the DevTools Console? That is: the value appears as undefined in the Console, but the code works.
  2. Are you able to provide a full code snippet for us to try and reproduce this locally? Right now, the code is incomplete and I can't really run it locally without inventing other parts of the code, which might not be the right ones to reproduce the issue.

Thank you.

datvm commented 2 weeks ago

@captainbrosset Hi,

  1. No, the DevTool tooltip is the only place where the should-be value shows up. However, the "real" value is still undefined, making my if statement's expression false when it should be true. That is, the code doesn't perform as it should.

  2. I sent it to the person at this post privately because it's a private project. Unfortunately I am not sure what causes it and cannot make a minimal reproducible example. If you provide a private channel I will send over the file.

captainbrosset commented 1 week ago

@datvm if you can, please send the file over as a private message either on my twitter or mastodon account, which are linked to from my github account page: https://github.com/captainbrosset/ Or send it as an email: patrickbrosset at gmail dot com.

datvm commented 1 week ago

@captainbrosset thanks, sent you an email.

captainbrosset commented 3 days ago

Thank you @datvm. It took me a bit of time, but I did find a reduced test case. This has nothing to do with your specific extension code, but instead seems to be a bug with the way DevTools evaluates private properties.

Here is the reduced test case:

<!DOCTYPE html>
<script>
class Foo {
  #bar = 1;
  constructor () {
    console.log(this.#bar);
    debugger;
  }
}

new Foo();
</script>

When you run this, the console shows 1, as expected, because of the console.log statement. Also, hovering over the this.#bar expression in the Sources tool shows the right value. But, when evaluating this.#bar in the Console tool, the result is undefined. See below:

image

I was also able to verify that this worked fine in Chrome, just not in Edge.

I'll bring this up with our dev team and make sure the bug is tracked on our backlog. Thank you for filing.

datvm commented 3 days ago

@captainbrosset Hi, thank you for the info. Please note that in your code, the issue only happens to the printed out Console, however, in my extension code, the whole expression actually gets evaluated incorrectly. For example, I added an if statement to your code:

class Foo {
  #bar = 1;
  constructor () {
    console.log(this.#bar);
    if (this.#bar < 2) {
        console.log("< 2");
    }
    debugger;
  }
}

new Foo();

In the above code, the if expression is still evaluated correctly and < 2 is printed out even though this.#bar is printed out as undefined. In my extension code, the whole if statement is skipped due to undefined being falsy.

captainbrosset commented 3 days ago

That is very surprising. If there's indeed an issue with the running code (whether DevTools is opened or not), then that is a different bug with the V8 scripting engine. What's surprising is that we use the exact same as Chrome does. So I don't expect there to be any differences.

Note that the DevTools bug (undefined showing up in the Console) is being investigated by our dev team, and they've identified the root cause.

I suggest waiting for a fix to make it to the next Edge Canary, and then test again to see if your issue goes away.

datvm commented 2 days ago

@captainbrosset Maybe an issue when the method is async? As for my extension, the code in question is this:

  if (now - this.#lastDownload < addDelay) {
      await sleepAsync(now - this.#lastDownload);
  }

In Edge, my tasks all ran at the same time without delay (that's why I used DevTools to inspect the issue to begin with). I am 90% sure the issue happens without DevTools being opened.

In Chrome, the tasks are correctly delayed.