Closed Bug 1757162 Opened 3 years ago Closed 3 years ago

Can’t access private field in class constructor arguments

Categories

(Core :: JavaScript Engine, defect, P1)

Firefox 97
defect

Tracking

()

RESOLVED FIXED
100 Branch
Tracking Status
firefox100 --- fixed

People

(Reporter: mozilla, Assigned: mgaudet)

References

(Blocks 1 open bug)

Details

Attachments

(1 file)

Steps to reproduce:

Specified a default in the constructor like so:

class Button {
#targetDefaults = 'default'
constructor(element, target = this.#targetDefaults) {
this.element = element
this.target = target
}
}

new Button(document.getElementById('butt'))

Code on CodePen: https://codepen.io/Moiety/pen/abVazdE/0090d1492e43588ded46c4a432f8c0bd?editors=1111

This code works in Chrome and Safari, but not Firefox.

Actual results:

Firefox throws an error: “Uncaught TypeError: can't access private field or method: object is not the right class”

Expected results:

this.target should be set to 'default' (via #targetDefaults)

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

Component: Untriaged → JavaScript Engine
Product: Firefox → Core

Can confirm that it throws in Nightly (build 20220225104705).

This currently syntax errors in Firefox; I will take a closer look soon.

Certainly seems like a bug in our private field scoping.

Severity: -- → S3
Flags: needinfo?(mgaudet)
Priority: -- → P1
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(mgaudet)

(Also peculiar that we don't have a test262 test for this -- we will have to write one as part of the fix here)

Blocks: js-lang

Definitely seems to be bug, potentially having to do with default argument execution context.

If you need a short term workaround, may I suggest making #targetDefaults static?

class Button {
  static #targetDefaults = 'default'
  constructor(element, target = Button.#targetDefaults) {
    this.element = element
    this.target = target
  }
}

So: Here's the specification argument for why Firefox is in the wrong here:

We're evaluating a new expression, and so we end up in 13.3.5.1.1 EvaluateNew. Step 6 is Construct, which in turn calls into 10.2.2 [[Construct]].

In this case, we take step 6, and initializes instance elements before evaluating the constructor in step 8.

So this should work. I'll dig though to see why we don't do it in this order tomorrow.

Summary: Can’t access private field in class constructor body → Can’t access private field in class constructor arguments
Assignee: nobody → mgaudet
Status: NEW → ASSIGNED
Pushed by mgaudet@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/bc8c1347f9c7 Initialize instance members before processing function formal parameters r=arai
Status: ASSIGNED → RESOLVED
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → 100 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: