Ignore:
Timestamp:
Feb 15, 2021, 2:40:26 PM (4 years ago)
Author:
Caio Lima
Message:

[ESNext] Implement private accessors
https://bugs.webkit.org/show_bug.cgi?id=194435

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/private-accesor-duplicate-name-early-errors.js: Added.
  • stress/private-getter-brand-check.js: Added.
  • stress/private-getter-inner-class.js: Added.
  • stress/private-members-get-and-set.js: Added.
  • stress/private-methods-and-accessors-postfix-node.js: Added.
  • stress/private-methods-and-accessors-prefix-node.js: Added.
  • stress/private-names-available-on-direct-eval.js:
  • stress/private-names-available-on-eval-during-field-initialization.js: Copied from JSTests/stress/private-names-available-on-direct-eval.js.
  • stress/private-setter-brand-check.js: Added.
  • stress/private-setter-inner-class.js: Added.
  • test262/config.yaml:
  • test262/expectations.yaml:

Source/JavaScriptCore:

This patch is implementing support for instance private getters and
setters following the proposal on https://tc39.es/proposal-private-methods.
Private accessors also use the private brand check mechanism of
private methods, which means that we are using both
op_set_private_brand and op_check_private_brand to perform brand
checks. Accessors are also stored on class lexical scope as a pair of
getter and setter. This is done creating a new JSObject and
storing the getter on get property, and setter on set
property. This is designed in such way that we can always hit IC fast
path on get_by_id_direct to access the property, and also to allow
constant folding of accessors on DFG/FTL, since acessors objects are
going to be constant once created.

For reference, we have the following bytecode for a private getter
access:

`
class C {

get #m() {...}
access() {

return this.#m;

}

}
`

Bytecode for class declaration:

`
...
new_object dst:loc12, inlineCapacity:2 this is the object to store getter and setter pair
new_func_exp dst:loc13, scope:loc4, functionDecl:"get #m() {...}"
put_by_id base:loc13, property:@homeObject, value:loc11, flags:Strict
put_by_id base:loc12, property:@get, value:loc13, flags:IsDirect|Strict
put_to_scope scope:loc4, var:#m, value:loc12
loc4 is the class lexical scope
...

`

Bytecode for access():

`
...
resolve_scope dst:loc7, scope:loc4, var:"#m", resolveType:GlobalProperty, localScopeDepth:0
get_from_scope dst:loc8, scope:loc7, var:@privateBrand
check_private_brand base:this, brand:loc8
get_from_scope dst:loc8, scope:loc7, var:"#m"
get_by_id_direct dst:loc9, base:loc8, property:@get
mov dst:loc10, src:this
call dst:loc6, callee:loc9, argc:1, argv:16
...

`

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::instantiateLexicalVariables):
(JSC::BytecodeGenerator::getPrivateTraits):
(JSC::BytecodeGenerator::getAvailablePrivateAccessNames):
(JSC::BytecodeGenerator::isPrivateMethod): Deleted.

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::PropertyListNode::emitBytecode):
(JSC::PropertyListNode::emitPutConstantProperty):
(JSC::BaseDotNode::emitGetPropertyValue):
(JSC::BaseDotNode::emitPutProperty):
(JSC::PostfixNode::emitDot):
(JSC::PrefixNode::emitDot):

  • parser/Nodes.h:
  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseClass):
(JSC::Parser<LexerType>::parseGetterSetter):

  • parser/Parser.h:

(JSC::Scope::declarePrivateSetter):
(JSC::Scope::declarePrivateGetter):

  • parser/VariableEnvironment.cpp:

(JSC::VariableEnvironment::declarePrivateAccessor):
(JSC::VariableEnvironment::declarePrivateSetter):
(JSC::VariableEnvironment::declarePrivateGetter):

  • parser/VariableEnvironment.h:

(JSC::VariableEnvironmentEntry::isPrivateSetter const):
(JSC::VariableEnvironmentEntry::isPrivateGetter const):
(JSC::VariableEnvironmentEntry::setIsPrivateSetter):
(JSC::VariableEnvironmentEntry::setIsPrivateGetter):
(JSC::PrivateNameEntry::isSetter const):
(JSC::PrivateNameEntry::isGetter const):
(JSC::PrivateNameEntry::isField const):
(JSC::PrivateNameEntry::isPrivateMethodOrAcessor const):
(JSC::VariableEnvironment::declarePrivateSetter):
(JSC::VariableEnvironment::declarePrivateGetter):

  • runtime/ExceptionHelpers.cpp:

(JSC::createPrivateMethodAccessError):

