[class] implement private accessors
This patch implements the access of private accessors by loading the referenced component from the AccessorPair associated with private name variables. It also makes the error messages for invalid kind of private accessor access more specific. Bug: v8:8330 Design doc: https://docs.google.com/document/d/10W4begYfs7lmldSqBoQBBt_BKamgT8igqxF9u50RGrI/edit Change-Id: I6d441cffb85f8d9cd0417ec9b6ae20f3e34ef418 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1695205 Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Commit-Queue: Joyee Cheung <joyee@igalia.com> Cr-Commit-Position: refs/heads/master@{#63474}
This commit is contained in:
parent
bdcc7502cb
commit
df12eb194e
@ -413,11 +413,15 @@ namespace internal {
|
||||
T(InvalidOrUnexpectedToken, "Invalid or unexpected token") \
|
||||
T(InvalidPrivateFieldResolution, \
|
||||
"Private field '%' must be declared in an enclosing class") \
|
||||
T(InvalidPrivateFieldRead, \
|
||||
"Read of private field % from an object which did not contain the field") \
|
||||
T(InvalidPrivateFieldWrite, \
|
||||
"Write of private field % to an object which did not contain the field") \
|
||||
T(InvalidPrivateMemberRead, \
|
||||
"Cannot read private member % from an object whose class did not declare " \
|
||||
"it") \
|
||||
T(InvalidPrivateMemberWrite, \
|
||||
"Cannot write private member % to an object whose class did not declare " \
|
||||
"it") \
|
||||
T(InvalidPrivateMethodWrite, "Private method '%' is not writable") \
|
||||
T(InvalidPrivateGetterAccess, "'%' was defined without a getter") \
|
||||
T(InvalidPrivateSetterAccess, "'%' was defined without a setter") \
|
||||
T(JsonParseUnexpectedEOS, "Unexpected end of JSON input") \
|
||||
T(JsonParseUnexpectedToken, "Unexpected token % in JSON at position %") \
|
||||
T(JsonParseUnexpectedTokenNumber, "Unexpected number in JSON at position %") \
|
||||
|
@ -412,7 +412,7 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
||||
if (name->IsPrivateName() && !it.IsFound()) {
|
||||
Handle<String> name_string(String::cast(Symbol::cast(*name).name()),
|
||||
isolate());
|
||||
return TypeError(MessageTemplate::kInvalidPrivateFieldRead, object,
|
||||
return TypeError(MessageTemplate::kInvalidPrivateMemberRead, object,
|
||||
name_string);
|
||||
}
|
||||
|
||||
@ -1411,7 +1411,7 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
|
||||
if (name->IsPrivateName() && !it.IsFound()) {
|
||||
Handle<String> name_string(String::cast(Symbol::cast(*name).name()),
|
||||
isolate());
|
||||
return TypeError(MessageTemplate::kInvalidPrivateFieldWrite, object,
|
||||
return TypeError(MessageTemplate::kInvalidPrivateMemberWrite, object,
|
||||
name_string);
|
||||
}
|
||||
|
||||
|
@ -2329,12 +2329,13 @@ void BytecodeGenerator::VisitInitializeClassMembersStatement(
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildThrowPrivateMethodWriteError(
|
||||
const AstRawString* name) {
|
||||
void BytecodeGenerator::BuildInvalidPropertyAccess(MessageTemplate tmpl,
|
||||
Property* property) {
|
||||
RegisterAllocationScope register_scope(this);
|
||||
const AstRawString* name = property->key()->AsVariableProxy()->raw_name();
|
||||
RegisterList args = register_allocator()->NewRegisterList(2);
|
||||
builder()
|
||||
->LoadLiteral(Smi::FromEnum(MessageTemplate::kInvalidPrivateMethodWrite))
|
||||
->LoadLiteral(Smi::FromEnum(tmpl))
|
||||
.StoreAccumulatorInRegister(args[0])
|
||||
.LoadLiteral(name)
|
||||
.StoreAccumulatorInRegister(args[1])
|
||||
@ -3887,15 +3888,28 @@ void BytecodeGenerator::BuildAssignment(
|
||||
break;
|
||||
}
|
||||
case PRIVATE_METHOD: {
|
||||
BuildThrowPrivateMethodWriteError(
|
||||
lhs_data.expr()->AsProperty()->key()->AsVariableProxy()->raw_name());
|
||||
BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateMethodWrite,
|
||||
lhs_data.expr()->AsProperty());
|
||||
break;
|
||||
}
|
||||
case PRIVATE_GETTER_ONLY: {
|
||||
BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateSetterAccess,
|
||||
lhs_data.expr()->AsProperty());
|
||||
break;
|
||||
}
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_SETTER_ONLY:
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
// TODO(joyee): implement private accessors.
|
||||
return;
|
||||
Register value = register_allocator()->NewRegister();
|
||||
builder()->StoreAccumulatorInRegister(value);
|
||||
Property* property = lhs_data.expr()->AsProperty();
|
||||
Register object = VisitForRegisterValue(property->obj());
|
||||
Register key = VisitForRegisterValue(property->key());
|
||||
BuildPrivateBrandCheck(property, object);
|
||||
BuildPrivateSetterAccess(object, key, value);
|
||||
if (!execution_result()->IsEffect()) {
|
||||
builder()->LoadAccumulatorWithRegister(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3942,16 +3956,13 @@ void BytecodeGenerator::VisitCompoundAssignment(CompoundAssignment* expr) {
|
||||
lhs_data.super_property_args().Truncate(3));
|
||||
break;
|
||||
}
|
||||
case PRIVATE_METHOD: {
|
||||
BuildThrowPrivateMethodWriteError(
|
||||
lhs_data.expr()->AsProperty()->key()->AsVariableProxy()->raw_name());
|
||||
break;
|
||||
}
|
||||
case PRIVATE_SETTER_ONLY:
|
||||
case PRIVATE_METHOD:
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_SETTER_ONLY:
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
// TODO(joyee): implement private accessors.
|
||||
return;
|
||||
// ({ #foo: name } = obj) is currently syntactically invalid.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4418,32 +4429,70 @@ void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* property) {
|
||||
case KEYED_SUPER_PROPERTY:
|
||||
VisitKeyedSuperPropertyLoad(property, Register::invalid_value());
|
||||
break;
|
||||
case PRIVATE_SETTER_ONLY: {
|
||||
BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateGetterAccess,
|
||||
property);
|
||||
break;
|
||||
}
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
Register key = VisitForRegisterValue(property->key());
|
||||
BuildPrivateBrandCheck(property, obj);
|
||||
BuildPrivateGetterAccess(obj, key);
|
||||
break;
|
||||
}
|
||||
case PRIVATE_METHOD: {
|
||||
Variable* private_name = property->key()->AsVariableProxy()->var();
|
||||
|
||||
// Perform the brand check.
|
||||
DCHECK(private_name->requires_brand_check());
|
||||
ClassScope* scope = private_name->scope()->AsClassScope();
|
||||
Variable* brand = scope->brand();
|
||||
BuildVariableLoadForAccumulatorValue(brand, HoleCheckMode::kElided);
|
||||
builder()->SetExpressionPosition(property);
|
||||
builder()->LoadKeyedProperty(
|
||||
obj, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
|
||||
|
||||
BuildPrivateBrandCheck(property, obj);
|
||||
// In the case of private methods, property->key() is the function to be
|
||||
// loaded (stored in a context slot), so load this directly.
|
||||
VisitForAccumulatorValue(property->key());
|
||||
break;
|
||||
}
|
||||
case PRIVATE_SETTER_ONLY:
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
// TODO(joyee): implement private accessors.
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildPrivateGetterAccess(Register object,
|
||||
Register accessor_pair) {
|
||||
RegisterAllocationScope scope(this);
|
||||
Register accessor = register_allocator()->NewRegister();
|
||||
RegisterList args = register_allocator()->NewRegisterList(1);
|
||||
|
||||
builder()
|
||||
->CallRuntime(Runtime::kLoadPrivateGetter, accessor_pair)
|
||||
.StoreAccumulatorInRegister(accessor)
|
||||
.MoveRegister(object, args[0])
|
||||
.CallProperty(accessor, args,
|
||||
feedback_index(feedback_spec()->AddCallICSlot()));
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildPrivateSetterAccess(Register object,
|
||||
Register accessor_pair,
|
||||
Register value) {
|
||||
RegisterAllocationScope scope(this);
|
||||
Register accessor = register_allocator()->NewRegister();
|
||||
RegisterList args = register_allocator()->NewRegisterList(2);
|
||||
|
||||
builder()
|
||||
->CallRuntime(Runtime::kLoadPrivateSetter, accessor_pair)
|
||||
.StoreAccumulatorInRegister(accessor)
|
||||
.MoveRegister(object, args[0])
|
||||
.MoveRegister(value, args[1])
|
||||
.CallProperty(accessor, args,
|
||||
feedback_index(feedback_spec()->AddCallICSlot()));
|
||||
}
|
||||
|
||||
void BytecodeGenerator::BuildPrivateBrandCheck(Property* property,
|
||||
Register object) {
|
||||
Variable* private_name = property->key()->AsVariableProxy()->var();
|
||||
DCHECK(private_name->requires_brand_check());
|
||||
ClassScope* scope = private_name->scope()->AsClassScope();
|
||||
Variable* brand = scope->brand();
|
||||
BuildVariableLoadForAccumulatorValue(brand, HoleCheckMode::kElided);
|
||||
builder()->SetExpressionPosition(property);
|
||||
builder()->LoadKeyedProperty(
|
||||
object, feedback_index(feedback_spec()->AddKeyedLoadICSlot()));
|
||||
}
|
||||
|
||||
void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
|
||||
Property* expr,
|
||||
Register destination) {
|
||||
@ -5030,16 +5079,27 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
break;
|
||||
}
|
||||
case PRIVATE_METHOD: {
|
||||
BuildThrowPrivateMethodWriteError(
|
||||
property->key()->AsVariableProxy()->raw_name());
|
||||
break;
|
||||
}
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_SETTER_ONLY:
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
// TODO(joyee): implement private accessors.
|
||||
BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateMethodWrite,
|
||||
property);
|
||||
return;
|
||||
}
|
||||
case PRIVATE_GETTER_ONLY: {
|
||||
BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateSetterAccess,
|
||||
property);
|
||||
return;
|
||||
}
|
||||
case PRIVATE_SETTER_ONLY: {
|
||||
BuildInvalidPropertyAccess(MessageTemplate::kInvalidPrivateGetterAccess,
|
||||
property);
|
||||
return;
|
||||
}
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
object = VisitForRegisterValue(property->obj());
|
||||
key = VisitForRegisterValue(property->key());
|
||||
BuildPrivateBrandCheck(property, object);
|
||||
BuildPrivateGetterAccess(object, key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Save result for postfix expressions.
|
||||
@ -5106,17 +5166,20 @@ void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
.CallRuntime(Runtime::kStoreKeyedToSuper, super_property_args);
|
||||
break;
|
||||
}
|
||||
case PRIVATE_METHOD: {
|
||||
BuildThrowPrivateMethodWriteError(
|
||||
property->key()->AsVariableProxy()->raw_name());
|
||||
break;
|
||||
}
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_SETTER_ONLY:
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
// TODO(joyee): implement private accessors.
|
||||
case PRIVATE_GETTER_ONLY:
|
||||
case PRIVATE_METHOD: {
|
||||
UNREACHABLE();
|
||||
}
|
||||
case PRIVATE_GETTER_AND_SETTER: {
|
||||
Register value = register_allocator()->NewRegister();
|
||||
builder()->StoreAccumulatorInRegister(value);
|
||||
BuildPrivateSetterAccess(object, key, value);
|
||||
if (!execution_result()->IsEffect()) {
|
||||
builder()->LoadAccumulatorWithRegister(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore old value for postfix expressions.
|
||||
|
@ -302,7 +302,11 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
void VisitArgumentsObject(Variable* variable);
|
||||
void VisitRestArgumentsArray(Variable* rest);
|
||||
void VisitCallSuper(Call* call);
|
||||
void BuildThrowPrivateMethodWriteError(const AstRawString* name);
|
||||
void BuildInvalidPropertyAccess(MessageTemplate tmpl, Property* property);
|
||||
void BuildPrivateBrandCheck(Property* property, Register object);
|
||||
void BuildPrivateGetterAccess(Register obj, Register access_pair);
|
||||
void BuildPrivateSetterAccess(Register obj, Register access_pair,
|
||||
Register value);
|
||||
void BuildClassLiteral(ClassLiteral* expr, Register name);
|
||||
void VisitClassLiteral(ClassLiteral* expr, Register name);
|
||||
void VisitNewTargetVariable(Variable* variable);
|
||||
|
@ -46,7 +46,7 @@ MaybeHandle<Object> Runtime::GetObjectProperty(Isolate* isolate,
|
||||
Handle<Object> name_string(Symbol::cast(*key).name(), isolate);
|
||||
DCHECK(name_string->IsString());
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kInvalidPrivateFieldRead,
|
||||
NewTypeError(MessageTemplate::kInvalidPrivateMemberRead,
|
||||
name_string, object),
|
||||
Object);
|
||||
}
|
||||
@ -413,7 +413,7 @@ MaybeHandle<Object> Runtime::SetObjectProperty(
|
||||
Handle<Object> name_string(Symbol::cast(*key).name(), isolate);
|
||||
DCHECK(name_string->IsString());
|
||||
THROW_NEW_ERROR(isolate,
|
||||
NewTypeError(MessageTemplate::kInvalidPrivateFieldWrite,
|
||||
NewTypeError(MessageTemplate::kInvalidPrivateMemberWrite,
|
||||
name_string, object),
|
||||
Object);
|
||||
}
|
||||
|
@ -0,0 +1,192 @@
|
||||
#
|
||||
# Autogenerated by generate-bytecode-expectations.
|
||||
#
|
||||
|
||||
---
|
||||
wrap: no
|
||||
test function name: test
|
||||
private methods: yes
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class A {
|
||||
get #a() { return 1; }
|
||||
set #a(val) { }
|
||||
|
||||
constructor() {
|
||||
this.#a++;
|
||||
this.#a = 1;
|
||||
return this.#a;
|
||||
}
|
||||
}
|
||||
var test = A;
|
||||
new test;
|
||||
"
|
||||
frame size: 6
|
||||
parameter count: 1
|
||||
bytecode array length: 95
|
||||
bytecodes: [
|
||||
/* 67 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 76 S> */ B(LdaCurrentContextSlot), U8(4),
|
||||
B(Star), R(3),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
/* 81 E> */ B(LdaKeyedProperty), R(this), U8(0),
|
||||
B(CallRuntime), U16(Runtime::kLoadPrivateGetter), R(3), U8(1),
|
||||
B(Star), R(4),
|
||||
B(CallProperty0), R(4), R(this), U8(2),
|
||||
B(Inc), U8(4),
|
||||
B(Star), R(4),
|
||||
/* 83 E> */ B(CallRuntime), U16(Runtime::kLoadPrivateSetter), R(3), U8(1),
|
||||
B(Star), R(5),
|
||||
B(CallProperty1), R(5), R(this), R(4), U8(5),
|
||||
/* 91 S> */ B(LdaSmi), I8(1),
|
||||
B(Star), R(2),
|
||||
B(LdaCurrentContextSlot), U8(4),
|
||||
B(Star), R(4),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
/* 96 E> */ B(LdaKeyedProperty), R(this), U8(7),
|
||||
B(CallRuntime), U16(Runtime::kLoadPrivateSetter), R(4), U8(1),
|
||||
B(Star), R(5),
|
||||
B(CallProperty1), R(5), R(this), R(2), U8(9),
|
||||
/* 108 S> */ B(LdaCurrentContextSlot), U8(4),
|
||||
B(Star), R(3),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
/* 120 E> */ B(LdaKeyedProperty), R(this), U8(11),
|
||||
B(CallRuntime), U16(Runtime::kLoadPrivateGetter), R(3), U8(1),
|
||||
B(Star), R(4),
|
||||
B(CallProperty0), R(4), R(this), U8(13),
|
||||
/* 123 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class B {
|
||||
get #b() { return 1; }
|
||||
constructor() { this.#b++; }
|
||||
}
|
||||
var test = B;
|
||||
new test;
|
||||
"
|
||||
frame size: 4
|
||||
parameter count: 1
|
||||
bytecode array length: 29
|
||||
bytecodes: [
|
||||
/* 48 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(263),
|
||||
B(Star), R(2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(3),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
|
||||
B(Throw),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#b"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class C {
|
||||
set #c(val) { }
|
||||
constructor() { this.#c++; }
|
||||
}
|
||||
var test = C;
|
||||
new test;
|
||||
"
|
||||
frame size: 4
|
||||
parameter count: 1
|
||||
bytecode array length: 29
|
||||
bytecodes: [
|
||||
/* 41 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(262),
|
||||
B(Star), R(2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(3),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
|
||||
B(Throw),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#c"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class D {
|
||||
get #d() { return 1; }
|
||||
constructor() { this.#d = 1; }
|
||||
}
|
||||
var test = D;
|
||||
new test;
|
||||
"
|
||||
frame size: 4
|
||||
parameter count: 1
|
||||
bytecode array length: 29
|
||||
bytecodes: [
|
||||
/* 48 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 53 S> */ B(Wide), B(LdaSmi), I16(263),
|
||||
B(Star), R(2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(3),
|
||||
/* 61 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
|
||||
B(Throw),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#d"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class E {
|
||||
set #e(val) { }
|
||||
constructor() { this.#e; }
|
||||
}
|
||||
var test = E;
|
||||
new test;
|
||||
"
|
||||
frame size: 5
|
||||
parameter count: 1
|
||||
bytecode array length: 29
|
||||
bytecodes: [
|
||||
/* 41 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 46 S> */ B(Wide), B(LdaSmi), I16(262),
|
||||
B(Star), R(3),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(4),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(3), U8(2),
|
||||
B(Throw),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#e"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
@ -0,0 +1,104 @@
|
||||
#
|
||||
# Autogenerated by generate-bytecode-expectations.
|
||||
#
|
||||
|
||||
---
|
||||
wrap: no
|
||||
test function name: test
|
||||
private methods: yes
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class A {
|
||||
#a() { return 1; }
|
||||
constructor() { return this.#a(); }
|
||||
}
|
||||
|
||||
var test = A;
|
||||
new A;
|
||||
"
|
||||
frame size: 3
|
||||
parameter count: 1
|
||||
bytecode array length: 28
|
||||
bytecodes: [
|
||||
/* 44 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 49 S> */ B(LdaCurrentContextSlot), U8(5),
|
||||
/* 61 E> */ B(LdaKeyedProperty), R(this), U8(0),
|
||||
B(LdaCurrentContextSlot), U8(4),
|
||||
B(Star), R(2),
|
||||
/* 63 E> */ B(CallAnyReceiver), R(2), R(this), U8(1), U8(2),
|
||||
/* 66 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class B {
|
||||
#b() { return 1; }
|
||||
constructor() { this.#b = 1; }
|
||||
}
|
||||
|
||||
var test = B;
|
||||
new test;
|
||||
"
|
||||
frame size: 4
|
||||
parameter count: 1
|
||||
bytecode array length: 29
|
||||
bytecodes: [
|
||||
/* 44 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 49 S> */ B(Wide), B(LdaSmi), I16(261),
|
||||
B(Star), R(2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(3),
|
||||
/* 57 E> */ B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
|
||||
B(Throw),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#b"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
||||
---
|
||||
snippet: "
|
||||
class C {
|
||||
#c() { return 1; }
|
||||
constructor() { this.#c++; }
|
||||
}
|
||||
|
||||
var test = C;
|
||||
new test;
|
||||
"
|
||||
frame size: 4
|
||||
parameter count: 1
|
||||
bytecode array length: 29
|
||||
bytecodes: [
|
||||
/* 44 E> */ B(StackCheck),
|
||||
B(LdaCurrentContextSlot), U8(5),
|
||||
B(Star), R(1),
|
||||
B(Mov), R(this), R(0),
|
||||
B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(2),
|
||||
/* 49 S> */ B(Wide), B(LdaSmi), I16(261),
|
||||
B(Star), R(2),
|
||||
B(LdaConstant), U8(0),
|
||||
B(Star), R(3),
|
||||
B(CallRuntime), U16(Runtime::kNewTypeError), R(2), U8(2),
|
||||
B(Throw),
|
||||
]
|
||||
constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["#c"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
|
@ -11,57 +11,43 @@ snippet: "
|
||||
{
|
||||
class A {
|
||||
#a() { return 1; }
|
||||
callA() { return this.#a(); }
|
||||
}
|
||||
|
||||
const a = new A;
|
||||
a.callA();
|
||||
}
|
||||
"
|
||||
frame size: 9
|
||||
frame size: 7
|
||||
parameter count: 1
|
||||
bytecode array length: 80
|
||||
bytecode array length: 55
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(CreateBlockContext), U8(0),
|
||||
B(PushContext), R(3),
|
||||
B(PushContext), R(2),
|
||||
B(LdaTheHole),
|
||||
B(Star), R(7),
|
||||
B(Star), R(6),
|
||||
B(CreateClosure), U8(2), U8(0), U8(2),
|
||||
B(Star), R(4),
|
||||
B(Star), R(3),
|
||||
B(LdaConstant), U8(1),
|
||||
B(Star), R(5),
|
||||
B(Star), R(4),
|
||||
B(CreateClosure), U8(3), U8(1), U8(2),
|
||||
B(StaCurrentContextSlot), U8(4),
|
||||
B(CreateClosure), U8(4), U8(2), U8(2),
|
||||
B(Star), R(8),
|
||||
B(Mov), R(4), R(6),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4),
|
||||
B(Mov), R(3), R(5),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(3),
|
||||
B(Star), R(4),
|
||||
B(Mov), R(5), R(1),
|
||||
B(LdaConstant), U8(4),
|
||||
B(Star), R(5),
|
||||
B(Mov), R(6), R(2),
|
||||
B(LdaConstant), U8(5),
|
||||
B(Star), R(6),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(6), U8(1),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(5), U8(1),
|
||||
B(StaCurrentContextSlot), U8(5),
|
||||
B(PopContext), R(3),
|
||||
B(Mov), R(2), R(0),
|
||||
/* 122 S> */ B(Ldar), R(0),
|
||||
/* 122 E> */ B(Construct), R(0), R(0), U8(0), U8(0),
|
||||
B(Star), R(1),
|
||||
/* 133 S> */ B(LdaNamedProperty), R(1), U8(6), U8(2),
|
||||
B(Star), R(3),
|
||||
/* 133 E> */ B(CallProperty0), R(3), R(1), U8(4),
|
||||
B(PopContext), R(2),
|
||||
B(Mov), R(1), R(0),
|
||||
B(LdaUndefined),
|
||||
/* 144 S> */ B(Return),
|
||||
/* 77 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
SCOPE_INFO_TYPE,
|
||||
FIXED_ARRAY_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["A"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["callA"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
@ -71,89 +57,70 @@ snippet: "
|
||||
{
|
||||
class D {
|
||||
#d() { return 1; }
|
||||
callD() { return this.#d(); }
|
||||
}
|
||||
|
||||
class E extends D {
|
||||
#e() { return 2; }
|
||||
callE() { return this.callD() + this.#e(); }
|
||||
}
|
||||
|
||||
const e = new E;
|
||||
e.callE();
|
||||
}
|
||||
"
|
||||
frame size: 11
|
||||
frame size: 9
|
||||
parameter count: 1
|
||||
bytecode array length: 138
|
||||
bytecode array length: 107
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(CreateBlockContext), U8(0),
|
||||
B(PushContext), R(5),
|
||||
B(PushContext), R(4),
|
||||
B(LdaTheHole),
|
||||
B(Star), R(9),
|
||||
B(Star), R(8),
|
||||
B(CreateClosure), U8(2), U8(0), U8(2),
|
||||
B(Star), R(6),
|
||||
B(Star), R(5),
|
||||
B(LdaConstant), U8(1),
|
||||
B(Star), R(7),
|
||||
B(Star), R(6),
|
||||
B(CreateClosure), U8(3), U8(1), U8(2),
|
||||
B(StaCurrentContextSlot), U8(4),
|
||||
B(CreateClosure), U8(4), U8(2), U8(2),
|
||||
B(Star), R(10),
|
||||
B(Mov), R(6), R(8),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(7), U8(4),
|
||||
B(Star), R(7),
|
||||
B(Mov), R(8), R(4),
|
||||
B(LdaConstant), U8(5),
|
||||
B(Star), R(8),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(8), U8(1),
|
||||
B(StaCurrentContextSlot), U8(5),
|
||||
B(PopContext), R(5),
|
||||
B(Mov), R(4), R(0),
|
||||
/* 38 E> */ B(CreateBlockContext), U8(6),
|
||||
B(PushContext), R(5),
|
||||
/* 128 E> */ B(CreateClosure), U8(8), U8(3), U8(2),
|
||||
B(Mov), R(5), R(7),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(3),
|
||||
B(Star), R(6),
|
||||
B(LdaConstant), U8(7),
|
||||
B(Mov), R(7), R(3),
|
||||
B(LdaConstant), U8(4),
|
||||
B(Star), R(7),
|
||||
B(CreateClosure), U8(9), U8(4), U8(2),
|
||||
B(StaCurrentContextSlot), U8(4),
|
||||
B(CreateClosure), U8(10), U8(5), U8(2),
|
||||
B(Star), R(10),
|
||||
B(Mov), R(6), R(8),
|
||||
B(Mov), R(4), R(9),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(7), U8(4),
|
||||
B(Star), R(7),
|
||||
B(Mov), R(8), R(3),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(8),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(8), U8(1),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(7), U8(1),
|
||||
B(StaCurrentContextSlot), U8(5),
|
||||
B(PopContext), R(5),
|
||||
B(Mov), R(3), R(1),
|
||||
/* 221 S> */ B(Ldar), R(1),
|
||||
/* 221 E> */ B(Construct), R(1), R(0), U8(0), U8(0),
|
||||
B(Star), R(2),
|
||||
/* 232 S> */ B(LdaNamedProperty), R(2), U8(12), U8(2),
|
||||
B(PopContext), R(4),
|
||||
B(Mov), R(3), R(0),
|
||||
/* 38 E> */ B(CreateBlockContext), U8(5),
|
||||
B(PushContext), R(4),
|
||||
/* 93 E> */ B(CreateClosure), U8(7), U8(2), U8(2),
|
||||
B(Star), R(5),
|
||||
/* 232 E> */ B(CallProperty0), R(5), R(2), U8(4),
|
||||
B(LdaConstant), U8(6),
|
||||
B(Star), R(6),
|
||||
B(CreateClosure), U8(8), U8(3), U8(2),
|
||||
B(StaCurrentContextSlot), U8(4),
|
||||
B(Mov), R(5), R(7),
|
||||
B(Mov), R(3), R(8),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(3),
|
||||
B(Star), R(6),
|
||||
B(Mov), R(7), R(2),
|
||||
B(LdaConstant), U8(9),
|
||||
B(Star), R(7),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(7), U8(1),
|
||||
B(StaCurrentContextSlot), U8(5),
|
||||
B(PopContext), R(4),
|
||||
B(Mov), R(2), R(1),
|
||||
B(LdaUndefined),
|
||||
/* 243 S> */ B(Return),
|
||||
/* 126 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
SCOPE_INFO_TYPE,
|
||||
FIXED_ARRAY_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["D"],
|
||||
SCOPE_INFO_TYPE,
|
||||
FIXED_ARRAY_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["E"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["callE"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
||||
@ -164,14 +131,12 @@ snippet: "
|
||||
class A { foo() {} }
|
||||
class C extends A {
|
||||
#m() { return super.foo; }
|
||||
fn() { return this.#m(); }
|
||||
}
|
||||
new C().fn();
|
||||
}
|
||||
"
|
||||
frame size: 10
|
||||
parameter count: 1
|
||||
bytecode array length: 131
|
||||
bytecode array length: 106
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(CreateBlockContext), U8(0),
|
||||
@ -198,31 +163,23 @@ bytecodes: [
|
||||
B(Star), R(6),
|
||||
B(CreateClosure), U8(7), U8(3), U8(2),
|
||||
B(StaCurrentContextSlot), U8(4),
|
||||
B(CreateClosure), U8(8), U8(4), U8(2),
|
||||
B(Star), R(9),
|
||||
B(Mov), R(5), R(7),
|
||||
B(Mov), R(3), R(8),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(4),
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(6), U8(3),
|
||||
B(Star), R(6),
|
||||
B(Mov), R(7), R(2),
|
||||
B(LdaConstant), U8(9),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(7),
|
||||
B(CallRuntime), U16(Runtime::kCreatePrivateNameSymbol), R(7), U8(1),
|
||||
B(StaCurrentContextSlot), U8(5),
|
||||
B(LdaCurrentContextSlot), U8(4),
|
||||
B(Star), R(8),
|
||||
B(Ldar), R(6),
|
||||
B(StaNamedProperty), R(8), U8(10), U8(0),
|
||||
B(StaNamedProperty), R(8), U8(9), U8(0),
|
||||
B(PopContext), R(4),
|
||||
B(Mov), R(2), R(1),
|
||||
/* 149 S> */ B(Ldar), R(1),
|
||||
/* 149 E> */ B(Construct), R(5), R(0), U8(0), U8(2),
|
||||
B(Star), R(5),
|
||||
/* 157 E> */ B(LdaNamedProperty), R(5), U8(11), U8(4),
|
||||
B(Star), R(4),
|
||||
/* 157 E> */ B(CallProperty0), R(4), R(5), U8(6),
|
||||
B(LdaUndefined),
|
||||
/* 165 S> */ B(Return),
|
||||
/* 118 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
SCOPE_INFO_TYPE,
|
||||
@ -233,10 +190,8 @@ constant pool: [
|
||||
FIXED_ARRAY_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
SHARED_FUNCTION_INFO_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["C"],
|
||||
SYMBOL_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["fn"],
|
||||
]
|
||||
handlers: [
|
||||
]
|
@ -2758,7 +2758,7 @@ TEST(PrivateClassFields) {
|
||||
LoadGolden("PrivateClassFields.golden")));
|
||||
}
|
||||
|
||||
TEST(PrivateMethods) {
|
||||
TEST(PrivateMethodDeclaration) {
|
||||
bool old_methods_flag = i::FLAG_harmony_private_methods;
|
||||
i::FLAG_harmony_private_methods = true;
|
||||
InitializedIgnitionHandleScope scope;
|
||||
@ -2768,43 +2768,124 @@ TEST(PrivateMethods) {
|
||||
"{\n"
|
||||
" class A {\n"
|
||||
" #a() { return 1; }\n"
|
||||
" callA() { return this.#a(); }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" const a = new A;\n"
|
||||
" a.callA();\n"
|
||||
"}\n",
|
||||
|
||||
"{\n"
|
||||
" class D {\n"
|
||||
" #d() { return 1; }\n"
|
||||
" callD() { return this.#d(); }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" class E extends D {\n"
|
||||
" #e() { return 2; }\n"
|
||||
" callE() { return this.callD() + this.#e(); }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" const e = new E;\n"
|
||||
" e.callE();\n"
|
||||
"}\n",
|
||||
|
||||
"{\n"
|
||||
" class A { foo() {} }\n"
|
||||
" class C extends A {\n"
|
||||
" #m() { return super.foo; }\n"
|
||||
" fn() { return this.#m(); }\n"
|
||||
" }\n"
|
||||
" new C().fn();\n"
|
||||
"}\n"};
|
||||
|
||||
CHECK(CompareTexts(BuildActual(printer, snippets),
|
||||
LoadGolden("PrivateMethods.golden")));
|
||||
LoadGolden("PrivateMethodDeclaration.golden")));
|
||||
i::FLAG_harmony_private_methods = old_methods_flag;
|
||||
}
|
||||
|
||||
TEST(PrivateAccessors) {
|
||||
TEST(PrivateMethodAccess) {
|
||||
bool old_methods_flag = i::FLAG_harmony_private_methods;
|
||||
i::FLAG_harmony_private_methods = true;
|
||||
InitializedIgnitionHandleScope scope;
|
||||
BytecodeExpectationsPrinter printer(CcTest::isolate());
|
||||
printer.set_wrap(false);
|
||||
printer.set_test_function_name("test");
|
||||
|
||||
const char* snippets[] = {
|
||||
"class A {\n"
|
||||
" #a() { return 1; }\n"
|
||||
" constructor() { return this.#a(); }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"var test = A;\n"
|
||||
"new A;\n",
|
||||
|
||||
"class B {\n"
|
||||
" #b() { return 1; }\n"
|
||||
" constructor() { this.#b = 1; }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"var test = B;\n"
|
||||
"new test;\n",
|
||||
|
||||
"class C {\n"
|
||||
" #c() { return 1; }\n"
|
||||
" constructor() { this.#c++; }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"var test = C;\n"
|
||||
"new test;\n"};
|
||||
|
||||
CHECK(CompareTexts(BuildActual(printer, snippets),
|
||||
LoadGolden("PrivateMethodAccess.golden")));
|
||||
i::FLAG_harmony_private_methods = old_methods_flag;
|
||||
}
|
||||
|
||||
TEST(PrivateAccessorAccess) {
|
||||
bool old_methods_flag = i::FLAG_harmony_private_methods;
|
||||
i::FLAG_harmony_private_methods = true;
|
||||
InitializedIgnitionHandleScope scope;
|
||||
BytecodeExpectationsPrinter printer(CcTest::isolate());
|
||||
printer.set_wrap(false);
|
||||
printer.set_test_function_name("test");
|
||||
|
||||
const char* snippets[] = {
|
||||
"class A {\n"
|
||||
" get #a() { return 1; }\n"
|
||||
" set #a(val) { }\n"
|
||||
"\n"
|
||||
" constructor() {\n"
|
||||
" this.#a++;\n"
|
||||
" this.#a = 1;\n"
|
||||
" return this.#a;\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"var test = A;\n"
|
||||
"new test;\n",
|
||||
|
||||
"class B {\n"
|
||||
" get #b() { return 1; }\n"
|
||||
" constructor() { this.#b++; }\n"
|
||||
"}\n"
|
||||
"var test = B;\n"
|
||||
"new test;\n",
|
||||
|
||||
"class C {\n"
|
||||
" set #c(val) { }\n"
|
||||
" constructor() { this.#c++; }\n"
|
||||
"}\n"
|
||||
"var test = C;\n"
|
||||
"new test;\n",
|
||||
|
||||
"class D {\n"
|
||||
" get #d() { return 1; }\n"
|
||||
" constructor() { this.#d = 1; }\n"
|
||||
"}\n"
|
||||
"var test = D;\n"
|
||||
"new test;\n",
|
||||
|
||||
"class E {\n"
|
||||
" set #e(val) { }\n"
|
||||
" constructor() { this.#e; }\n"
|
||||
"}\n"
|
||||
"var test = E;\n"
|
||||
"new test;\n"};
|
||||
|
||||
CHECK(CompareTexts(BuildActual(printer, snippets),
|
||||
LoadGolden("PrivateAccessorAccess.golden")));
|
||||
i::FLAG_harmony_private_methods = old_methods_flag;
|
||||
}
|
||||
|
||||
TEST(PrivateAccessorDeclaration) {
|
||||
bool old_methods_flag = i::FLAG_harmony_private_methods;
|
||||
i::FLAG_harmony_private_methods = true;
|
||||
InitializedIgnitionHandleScope scope;
|
||||
@ -2859,7 +2940,7 @@ TEST(PrivateAccessors) {
|
||||
"}\n"};
|
||||
|
||||
CHECK(CompareTexts(BuildActual(printer, snippets),
|
||||
LoadGolden("PrivateAccessors.golden")));
|
||||
LoadGolden("PrivateAccessorDeclaration.golden")));
|
||||
i::FLAG_harmony_private_methods = old_methods_flag;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
set #foo(val) {}
|
||||
constructor() {
|
||||
this.#foo++;
|
||||
}
|
||||
}
|
||||
|
||||
new C();
|
@ -0,0 +1,9 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:10: TypeError: '#foo' was defined without a getter
|
||||
this.#foo++;
|
||||
^
|
||||
TypeError: '#foo' was defined without a getter
|
||||
at new C (*%(basename)s:10:5)
|
||||
at *%(basename)s:14:1
|
@ -0,0 +1,19 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
set #a(val) {}
|
||||
setA(obj, val) { obj.#a = val; }
|
||||
|
||||
constructor() {
|
||||
class D {
|
||||
get #a() {}
|
||||
}
|
||||
this.setA(new D(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
new C;
|
@ -0,0 +1,10 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:9: TypeError: Cannot read private member C from an object whose class did not declare it
|
||||
setA(obj, val) { obj.#a = val; }
|
||||
^
|
||||
TypeError: Cannot read private member C from an object whose class did not declare it
|
||||
at C.setA (*%(basename)s:9:24)
|
||||
at new C (*%(basename)s:15:10)
|
||||
at *%(basename)s:19:1
|
@ -0,0 +1,13 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
set #a(val) {}
|
||||
constructor() {
|
||||
const a = this.#a;
|
||||
}
|
||||
}
|
||||
new C;
|
@ -0,0 +1,9 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:10: TypeError: '#a' was defined without a getter
|
||||
const a = this.#a;
|
||||
^
|
||||
TypeError: '#a' was defined without a getter
|
||||
at new C (*%(basename)s:10:15)
|
||||
at *%(basename)s:13:1
|
@ -0,0 +1,13 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
get #a() {}
|
||||
constructor() {
|
||||
this.#a = 1;
|
||||
}
|
||||
}
|
||||
new C;
|
@ -0,0 +1,9 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:10: TypeError: '#a' was defined without a setter
|
||||
this.#a = 1;
|
||||
^
|
||||
TypeError: '#a' was defined without a setter
|
||||
at new C (*%(basename)s:10:13)
|
||||
at *%(basename)s:13:1
|
@ -0,0 +1,14 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
get #foo() {}
|
||||
constructor() {
|
||||
this.#foo++;
|
||||
}
|
||||
}
|
||||
|
||||
new C();
|
@ -0,0 +1,9 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:10: TypeError: '#foo' was defined without a setter
|
||||
this.#foo++;
|
||||
^
|
||||
TypeError: '#foo' was defined without a setter
|
||||
at new C (*%(basename)s:10:5)
|
||||
at *%(basename)s:14:1
|
@ -0,0 +1,19 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
get #a() {}
|
||||
getA(obj) { return obj.#a; }
|
||||
|
||||
constructor() {
|
||||
class D {
|
||||
set #a(val) {}
|
||||
}
|
||||
this.getA(new D());
|
||||
}
|
||||
}
|
||||
|
||||
new C;
|
@ -0,0 +1,10 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:9: TypeError: Cannot read private member C from an object whose class did not declare it
|
||||
getA(obj) { return obj.#a; }
|
||||
^
|
||||
TypeError: Cannot read private member C from an object whose class did not declare it
|
||||
at C.getA (*%(basename)s:9:26)
|
||||
at new C (*%(basename)s:15:10)
|
||||
at *%(basename)s:19:1
|
@ -0,0 +1,13 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
// Flags: --harmony-private-methods
|
||||
|
||||
class C {
|
||||
get #a() {}
|
||||
constructor() {
|
||||
this.#a = 1;
|
||||
}
|
||||
}
|
||||
new C;
|
@ -0,0 +1,9 @@
|
||||
# Copyright 2019 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.
|
||||
*%(basename)s:10: TypeError: '#a' was defined without a setter
|
||||
this.#a = 1;
|
||||
^
|
||||
TypeError: '#a' was defined without a setter
|
||||
at new C (*%(basename)s:10:13)
|
||||
at *%(basename)s:13:1
|
@ -1,5 +1,5 @@
|
||||
*%(basename)s:9: TypeError: Read of private field #a from an object which did not contain the field
|
||||
*%(basename)s:9: TypeError: Cannot read private member #a from an object whose class did not declare it
|
||||
[o.#a](){}
|
||||
^
|
||||
TypeError: Read of private field #a from an object which did not contain the field
|
||||
TypeError: Cannot read private member #a from an object whose class did not declare it
|
||||
at *%(basename)s:9:8
|
||||
|
@ -1,6 +1,6 @@
|
||||
*%(basename)s:8: TypeError: Write of private field #x to an object which did not contain the field
|
||||
*%(basename)s:8: TypeError: Cannot write private member #x to an object whose class did not declare it
|
||||
({}).#x = 1;
|
||||
^
|
||||
TypeError: Write of private field #x to an object which did not contain the field
|
||||
TypeError: Cannot write private member #x to an object whose class did not declare it
|
||||
at new X (*%(basename)s:8:13)
|
||||
at *%(basename)s:12:1
|
@ -1,6 +1,6 @@
|
||||
*%(basename)s:7: TypeError: Read of private field #x from an object which did not contain the field
|
||||
*%(basename)s:7: TypeError: Cannot read private member #x from an object whose class did not declare it
|
||||
eq(o) { return this.#x === o.#x; }
|
||||
^
|
||||
TypeError: Read of private field #x from an object which did not contain the field
|
||||
TypeError: Cannot read private member #x from an object whose class did not declare it
|
||||
at X.eq (*%(basename)s:7:32)
|
||||
at *%(basename)s:10:9
|
@ -1,6 +1,6 @@
|
||||
*%(basename)s:7: TypeError: Write of private field #x to an object which did not contain the field
|
||||
*%(basename)s:7: TypeError: Cannot write private member #x to an object whose class did not declare it
|
||||
setX(o, val) { o.#x = val; }
|
||||
^
|
||||
TypeError: Write of private field #x to an object which did not contain the field
|
||||
TypeError: Cannot write private member #x to an object whose class did not declare it
|
||||
at X.setX (*%(basename)s:7:23)
|
||||
at *%(basename)s:10:9
|
@ -8,12 +8,40 @@
|
||||
|
||||
// Complementary private accessors.
|
||||
{
|
||||
let store = 1;
|
||||
class C {
|
||||
get #a() { }
|
||||
set #a(val) { }
|
||||
get #a() { return store; }
|
||||
set #a(val) { store = val; }
|
||||
incA() { this.#a++; } // CountOperation
|
||||
setA(val) { this.#a = val; }
|
||||
getA() { return this.#a; }
|
||||
}
|
||||
|
||||
new C;
|
||||
const c = new C;
|
||||
assertEquals(store, c.getA());
|
||||
assertEquals(1, c.getA());
|
||||
c.setA(2);
|
||||
assertEquals(store, c.getA());
|
||||
assertEquals(2, c.getA());
|
||||
c.incA();
|
||||
assertEquals(store, c.getA());
|
||||
assertEquals(3, c.getA());
|
||||
}
|
||||
|
||||
// Compound assignment.
|
||||
{
|
||||
let store;
|
||||
class A {
|
||||
get #a() { return store; }
|
||||
set #a(val) { store = val; }
|
||||
getA() { return this.#a; }
|
||||
constructor(val) {
|
||||
({ y: this.#a } = val);
|
||||
}
|
||||
}
|
||||
|
||||
const a = new A({y: 'test'});
|
||||
assertEquals('test', a.getA());
|
||||
}
|
||||
|
||||
// Accessing super in private accessors.
|
||||
@ -39,13 +67,20 @@
|
||||
// Nested private accessors.
|
||||
{
|
||||
class C {
|
||||
a() { this.#a; }
|
||||
get #a() {
|
||||
class D { get #a() { } }
|
||||
let storeD = 'd';
|
||||
class D {
|
||||
// Shadows outer #a
|
||||
get #a() { return storeD; }
|
||||
getD() { return this.#a; }
|
||||
}
|
||||
return new D;
|
||||
}
|
||||
getA() {
|
||||
return this.#a;
|
||||
}
|
||||
}
|
||||
new C().a();
|
||||
assertEquals('d', new C().getA().getD());
|
||||
}
|
||||
|
||||
// Duplicate private accessors.
|
||||
|
Loading…
Reference in New Issue
Block a user