* Copyright (c) 2021-2026 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "memberExpression.h"
#include <compiler/core/pandagen.h>
#include <ir/astDump.h>
#include <ir/expressions/identifier.h>
#include <ir/expressions/privateIdentifier.h>
#include <ir/expressions/literals/numberLiteral.h>
#include <ir/expressions/literals/stringLiteral.h>
namespace panda::es2panda::ir {
void MemberExpression::Iterate(const NodeTraverser &cb) const
{
cb(object_);
cb(property_);
}
void MemberExpression::Dump(ir::AstDumper *dumper) const
{
dumper->Add({{"type", "MemberExpression"},
{"object", object_},
{"property", property_},
{"computed", computed_},
{"optional", optional_}});
}
void MemberExpression::CompileObject(compiler::PandaGen *pg, compiler::VReg dest) const
{
object_->Compile(pg);
pg->StoreAccumulator(this, dest);
pg->GetOptionalChain()->CheckNullish(optional_, dest);
}
compiler::Operand MemberExpression::CompileKey(compiler::PandaGen *pg) const
{
return pg->ToPropertyKey(property_, computed_);
}
void MemberExpression::Compile(compiler::PandaGen *pg) const
{
compiler::RegScope rs(pg);
compiler::VReg objReg = pg->AllocReg();
Compile(pg, objReg);
}
void MemberExpression::Compile(compiler::PandaGen *pg, compiler::VReg objReg) const
{
CompileObject(pg, objReg);
if (AccessPrivateProperty()) {
auto name = property_->AsPrivateIdentifier()->Name();
auto result = pg->Scope()->FindPrivateName(name);
if (!result.result.isMethod) {
pg->LoadAccumulator(this, objReg);
pg->LoadPrivateProperty(this, result.lexLevel, result.result.slot);
return;
}
if (result.result.isSetter) {
pg->ThrowTypeError(this, "Property is not defined with Getter");
}
if (result.result.isStatic) {
pg->LoadLexicalVar(this, result.lexLevel, result.result.validateMethodSlot);
pg->Equal(this, objReg);
pg->ThrowTypeErrorIfFalse(this, "Object does not have private property");
} else {
pg->LoadAccumulator(this, objReg);
pg->LoadPrivateProperty(this, result.lexLevel, result.result.validateMethodSlot);
}
if (result.result.isGetter) {
pg->LoadAccumulator(this, objReg);
pg->LoadPrivateProperty(this, result.lexLevel, result.result.slot);
return;
}
pg->LoadLexicalVar(this, result.lexLevel, result.result.slot);
return;
}
compiler::Operand prop = CompileKey(pg);
if (object_->IsSuperExpression()) {
pg->LoadSuperProperty(property_, objReg, prop);
} else {
pg->LoadObjProperty(property_, objReg, prop);
}
}
void MemberExpression::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder)
{
object_ = std::get<ir::AstNode *>(cb(object_))->AsExpression();
property_ = std::get<ir::AstNode *>(cb(property_))->AsExpression();
}
}