Location:
trunk/Source/JavaScriptCore/bytecompiler
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r272580 r272883  
    5757#include "UnlinkedProgramCodeBlock.h"
    5858#include <wtf/BitVector.h>
     59#include <wtf/HashSet.h>
    5960#include <wtf/Optional.h>
    60 #include <wtf/SmallPtrSet.h>
    6161#include <wtf/StdLibExtras.h>
    6262#include <wtf/text/WTFString.h>
     
    19011901            // FIXME: only do this if there is an eval() within a nested scope --- otherwise it isn't needed.
    19021902            // https://bugs.webkit.org/show_bug.cgi?id=206663
    1903             if (entry.value.isPrivateField())
    1904                 symbolTable->addPrivateName(entry.key.get(), PrivateNameEntry(PrivateNameEntry::Traits::IsDeclared));
    1905             else if (entry.value.isPrivateMethod())
    1906                 symbolTable->addPrivateName(entry.key.get(), PrivateNameEntry(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsMethod));
     1903           
     1904            const PrivateNameEnvironment* privateEnvironment = lexicalVariables.privateNameEnvironment();
     1905            if (!privateEnvironment)
     1906                continue;
     1907
     1908            auto findResult = privateEnvironment->find(entry.key.get());
     1909
     1910            if (findResult == privateEnvironment->end())
     1911                continue;
     1912
     1913            symbolTable->addPrivateName(findResult->key.get(), findResult->value);
    19071914        }
    19081915    }
     
    29322939}
    29332940
    2934 bool BytecodeGenerator::isPrivateMethod(const Identifier& ident)
     2941// This should be called only with PrivateNames available.
     2942PrivateNameEntry BytecodeGenerator::getPrivateTraits(const Identifier& ident)
    29352943{
    29362944    for (unsigned i = m_privateNamesStack.size(); i--; ) {
     
    29382946        auto it = map.find(ident.impl());
    29392947        if (it != map.end())
    2940             return it->value.isMethod();
    2941     }
    2942 
    2943     return false;
     2948            return it->value;
     2949    }
     2950
     2951    RELEASE_ASSERT_NOT_REACHED();
     2952    return PrivateNameEntry();
    29442953}
    29452954
     
    29822991{
    29832992    PrivateNameEnvironment result;
    2984     SmallPtrSet<UniquedStringImpl*, 16> excludedNames;
     2993    HashSet<UniquedStringImpl*> excludedNames;
    29852994    for (unsigned i = m_privateNamesStack.size(); i--; ) {
    29862995        auto& map = m_privateNamesStack[i];
    29872996        for (auto& entry : map)  {
    2988             if (entry.value.isPrivateMethodOrAcessor()) {
    2989                 if (!excludedNames.contains(entry.key.get())) {
    2990                     result.add(entry.key, entry.value);
    2991                     excludedNames.add(entry.key.get());
    2992                 }
    2993             } else
    2994                 excludedNames.add(entry.key.get());
     2997            auto addResult = excludedNames.add(entry.key.get());
     2998            if (addResult.isNewEntry)
     2999                result.add(entry.key, entry.value);
    29953000        }
    29963001    }
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r272580 r272883  
    12641264        }
    12651265
    1266         bool isPrivateMethod(const Identifier&);
     1266        PrivateNameEntry getPrivateTraits(const Identifier&);
    12671267
    12681268        void pushPrivateAccessNames(const PrivateNameEnvironment*);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r272580 r272883  
    580580RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dstOrConstructor, RegisterID* prototype, Vector<JSTextPosition>* instanceFieldLocations, Vector<JSTextPosition>* staticFieldLocations)
    581581{
     582    using GetterSetterPair = std::pair<PropertyNode*, PropertyNode*>;
     583    using GetterSetterMap = HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash>;
     584
     585    if (hasPrivateAccessors()) {
     586        GetterSetterMap privateAccessorMap;
     587
     588        for (PropertyListNode* propertyList = this; propertyList; propertyList = propertyList->m_next) {
     589            if (!(propertyList->m_node->type() & (PropertyNode::PrivateGetter | PropertyNode::PrivateSetter)))
     590                continue;
     591
     592            // We group private getters and setters to store them in a object
     593            GetterSetterPair pair(propertyList->m_node, static_cast<PropertyNode*>(nullptr));
     594            GetterSetterMap::AddResult result = privateAccessorMap.add(propertyList->m_node->name()->impl(), pair);
     595            auto& resultPair = result.iterator->value;
     596            // If the map already contains an element with node->name(),
     597            // we need to store this node in the second part.
     598            if (!result.isNewEntry)
     599                resultPair.second = propertyList->m_node;
     600            continue;
     601        }
     602
     603        // Then we declare private accessors
     604        for (auto& it : privateAccessorMap) {
     605            // FIXME: Use GetterSetter to store private accessors
     606            // https://bugs.webkit.org/show_bug.cgi?id=221915
     607            RefPtr<RegisterID> getterSetterObj = generator.emitNewObject(generator.newTemporary());
     608            GetterSetterPair pair = it.value;
     609
     610            auto emitPutAccessor = [&] (PropertyNode* propertyNode) {
     611                RegisterID* base = propertyNode->isInstanceClassProperty() ? prototype : dstOrConstructor;
     612
     613                RefPtr<RegisterID> value = generator.emitNode(propertyNode->m_assign);
     614                if (propertyNode->needsSuperBinding())
     615                    emitPutHomeObject(generator, value.get(), base);
     616                auto setterOrGetterIdent = propertyNode->m_type & PropertyNode::PrivateGetter
     617                    ? generator.propertyNames().builtinNames().getPrivateName()
     618                    : generator.propertyNames().builtinNames().setPrivateName();
     619                generator.emitDirectPutById(getterSetterObj.get(), setterOrGetterIdent, value.get());
     620            };
     621
     622            if (pair.first)
     623                emitPutAccessor(pair.first);
     624
     625            if (pair.second)
     626                emitPutAccessor(pair.second);
     627
     628            Variable var = generator.variable(*pair.first->name());
     629            generator.emitPutToScope(generator.scopeRegister(), var, getterSetterObj.get(), DoNotThrowIfNotFound, InitializationMode::ConstInitialization);
     630        }
     631    }
     632
    582633    PropertyListNode* p = this;
    583634    RegisterID* dst = nullptr;
     
    586637    for (; p && (p->m_node->m_type & PropertyNode::Constant); p = p->m_next) {
    587638        dst = p->m_node->isInstanceClassProperty() ? prototype : dstOrConstructor;
     639
     640        if (p->m_node->type() & (PropertyNode::PrivateGetter | PropertyNode::PrivateSetter))
     641            continue;
    588642
    589643        if (p->isComputedClassField())
     
    611665        bool canOverrideProperties = false;
    612666
    613         typedef std::pair<PropertyNode*, PropertyNode*> GetterSetterPair;
    614         typedef HashMap<UniquedStringImpl*, GetterSetterPair, IdentifierRepHash> GetterSetterMap;
    615667        GetterSetterMap instanceMap;
    616668        GetterSetterMap staticMap;
     
    651703            if (p->isComputedClassField())
    652704                emitSaveComputedFieldName(generator, *p->m_node);
     705
     706            if (p->m_node->type() & (PropertyNode::PrivateGetter | PropertyNode::PrivateSetter))
     707                continue;
    653708
    654709            if (p->isInstanceClassField()) {
     
    783838    if (node.isClassProperty()) {
    784839        ASSERT(node.needsSuperBinding());
     840        ASSERT(!(node.type() & PropertyNode::PrivateSetter));
     841        ASSERT(!(node.type() & PropertyNode::PrivateGetter));
    785842
    786843        if (node.type() & PropertyNode::PrivateMethod) {
     
    920977{
    921978    if (isPrivateMember()) {
    922         if (generator.isPrivateMethod(identifier())) {
    923             Variable var = generator.variable(identifier());
     979        auto identifierName = identifier();
     980        auto privateTraits = generator.getPrivateTraits(identifierName);
     981        if (privateTraits.isMethod()) {
     982            Variable var = generator.variable(identifierName);
    924983            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    925984
    926             RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    927             generator.emitCheckPrivateBrand(base, privateBrandSymbol);
     985            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     986            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
    928987
    929988            return generator.emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
    930989        }
    931990
     991        if (privateTraits.isGetter()) {
     992            Variable var = generator.variable(identifierName);
     993            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     994
     995            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     996            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     997
     998            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     999            RefPtr<RegisterID> getterFunction = generator.emitDirectGetById(generator.newTemporary(), getterSetterObj.get(), generator.propertyNames().builtinNames().getPrivateName());
     1000            CallArguments args(generator, nullptr);
     1001            generator.move(args.thisRegister(), base);
     1002            return generator.emitCall(dst, getterFunction.get(), NoExpectedFunction, args, m_position, m_position, m_position, DebuggableCall::Yes);
     1003        }
     1004
     1005        if (privateTraits.isSetter()) {
     1006            // We need to perform brand check to follow the spec
     1007            Variable var = generator.variable(identifierName);
     1008            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     1009
     1010            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     1011            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     1012            generator.emitThrowTypeError("Trying to access an undefined private getter");
     1013            return dst;
     1014        }
     1015
     1016        ASSERT(privateTraits.isField());
    9321017        Variable var = generator.variable(m_ident);
    9331018        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     
    9581043    if (isPrivateMember()) {
    9591044        auto identifierName = identifier();
    960         if (generator.isPrivateMethod(identifierName)) {
     1045        auto privateTraits = generator.getPrivateTraits(identifierName);
     1046        if (privateTraits.isSetter()) {
    9611047            Variable var = generator.variable(identifierName);
    9621048            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    9631049
    964             RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
    965             generator.emitCheckPrivateBrand(base, privateBrandSymbol);
    966 
    967             generator.emitThrowTypeError("Trying to access a not defined private setter");
    968         }
    969 
     1050            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     1051            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     1052
     1053            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     1054            RefPtr<RegisterID> setterFunction = generator.emitDirectGetById(generator.newTemporary(), getterSetterObj.get(), generator.propertyNames().builtinNames().setPrivateName());
     1055            CallArguments args(generator, nullptr, 1);
     1056            generator.move(args.thisRegister(), base);
     1057            generator.move(args.argumentRegister(0), value);
     1058            generator.emitCall(generator.newTemporary(), setterFunction.get(), NoExpectedFunction, args, m_position, m_position, m_position, DebuggableCall::Yes);
     1059
     1060            return value;
     1061        }
     1062
     1063        if (privateTraits.isGetter() || privateTraits.isMethod()) {
     1064            Variable var = generator.variable(identifierName);
     1065            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     1066
     1067            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     1068            generator.emitCheckPrivateBrand(base, privateBrandSymbol.get());
     1069
     1070            generator.emitThrowTypeError("Trying to access an undefined private setter");
     1071            return value;
     1072        }
     1073
     1074        ASSERT(privateTraits.isField());
    9701075        Variable var = generator.variable(m_ident);
    9711076        ASSERT_WITH_MESSAGE(!var.local(), "Private Field names must be stored in captured variables");
     
    22882393    if (dotAccessor->isPrivateMember()) {
    22892394        ASSERT(!baseIsSuper);
     2395        auto privateTraits = generator.getPrivateTraits(ident);
     2396
     2397        if (privateTraits.isField()) {
     2398            Variable var = generator.variable(ident);
     2399            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     2400            RefPtr<RegisterID> privateName = generator.newTemporary();
     2401            generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     2402
     2403            RefPtr<RegisterID> value = generator.emitGetPrivateName(generator.newTemporary(), base.get(), privateName.get());
     2404            RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
     2405            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2406            generator.emitPrivateFieldPut(base.get(), privateName.get(), value.get());
     2407            generator.emitProfileType(value.get(), divotStart(), divotEnd());
     2408            return generator.move(dst, oldValue.get());
     2409        }
     2410
     2411        if (privateTraits.isMethod()) {
     2412            Variable var = generator.variable(ident);
     2413            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     2414
     2415            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     2416            generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2417
     2418            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2419            generator.emitThrowTypeError("Trying to access an undefined private setter");
     2420            return generator.tempDestination(dst);
     2421        }
     2422
    22902423        Variable var = generator.variable(ident);
    22912424        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    2292         RefPtr<RegisterID> privateName = generator.newTemporary();
    2293         generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
    2294 
    2295         RefPtr<RegisterID> value = generator.emitGetPrivateName(generator.newTemporary(), base.get(), privateName.get());
     2425
     2426        RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     2427        generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2428
     2429        RefPtr<RegisterID> value;
     2430        if (privateTraits.isGetter()) {
     2431            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     2432            RefPtr<RegisterID> getterFunction = generator.emitDirectGetById(generator.newTemporary(), getterSetterObj.get(), generator.propertyNames().builtinNames().getPrivateName());
     2433            CallArguments args(generator, nullptr);
     2434            generator.move(args.thisRegister(), base.get());
     2435            value = generator.emitCall(generator.newTemporary(), getterFunction.get(), NoExpectedFunction, args, m_position, m_position, m_position, DebuggableCall::Yes);
     2436        } else {
     2437            generator.emitThrowTypeError("Trying to access an undefined private getter");
     2438            return generator.tempDestination(dst);
     2439        }
     2440
    22962441        RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.tempDestination(dst), value.get(), m_operator);
    22972442        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2298         generator.emitPrivateFieldPut(base.get(), privateName.get(), value.get());
    2299         generator.emitProfileType(value.get(), divotStart(), divotEnd());
     2443
     2444        if (privateTraits.isSetter()) {
     2445            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     2446            RefPtr<RegisterID> setterFunction = generator.emitDirectGetById(generator.newTemporary(), getterSetterObj.get(), generator.propertyNames().builtinNames().setPrivateName());
     2447            CallArguments args(generator, nullptr, 1);
     2448            generator.move(args.thisRegister(), base.get());
     2449            generator.move(args.argumentRegister(0), value.get());
     2450            generator.emitCall(generator.newTemporary(), setterFunction.get(), NoExpectedFunction, args, m_position, m_position, m_position, DebuggableCall::Yes);
     2451            generator.emitProfileType(value.get(), divotStart(), divotEnd());
     2452            return generator.move(dst, oldValue.get());
     2453        }
     2454
     2455        generator.emitThrowTypeError("Trying to access an undefined private getter");
    23002456        return generator.move(dst, oldValue.get());
    23012457    }
     
    25262682    RegisterID* value;
    25272683    if (dotAccessor->isPrivateMember()) {
    2528         ASSERT(!baseNode->isSuperNode());
     2684        auto privateTraits = generator.getPrivateTraits(ident);
     2685        if (privateTraits.isField()) {
     2686            ASSERT(!baseNode->isSuperNode());
     2687            Variable var = generator.variable(ident);
     2688            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     2689            RefPtr<RegisterID> privateName = generator.newTemporary();
     2690            generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
     2691
     2692            value = generator.emitGetPrivateName(propDst.get(), base.get(), privateName.get());
     2693            emitIncOrDec(generator, value, m_operator);
     2694            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2695            generator.emitPrivateFieldPut(base.get(), privateName.get(), value);
     2696            generator.emitProfileType(value, divotStart(), divotEnd());
     2697            return generator.move(dst, propDst.get());
     2698        }
     2699
     2700        if (privateTraits.isMethod()) {
     2701            Variable var = generator.variable(ident);
     2702            RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
     2703
     2704            RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     2705            generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2706
     2707            generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2708            generator.emitThrowTypeError("Trying to access an undefined private setter");
     2709            return generator.move(dst, propDst.get());
     2710        }
     2711
    25292712        Variable var = generator.variable(ident);
    25302713        RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
    2531         RefPtr<RegisterID> privateName = generator.newTemporary();
    2532         generator.emitGetFromScope(privateName.get(), scope.get(), var, DoNotThrowIfNotFound);
    2533 
    2534         value = generator.emitGetPrivateName(propDst.get(), base.get(), privateName.get());
     2714
     2715        RefPtr<RegisterID> privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get());
     2716        generator.emitCheckPrivateBrand(base.get(), privateBrandSymbol.get());
     2717
     2718        if (privateTraits.isGetter()) {
     2719            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     2720            RefPtr<RegisterID> getterFunction = generator.emitDirectGetById(generator.newTemporary(), getterSetterObj.get(), generator.propertyNames().builtinNames().getPrivateName());
     2721            CallArguments args(generator, nullptr);
     2722            generator.move(args.thisRegister(), base.get());
     2723            value = generator.emitCall(propDst.get(), getterFunction.get(), NoExpectedFunction, args, m_position, m_position, m_position, DebuggableCall::Yes);
     2724        } else {
     2725            generator.emitThrowTypeError("Trying to access an undefined private getter");
     2726            return generator.move(dst, propDst.get());
     2727        }
     2728
    25352729        emitIncOrDec(generator, value, m_operator);
    25362730        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2537         generator.emitPrivateFieldPut(base.get(), privateName.get(), value);
    2538         generator.emitProfileType(value, divotStart(), divotEnd());
     2731
     2732        if (privateTraits.isSetter()) {
     2733            RefPtr<RegisterID> getterSetterObj = generator.emitGetFromScope(generator.newTemporary(), scope.get(), var, ThrowIfNotFound);
     2734            RefPtr<RegisterID> setterFunction = generator.emitDirectGetById(generator.newTemporary(), getterSetterObj.get(), generator.propertyNames().builtinNames().setPrivateName());
     2735            CallArguments args(generator, nullptr, 1);
     2736            generator.move(args.thisRegister(), base.get());
     2737            generator.move(args.argumentRegister(0), value);
     2738            generator.emitCall(generator.newTemporary(), setterFunction.get(), NoExpectedFunction, args, m_position, m_position, m_position, DebuggableCall::Yes);
     2739            generator.emitProfileType(value, divotStart(), divotEnd());
     2740            return generator.move(dst, propDst.get());
     2741        }
     2742
     2743        generator.emitThrowTypeError("Trying to access an undefined private getter");
    25392744        return generator.move(dst, propDst.get());
    25402745    }
Note: See TracChangeset for help on using the changeset viewer.