• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 - 2023 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 "es2panda.h"
19 #include "checker/TSchecker.h"
20 #include "compiler/core/ETSGen.h"
21 #include "compiler/core/pandagen.h"
22 #include "ir/astDump.h"
23 #include "ir/srcDump.h"
24 
25 namespace panda::es2panda::ir {
Property(Tag const tag,Property const & other,Expression * const key,Expression * const value)26 Property::Property([[maybe_unused]] Tag const tag, Property const &other, Expression *const key,
27                    Expression *const value)
28     : Property(other)
29 {
30     key_ = key;
31     value_ = value;
32 }
33 
34 // NOLINTNEXTLINE(google-default-arguments)
Clone(ArenaAllocator * const allocator,AstNode * const parent)35 Property *Property::Clone(ArenaAllocator *const allocator, AstNode *const parent)
36 {
37     auto *const key = key_ != nullptr ? key_->Clone(allocator)->AsExpression() : nullptr;
38     auto *const value = value_ != nullptr ? value_->Clone(allocator)->AsExpression() : nullptr;
39 
40     if (auto *const clone = allocator->New<Property>(Tag {}, *this, key, value); clone != nullptr) {
41         if (key != nullptr) {
42             key->SetParent(clone);
43         }
44         if (value != nullptr) {
45             value->SetParent(clone);
46         }
47         if (parent != nullptr) {
48             clone->SetParent(parent);
49         }
50         return clone;
51     }
52 
53     throw Error(ErrorType::GENERIC, "", CLONE_ALLOCATION_ERROR);
54 }
55 
ConvertibleToPatternProperty()56 bool Property::ConvertibleToPatternProperty()
57 {
58     // Object pattern can't contain getter or setter
59     if (IsAccessor() || isMethod_) {
60         return false;
61     }
62 
63     switch (value_->Type()) {
64         case AstNodeType::OBJECT_EXPRESSION: {
65             return value_->AsObjectExpression()->ConvertibleToObjectPattern();
66         }
67         case AstNodeType::ARRAY_EXPRESSION: {
68             return value_->AsArrayExpression()->ConvertibleToArrayPattern();
69         }
70         case AstNodeType::ASSIGNMENT_EXPRESSION: {
71             return value_->AsAssignmentExpression()->ConvertibleToAssignmentPattern();
72         }
73         case AstNodeType::IDENTIFIER:
74         case AstNodeType::MEMBER_EXPRESSION:
75         case AstNodeType::ARRAY_PATTERN:
76         case AstNodeType::OBJECT_PATTERN:
77         case AstNodeType::ASSIGNMENT_PATTERN: {
78             break;
79         }
80         default: {
81             if (isShorthand_) {
82                 break;
83             }
84 
85             return false;
86         }
87     }
88 
89     return true;
90 }
91 
ValidateExpression()92 ValidationInfo Property::ValidateExpression()
93 {
94     ValidationInfo info;
95 
96     if (!IsComputed() && !IsMethod() && !IsAccessor() && !IsShorthand()) {
97         bool currentIsProto = false;
98 
99         if (key_->IsIdentifier()) {
100             currentIsProto = key_->AsIdentifier()->Name().Is("__proto__");
101         } else if (key_->IsStringLiteral()) {
102             currentIsProto = key_->AsStringLiteral()->Str().Is("__proto__");
103         }
104 
105         if (currentIsProto) {
106             kind_ = PropertyKind::PROTO;
107         }
108     }
109 
110     if (value_ != nullptr) {
111         if (value_->IsAssignmentPattern()) {
112             return {"Invalid shorthand property initializer.", value_->Start()};
113         }
114 
115         if (value_->IsObjectExpression()) {
116             info = value_->AsObjectExpression()->ValidateExpression();
117         } else if (value_->IsArrayExpression()) {
118             info = value_->AsArrayExpression()->ValidateExpression();
119         }
120     }
121 
122     return info;
123 }
124 
TransformChildren(const NodeTransformer & cb)125 void Property::TransformChildren(const NodeTransformer &cb)
126 {
127     key_ = cb(key_)->AsExpression();
128     value_ = cb(value_)->AsExpression();
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             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     dumper->Add("Property");
185 }
186 
Check(checker::TSChecker * checker)187 checker::Type *Property::Check(checker::TSChecker *checker)
188 {
189     return checker->GetAnalyzer()->Check(this);
190 }
191 
Check(checker::ETSChecker * checker)192 checker::Type *Property::Check(checker::ETSChecker *checker)
193 {
194     return checker->GetAnalyzer()->Check(this);
195 }
196 }  // namespace panda::es2panda::ir
197