[decorators] Support private auto-accessors

Support for the accessor keywords for private class fields as part of
the decorators proposal.

Changes to AST:

- Add an AUTO_ACCESSOR value to the ClassLiteralProperty::Kind enum.
- Add an AutoAccessorInfo class to be used in ClassLiteralProperty
  objects of kind AUTO_ACCESSOR to hold the information about the
  generated getters/setters and backing storage.
- Add AutoAccessorGetterBody and AutoAccessorSetterBody statements to
  implement the logic of generated getters and setters.

Changes to Parser:
- Add logic to parse the "accessor" keyword and throw when used on non
  field class properties.
- Add preparser logic to mock the function scopes and variable
  declarations required for the generated getters/setters.
- Add parser logic to synthetically create statements for the
  generated setters/getters. 

Changes to the Bytecode Generator:
- Add logic to BuildClassLiteral to build auto accessor storage
  private names.
- Add logic to set the generated getters/setters in the accessor pair.
- Add logic to initialize the accessor storage in BuildClassProperty.
- Add AutoAccessorGetterBody and AutoAccessorSetterBody visitors.

Tests:
- Add parsing-unittests for parsing converage.
- Add test262 tests for functionality coverage.
- Add test-debug test for devtools support coverage.

Bug: 42202709
Change-Id: Ibb9bee3bbd0c09341108856f969e0c22bbb8b9cc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5547688
Reviewed-by: Seth Brenith <seth.brenith@microsoft.com>
Commit-Queue: Luis Pardo <lpardosixtos@microsoft.com>
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#95612}
This commit is contained in:
Luis Fernando Pardo Sixtos 2024-08-13 10:19:32 -07:00 committed by test262-merge-bot
parent bcb42e339d
commit 2020cfbe66
1 changed files with 106 additions and 0 deletions

View File

@ -0,0 +1,106 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/*---
description: Test private auto-accessors.
features: [decorators]
---*/
(function TestUninitializedPrivateAccessor() {
class C {
accessor #x;
assertFieldIsUndefined() {
assert.sameValue(this.#x, undefined);
}
assertFieldMatchesValue(value) {
assert.sameValue(this.#x, value);
}
setField(value) {
this.#x = value;
}
}
let c = new C();
c.assertFieldIsUndefined();
c.setField(42);
c.assertFieldMatchesValue(42);
})();
(function TestInitializedPrivateAccessor() {
class C {
accessor #x = 5;
assertFieldMatchesValue(value) {
assert.sameValue(this.#x, value);
}
setField(value) {
this.#x = value;
}
}
let c = new C();
c.assertFieldMatchesValue(5);
c.setField(42);
c.assertFieldMatchesValue(42);
})();
(function TestInitializedMultiplePrivateAccessor() {
class C {
accessor #x = 5;
accessor #y = 42;
assertFieldsMatcheValues(value_x, value_y) {
assert.sameValue(this.#x, value_x);
assert.sameValue(this.#y, value_y);
}
}
let c = new C();
c.assertFieldsMatcheValues(5, 42);
})();
(function TestThrowOnDuplicatedName() {
// Auto-accessors will instantiate private getter and setter with the same
// name, which shouldn't collide with other private variables.
let assertThrowsSyntaxError = (code_string) => {
assert.throws(SyntaxError, () => {eval(code_string)});
};
assertThrowsSyntaxError('class C { accessor #x = 5; accessor #x = 42; }');
assertThrowsSyntaxError('class C { accessor #x = 5; #x = 42; }');
assertThrowsSyntaxError('class C { accessor #x = 5; get #x() {}; }');
assertThrowsSyntaxError('class C { accessor #x = 5; set #x(value) {}; }');
assertThrowsSyntaxError('class C { accessor #x = 5; #x() {}; }');
assertThrowsSyntaxError('class C { accessor #x = 5; static #x = 42; }');
assertThrowsSyntaxError('class C { static accessor #x = 5; #x = 42; }');
assertThrowsSyntaxError(
'class C { static accessor #x = 5; static #x = 42; }');
})();
(function TestUninitializedStaticPrivateAccessor() {
class C {
static #x;
static assertFieldIsUndefined() {
assert.sameValue(C.#x, undefined);
}
static assertFieldMatchesValue(value) {
assert.sameValue(C.#x, value);
}
static setField(value) {
C.#x = value;
}
}
C.assertFieldIsUndefined();
C.setField(42);
C.assertFieldMatchesValue(42);
})();
(function TestInitializedStaticPrivateAccessor() {
class C {
static accessor #x = 5;
static assertFieldMatchesValue(value) {
assert.sameValue(C.#x, value);
}
static setField(value) {
C.#x = value;
}
}
C.assertFieldMatchesValue(5);
C.setField(42);
C.assertFieldMatchesValue(42);
})();