• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "property.h"
17 
18 #include "checker/TSchecker.h"
19 #include "compiler/core/ETSGen.h"
20 #include "compiler/core/pandagen.h"
21 
22 namespace ark::es2panda::ir {
Property(Tag const tag,Property const & other,Expression * const key,Expression * const value)23 Property::Property([[maybe_unused]] Tag const tag, Property const &other, Expression *const key,
24                    Expression *const value)
25     : Property(other)
26 {
27     key_ = key;
28     value_ = value;
29 }
30 
Clone(ArenaAllocator * const allocator,AstNode * const parent)31 Property *Property::Clone(ArenaAllocator *const allocator, AstNode *const parent)
32 {
33     auto *const key = key_ != nullptr ? key_->Clone(allocator, nullptr)->AsExpression() : nullptr;
34     auto *const value = value_ != nullptr ? value_->Clone(allocator, nullptr)->AsExpression() : nullptr;
35     auto *const clone = allocator->New<Property>(Tag {}, *this, key, value);
36     ES2PANDA_ASSERT(clone != nullptr);
37     if (key != nullptr) {
38         key->SetParent(clone);
39     }
40     if (value != nullptr) {
41         value->SetParent(clone);
42     }
43     if (parent != nullptr) {
44         clone->SetParent(parent);
45     }
46     return clone;
47 }
48 
ConvertibleToPatternProperty()49 bool Property::ConvertibleToPatternProperty()
50 {
51     // Object pattern can't contain getter or setter
52     if (IsAccessor() || isMethod_) {
53         return false;
54     }
55 
56     switch (value_->Type()) {
57         case AstNodeType::OBJECT_EXPRESSION: {
58             return value_->AsObjectExpression()->ConvertibleToObjectPattern();
59         }
60         case AstNodeType::ARRAY_EXPRESSION: {
61             return value_->AsArrayExpression()->ConvertibleToArrayPattern();
62         }
63         case AstNodeType::ASSIGNMENT_EXPRESSION: {
64             return value_->AsAssignmentExpression()->ConvertibleToAssignmentPattern();
65         }
66         case AstNodeType::IDENTIFIER:
67         case AstNodeType::MEMBER_EXPRESSION:
68         case AstNodeType::ARRAY_PATTERN:
69         case AstNodeType::OBJECT_PATTERN:
70         case AstNodeType::ASSIGNMENT_PATTERN: {
71             break;
72         }
73         default: {
74             if (isShorthand_) {
75                 break;
76             }
77 
78             return false;
79         }
80     }
81 
82     return true;
83 }
84 
ValidateExpression()85 ValidationInfo Property::ValidateExpression()
86 {
87     ValidationInfo info;
88 
89     if (!IsComputed() && !IsMethod() && !IsAccessor() && !IsShorthand()) {
90         bool currentIsProto = false;
91 
92         if (key_->IsIdentifier()) {
93             currentIsProto = key_->AsIdentifier()->Name().Is("__proto__");
94         } else if (key_->IsStringLiteral()) {
95             currentIsProto = key_->AsStringLiteral()->Str().Is("__proto__");
96         }
97 
98         if (currentIsProto) {
99             kind_ = PropertyKind::PROTO;
100         }
101     }
102 
103     if (value_ != nullptr) {
104         if (value_->IsAssignmentPattern()) {
105             return {"Invalid shorthand property initializer.", value_->Start()};
106         }
107 
108         if (value_->IsObjectExpression()) {
109             info = value_->AsObjectExpression()->ValidateExpression();
110         } else if (value_->IsArrayExpression()) {
111             info = value_->AsArrayExpression()->ValidateExpression();
112         }
113     }
114 
115     return info;
116 }
117 
TransformChildren(const NodeTransformer & cb,std::string_view transformationName)118 void Property::TransformChildren(const NodeTransformer &cb, std::string_view transformationName)
119 {
120     if (auto *transformedNode = cb(key_); key_ != transformedNode) {
121         key_->SetTransformedNode(transformationName, transformedNode);
122         key_ = transformedNode->AsExpression();
123     }
124 
125     if (auto *transformedNode = cb(value_); value_ != transformedNode) {
126         value_->SetTransformedNode(transformationName, transformedNode);
127         value_ = transformedNode->AsExpression();
128     }
129 }
130 
Iterate(const NodeTraverser & cb) const131 void Property::Iterate(const NodeTraverser &cb) const
132 {
133     cb(key_);
134     cb(value_);
135 }
136 
Dump(ir::AstDumper * dumper) const137 void Property::Dump(ir::AstDumper *dumper) const
138 {
139     const char *kind = nullptr;
140 
141     switch (kind_) {
142         case PropertyKind::INIT: {
143             kind = "init";
144             break;
145         }
146         case PropertyKind::PROTO: {
147             kind = "proto";
148             break;
149         }
150         case PropertyKind::GET: {
151             kind = "get";
152             break;
153         }
154         case PropertyKind::SET: {
155             kind = "set";
156             break;
157         }
158         default: {
159             ES2PANDA_UNREACHABLE();
160         }
161     }
162 
163     dumper->Add({{"type", "Property"},
164                  {"method", isMethod_},
165                  {"shorthand", isShorthand_},
166                  {"computed", isComputed_},
167                  {"key", key_},
168                  {"value", value_},
169                  {"kind", kind}});
170 }
171 
Compile(compiler::PandaGen * pg) const172 void Property::Compile(compiler::PandaGen *pg) const
173 {
174     pg->GetAstCompiler()->Compile(this);
175 }
176 
Compile(compiler::ETSGen * etsg) const177 void Property::Compile(compiler::ETSGen *etsg) const
178 {
179     etsg->GetAstCompiler()->Compile(this);
180 }
181 
Dump(ir::SrcDumper * dumper) const182 void Property::Dump(ir::SrcDumper *dumper) const
183 {
184     if (kind_ == PropertyKind::INIT) {
185         key_->Dump(dumper);
186         dumper->Add(": ");
187         value_->Dump(dumper);
188     }
189 }
190 
Check(checker::TSChecker * checker)191 checker::Type *Property::Check(checker::TSChecker *checker)
192 {
193     return checker->GetAnalyzer()->Check(this);
194 }
195 
Check(checker::ETSChecker * checker)196 checker::VerifiedType Property::Check(checker::ETSChecker *checker)
197 {
198     return {this, checker->GetAnalyzer()->Check(this)};
199 }
200 }  // namespace ark::es2panda::ir
201