1 /*
2 * Copyright (c) 2022 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 "transformer.h"
17
18 #include "ir/base/catchClause.h"
19 #include "ir/base/classStaticBlock.h"
20 #include "ir/base/decorator.h"
21 #include "ir/base/scriptFunction.h"
22 #include "ir/expressions/assignmentExpression.h"
23 #include "ir/expressions/binaryExpression.h"
24 #include "ir/expressions/callExpression.h"
25 #include "ir/expressions/classExpression.h"
26 #include "ir/expressions/functionExpression.h"
27 #include "ir/expressions/literals/bigIntLiteral.h"
28 #include "ir/expressions/literals/numberLiteral.h"
29 #include "ir/expressions/literals/stringLiteral.h"
30 #include "ir/expressions/memberExpression.h"
31 #include "ir/expressions/objectExpression.h"
32 #include "ir/expressions/sequenceExpression.h"
33 #include "ir/expressions/templateLiteral.h"
34 #include "ir/expressions/thisExpression.h"
35 #include "ir/module/exportDefaultDeclaration.h"
36 #include "ir/module/exportNamedDeclaration.h"
37 #include "ir/statements/blockStatement.h"
38 #include "ir/statements/classDeclaration.h"
39 #include "ir/statements/doWhileStatement.h"
40 #include "ir/statements/expressionStatement.h"
41 #include "ir/statements/forInStatement.h"
42 #include "ir/statements/forOfStatement.h"
43 #include "ir/statements/forUpdateStatement.h"
44 #include "ir/statements/functionDeclaration.h"
45 #include "ir/statements/returnStatement.h"
46 #include "ir/statements/switchStatement.h"
47 #include "ir/statements/variableDeclaration.h"
48 #include "ir/statements/variableDeclarator.h"
49 #include "ir/statements/whileStatement.h"
50 #include "ir/ts/tsConstructorType.h"
51 #include "ir/ts/tsEnumDeclaration.h"
52 #include "ir/ts/tsEnumMember.h"
53 #include "ir/ts/tsFunctionType.h"
54 #include "ir/ts/tsImportEqualsDeclaration.h"
55 #include "ir/ts/tsInterfaceDeclaration.h"
56 #include "ir/ts/tsMethodSignature.h"
57 #include "ir/ts/tsModuleBlock.h"
58 #include "ir/ts/tsModuleDeclaration.h"
59 #include "ir/ts/tsParameterProperty.h"
60 #include "ir/ts/tsPrivateIdentifier.h"
61 #include "ir/ts/tsQualifiedName.h"
62 #include "ir/ts/tsSignatureDeclaration.h"
63 #include "ir/ts/tsTypeParameterDeclaration.h"
64
65 namespace panda::es2panda::parser {
66
Transform(Program * program)67 void Transformer::Transform(Program *program)
68 {
69 program_ = program;
70 if (Extension() == ScriptExtension::TS) {
71 TransformFromTS();
72 }
73 }
74
TransformFromTS()75 void Transformer::TransformFromTS()
76 {
77 ASSERT(Extension() == ScriptExtension::TS);
78 VisitTSNodes(program_->Ast());
79 PushVariablesToNearestStatements(program_->Ast());
80 }
81
VisitTSNodes(ir::AstNode * parent)82 ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent)
83 {
84 if (!parent) {
85 return nullptr;
86 }
87 parent->UpdateSelf([this](auto *childNode) { return VisitTSNode(childNode); }, Binder());
88 return parent;
89 }
90
AddVariableToNearestStatements(util::StringView name)91 void Transformer::AddVariableToNearestStatements(util::StringView name)
92 {
93 /*
94 * Add variable declare like 'var ##var_1;' to nearest statements in namespace function or top level scope
95 * Record the variable name and scope in tempVarDeclStatements_ and will push the VariableDeclaration nodes
96 * to statements in PushVariablesToNearestStatements
97 */
98 auto currentScope = Scope();
99 while (currentScope != nullptr) {
100 if (currentScope->IsTSModuleScope()) {
101 auto node = currentScope->Node();
102 ASSERT(node->IsTSModuleDeclaration());
103 if (node->AsTSModuleDeclaration()->Body()->IsTSModuleBlock()) {
104 break;
105 }
106 }
107 if (currentScope->IsFunctionScope()) {
108 auto node = currentScope->Node();
109 ASSERT(node->IsScriptFunction());
110 if (!node->AsScriptFunction()->FunctionBodyIsExpression()) {
111 break;
112 }
113 }
114 currentScope = currentScope->Parent();
115 }
116 tempVarDeclStatements_.insert({name, currentScope});
117 }
118
PushVariablesToNearestStatements(ir::BlockStatement * ast)119 void Transformer::PushVariablesToNearestStatements(ir::BlockStatement *ast)
120 {
121 /*
122 * Push the VariableDeclaration nodes to nearest statements
123 * For example, transform:
124 * namespace ns {
125 * ...
126 * }
127 *
128 * To:
129 * namespace ns {
130 * var ##var_1;
131 * ...
132 * }
133 */
134 if (tempVarDeclStatements_.empty()) {
135 return;
136 }
137 for (auto it : tempVarDeclStatements_) {
138 auto *scope = it.second;
139 if (scope == nullptr) {
140 auto scopeCtx = binder::LexicalScope<binder::Scope>::Enter(Binder(), ast->Scope());
141 ast->AddStatementAtPos(0, CreateVariableDeclarationWithIdentify(it.first, VariableParsingFlags::VAR,
142 nullptr, false));
143 } else if (scope->IsFunctionScope() || scope->IsTSModuleScope()) {
144 auto *body = scope->Node()->AsScriptFunction()->Body();
145 ASSERT(body->IsBlockStatement());
146 auto scopeCtx = binder::LexicalScope<binder::Scope>::Enter(Binder(), scope);
147 body->AsBlockStatement()->AddStatementAtPos(0, CreateVariableDeclarationWithIdentify(it.first,
148 VariableParsingFlags::VAR, nullptr, false));
149 }
150 }
151 }
152
FindExportVariableInTsModuleScope(util::StringView name) const153 binder::Scope *Transformer::FindExportVariableInTsModuleScope(util::StringView name) const
154 {
155 bool isExport = false;
156 auto currentScope = Scope();
157 while (currentScope != nullptr) {
158 binder::Variable *v = currentScope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS);
159 bool isTSModuleScope = currentScope->IsTSModuleScope();
160 if (v != nullptr) {
161 if (!v->Declaration()->IsVarDecl() && !v->Declaration()->IsLetDecl() && !v->Declaration()->IsConstDecl()) {
162 break;
163 }
164 if (isTSModuleScope && v->Declaration()->IsExportDeclInTsModule()) {
165 isExport = true;
166 }
167 break;
168 }
169 if (currentScope->InLocalTSBindings(name) &&
170 !currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name)) {
171 break;
172 }
173 if (isTSModuleScope && currentScope->AsTSModuleScope()->InExportBindings(name)) {
174 isExport = true;
175 break;
176 }
177 currentScope = currentScope->Parent();
178 }
179 if (!isExport) {
180 return nullptr;
181 }
182 return currentScope;
183 }
184
VisitTSNode(ir::AstNode * childNode)185 ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode)
186 {
187 ASSERT(childNode != nullptr);
188 switch (childNode->Type()) {
189 case ir::AstNodeType::IDENTIFIER: {
190 auto *ident = childNode->AsIdentifier();
191 if (!ident->IsReference() || (!IsTsModule() && !IsTsEnum() && !InClass())) {
192 return VisitTSNodes(childNode);
193 }
194
195 auto name = ident->Name();
196 if (InClass()) {
197 auto *classDefinition = GetClassReference(name);
198 auto aliasName = GetClassAliasName(name, classDefinition);
199 if (classDefinition != nullptr && aliasName != name) {
200 ident->SetName(aliasName);
201 }
202 }
203
204 if (IsTsEnum()) {
205 auto scope = FindEnumMemberScope(name);
206 if (scope) {
207 return CreateMemberExpressionFromIdentifier(scope, ident);
208 }
209 }
210 if (IsTsModule()) {
211 auto scope = FindExportVariableInTsModuleScope(name);
212 if (scope) {
213 return CreateMemberExpressionFromIdentifier(scope, ident);
214 }
215 }
216
217 return VisitTSNodes(childNode);
218 }
219 case ir::AstNodeType::TS_MODULE_DECLARATION: {
220 auto *node = childNode->AsTSModuleDeclaration();
221 if (node->Declare() || !node->IsInstantiated()) {
222 return childNode;
223 }
224 auto res = VisitTsModuleDeclaration(node);
225 SetOriginalNode(res, childNode);
226 return res;
227 }
228 case ir::AstNodeType::TS_ENUM_DECLARATION: {
229 auto *node = childNode->AsTSEnumDeclaration();
230 if (node->IsDeclare()) {
231 return childNode;
232 }
233 auto res = VisitTsEnumDeclaration(node);
234 SetOriginalNode(res, childNode);
235 return res;
236 }
237 case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
238 auto *node = childNode->AsExportNamedDeclaration();
239 auto *decl = node->Decl();
240 if (!decl) {
241 return VisitTSNodes(childNode);
242 }
243
244 if (decl->IsTSModuleDeclaration()) {
245 auto *tsModuleDeclaration = decl->AsTSModuleDeclaration();
246 if (tsModuleDeclaration->Declare() || !tsModuleDeclaration->IsInstantiated()) {
247 return childNode;
248 }
249 auto res = VisitTsModuleDeclaration(tsModuleDeclaration, true);
250 SetOriginalNode(res, childNode);
251 return res;
252 }
253
254 if (decl->IsTSEnumDeclaration()) {
255 if (decl->AsTSEnumDeclaration()->IsDeclare() ||
256 (decl->AsTSEnumDeclaration()->IsConst() && program_->IsShared())) {
257 return childNode;
258 }
259 auto res = VisitTsEnumDeclaration(decl->AsTSEnumDeclaration(), true);
260 SetOriginalNode(res, childNode);
261 return res;
262 }
263
264 if (IsTsModule()) {
265 auto res = VisitExportNamedVariable(decl);
266 SetOriginalNode(res, node);
267 return res;
268 }
269
270 if (decl->IsClassDeclaration()) {
271 return VisitExportClassDeclaration<ir::ExportNamedDeclaration>(node);
272 }
273
274 return VisitTSNodes(node);
275 }
276 case ir::AstNodeType::EXPORT_DEFAULT_DECLARATION: {
277 auto *node = childNode->AsExportDefaultDeclaration();
278 auto *decl = node->Decl();
279 ASSERT(decl != nullptr);
280 if (decl->IsClassDeclaration()) {
281 return VisitExportClassDeclaration<ir::ExportDefaultDeclaration>(node);
282 }
283 // When we export default an identify 'a', a maybe a interface or type. So we should check here.
284 // if decl is not an identifier, it's won't be a type.
285 if (decl->IsIdentifier() && !IsValueReference(decl->AsIdentifier())) {
286 RemoveDefaultLocalExportEntry();
287 return nullptr;
288 }
289 return VisitTSNodes(childNode);
290 }
291 case ir::AstNodeType::TS_IMPORT_EQUALS_DECLARATION: {
292 auto *node = childNode->AsTSImportEqualsDeclaration();
293 auto *express = node->ModuleReference();
294 if (express->IsTSExternalModuleReference()) {
295 return VisitTSNodes(childNode);
296 }
297 auto *res = VisitTsImportEqualsDeclaration(node);
298 SetOriginalNode(res, childNode);
299 return res;
300 }
301 case ir::AstNodeType::CLASS_DECLARATION: {
302 auto *node = childNode->AsClassDeclaration();
303 if (node->Definition()->Declare() || node->IsAnnotationDecl()) {
304 return node;
305 }
306 DuringClass duringClass(&classList_, node->Definition()->GetName(),
307 CreateClassAliasName(node), node->Definition());
308 auto *classNode = VisitTSNodes(node);
309 CHECK_NOT_NULL(classNode);
310 node = classNode->AsClassDeclaration();
311 auto res = VisitClassDeclaration(node);
312 SetOriginalNode(res, childNode);
313 ResetParentScope(res, Scope());
314 return res;
315 }
316 case ir::AstNodeType::CLASS_EXPRESSION: {
317 auto *node = childNode->AsClassExpression();
318 DuringClass duringClass(&classList_, node->Definition()->GetName(),
319 node->Definition()->GetName(), node->Definition());
320 auto *classNode = VisitTSNodes(node);
321 CHECK_NOT_NULL(classNode);
322 node = classNode->AsClassExpression();
323 auto res = VisitClassExpression(node);
324 SetOriginalNode(res, childNode);
325 return res;
326 }
327 case ir::AstNodeType::CLASS_DEFINITION: {
328 auto *node = childNode->AsClassDefinition();
329 VisitPrivateElement(node);
330 VisitComputedProperty(node);
331 // Process auto accessor properties
332 VisitAutoAccessorProperty(node);
333 auto res = VisitTSNodes(childNode);
334 SetOriginalNode(res, childNode);
335 return res;
336 }
337 case ir::AstNodeType::TS_PRIVATE_IDENTIFIER: {
338 auto id = childNode->AsTSPrivateIdentifier()->Key()->AsIdentifier();
339 auto name = FindPrivateElementBindName(id->Name());
340 auto res = CreateReferenceIdentifier(name);
341 SetOriginalNode(res, childNode);
342 return res;
343 }
344 default: {
345 return VisitTSNodes(childNode);
346 }
347 }
348 }
349
350 template <typename T>
VisitExportClassDeclaration(T * node)351 ir::UpdateNodes Transformer::VisitExportClassDeclaration(T *node)
352 {
353 auto *decl = node->Decl();
354 auto newDecl = VisitTSNode(decl);
355 if (std::holds_alternative<ir::AstNode *>(newDecl)) {
356 auto statement = std::get<ir::AstNode *>(newDecl);
357 ASSERT(statement->IsClassDeclaration());
358 node->SetDecl(statement->AsClassDeclaration());
359 return node;
360 } else {
361 auto statements = std::get<std::vector<ir::AstNode *>>(newDecl);
362 std::vector<ir::AstNode *> res;
363 auto firstStatement = statements.front();
364 statements.erase(statements.begin());
365 if (firstStatement->IsVariableDeclaration()) {
366 node->SetDecl(firstStatement->AsVariableDeclaration());
367 } else {
368 ASSERT(firstStatement->IsClassDeclaration());
369 node->SetDecl(firstStatement->AsClassDeclaration());
370 }
371 res.push_back(node);
372 res.insert(res.end(), statements.begin(), statements.end());
373 return res;
374 }
375 }
376
CreateNewVariable(bool needAddToStatements)377 util::StringView Transformer::CreateNewVariable(bool needAddToStatements)
378 {
379 util::StringView name = CreateNewVariableName();
380 if (needAddToStatements) {
381 AddVariableToNearestStatements(name);
382 }
383 return name;
384 }
385
CreateUniqueName(const std::string & head,size_t * index) const386 util::StringView Transformer::CreateUniqueName(const std::string &head, size_t *index) const
387 {
388 util::StringView name;
389 size_t idx = 0;
390 if (index != nullptr) {
391 idx = *index;
392 }
393 do {
394 idx++;
395 std::stringstream ss;
396 ss << head << std::to_string(idx);
397 auto s = ss.str();
398 if (!Binder()->HasVariableName(util::StringView(s))) {
399 name = util::UString(s, Allocator()).View();
400 break;
401 }
402 } while (true);
403 if (index != nullptr) {
404 *index = idx;
405 }
406 Binder()->AddDeclarationName(name);
407 return name;
408 }
409
CreateNewVariableName() const410 util::StringView Transformer::CreateNewVariableName() const
411 {
412 auto name = CreateUniqueName(std::string(NEW_VAR_PREFIX) + std::string(NEW_VAR_HEAD));
413 return name;
414 }
415
VisitClassExpression(ir::ClassExpression * node)416 ir::UpdateNodes Transformer::VisitClassExpression(ir::ClassExpression *node)
417 {
418 /*
419 * Transform:
420 * var c = class C {
421 * static a = 1
422 * }
423 *
424 * To:
425 * var ##var_1;
426 * var c = (##var_1 = class C {},
427 * ##var_1.a = 1,
428 * ##var_1)
429 */
430 auto instanceComputedProperty = VisitInstanceProperty(node->Definition());
431
432 VisitTSParameterProperty(node->Definition());
433
434 auto varName = CreateNewVariable(false);
435 auto staticProperty = VisitStaticProperty(node->Definition(), varName);
436 if (instanceComputedProperty.empty() && staticProperty.empty()) {
437 return node;
438 }
439 AddVariableToNearestStatements(varName);
440
441 auto assignment = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(varName),
442 node->AsExpression(), lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
443 ArenaVector<ir::Expression *> sequence(Allocator()->Adapter());
444 sequence.push_back(assignment);
445
446 for (auto *it : instanceComputedProperty) {
447 sequence.push_back(it->GetExpression());
448 }
449 for (auto *it : staticProperty) {
450 sequence.push_back(it->GetExpression());
451 }
452
453 sequence.push_back(CreateReferenceIdentifier(varName));
454 return AllocNode<ir::SequenceExpression>(std::move(sequence));
455 }
456
VisitComputedProperty(ir::ClassDefinition * node)457 void Transformer::VisitComputedProperty(ir::ClassDefinition *node)
458 {
459 /*
460 * Only create variable for the computed members with decorators or static class property
461 * The new value will be used in the decorators or static property initialize
462 * Transform:
463 * class C {
464 * @f
465 * [a](){}
466 * static [b] = 1
467 * [c] = 1
468 * }
469 *
470 * To:
471 * var ##var_1;
472 * var ##var_2;
473 * var ##var_3;
474 * class C {
475 * @f
476 * [##var_1 = a](){}
477 * static [##var_2 = b] = 1
478 * [##var_3 = c] = 1
479 * }
480 */
481 for (auto *it : node->Body()) {
482 if (it->IsClassProperty()) {
483 auto *classProperty = it->AsClassProperty();
484 if (!classProperty->IsComputed()) {
485 continue;
486 }
487 if (classProperty->IsAutoAccessor()) {
488 // Left to processing in auto aceessor process procedure.
489 continue;
490 }
491 auto *key = classProperty->Key();
492 auto name = CreateNewVariable();
493 auto *newKey = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(name),
494 key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
495 classProperty->SetKey(newKey);
496 AddComputedPropertyBinding(it, name);
497 } else if (it->IsMethodDefinition()) {
498 auto *methodDefinition = it->AsMethodDefinition();
499 if (!methodDefinition->Computed() ||
500 (!methodDefinition->HasDecorators() && !methodDefinition->HasParamDecorators())) {
501 continue;
502 }
503 auto *key = methodDefinition->Key();
504 auto name = CreateNewVariable();
505 auto *newKey = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(name),
506 key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
507 methodDefinition->SetKey(newKey);
508 AddComputedPropertyBinding(it, name);
509 }
510 }
511 }
512
GetClassReference(util::StringView name) const513 const ir::ClassDefinition *Transformer::GetClassReference(util::StringView name) const
514 {
515 auto *scope = Scope();
516 while (scope != nullptr) {
517 auto *v = scope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS);
518 if (v != nullptr) {
519 if (v->Declaration() != nullptr && v->Declaration()->Node() != nullptr &&
520 v->Declaration()->Node()->IsClassDefinition()) {
521 ASSERT(v->Declaration()->Node()->AsClassDefinition()->GetName() == name);
522 return v->Declaration()->Node()->AsClassDefinition();
523 } else {
524 return nullptr;
525 }
526 }
527
528 scope = scope->Parent();
529 }
530
531 return nullptr;
532 }
533
CreateClassAliasName(ir::ClassDeclaration * node)534 util::StringView Transformer::CreateClassAliasName(ir::ClassDeclaration *node)
535 {
536 if (node->HasDecorators()) {
537 return CreateUniqueName(std::string(NEW_VAR_PREFIX) + std::string(NEW_VAR_HEAD));
538 }
539 return node->Definition()->GetName();
540 }
541
VisitPrivateElement(ir::ClassDefinition * node)542 void Transformer::VisitPrivateElement(ir::ClassDefinition *node)
543 {
544 /*
545 * Create an unique variable name for private property member in class
546 * Transform:
547 * class C {
548 * #a = 1
549 * }
550 *
551 * To:
552 * class C {
553 * ##${RecordName}#C#a#1 = 1
554 * }
555 */
556 for (auto *it : node->Body()) {
557 if (!it->IsClassProperty() && !it->IsMethodDefinition()) {
558 continue;
559 }
560 auto *key = it->IsClassProperty() ? it->AsClassProperty()->Key() : it->AsMethodDefinition()->Key();
561 if (!key->IsTSPrivateIdentifier()) {
562 continue;
563 }
564 auto name = key->AsTSPrivateIdentifier()->Key()->AsIdentifier()->Name();
565 auto bindName = CreatePrivateElementBindName(name);
566 AddPrivateElementBinding(name, bindName);
567 }
568 }
569
FindPrivateElementBindName(util::StringView name)570 util::StringView Transformer::FindPrivateElementBindName(util::StringView name)
571 {
572 for (int i = static_cast<int>(classList_.size() - 1); i >= 0; i--) {
573 auto res = classList_[i].bindNameMap->find(name);
574 if (res != classList_[i].bindNameMap->end()) {
575 return res->second;
576 }
577 }
578 UNREACHABLE();
579 }
580
CreatePrivateElementBindName(util::StringView name)581 util::StringView Transformer::CreatePrivateElementBindName(util::StringView name)
582 {
583 std::stringstream head;
584 head << NEW_VAR_PREFIX << std::string(RecordName());
585 for (auto it : classList_) {
586 head << PRIVATE_PROPERTY_SIGN << std::string(it.name);
587 }
588 head << PRIVATE_PROPERTY_SIGN << std::string(name) << PRIVATE_PROPERTY_SIGN;
589 size_t index = GetCurrentClassInfoPropertyIndex();
590 auto uniqueName = CreateUniqueName(head.str(), &index);
591 SetCurrentClassInfoPropertyIndex(index);
592 return uniqueName;
593 }
594
GetInsertPosForConstructor(ir::ClassDefinition * node)595 size_t Transformer::GetInsertPosForConstructor(ir::ClassDefinition *node)
596 {
597 size_t insertPos = 0;
598 ir::BlockStatement *blockStat = node->Ctor()->Function()->Body()->AsBlockStatement();
599 auto iter = blockStat->Statements().begin();
600 for (; iter != blockStat->Statements().end();) {
601 if ((*iter)->IsExpressionStatement() &&
602 (*iter)->AsExpressionStatement()->GetExpression()->IsStringLiteral()) {
603 iter++;
604 insertPos++;
605 } else {
606 break;
607 }
608 }
609
610 if (node->Super() == nullptr || node->Super()->IsNullLiteral()) {
611 return insertPos;
612 }
613
614 for (; iter != blockStat->Statements().end(); iter++) {
615 insertPos++;
616
617 bool hasSuperCall = false;
618 FindSuperCallInCtorChildNode(*iter, &hasSuperCall);
619 if (hasSuperCall) {
620 break;
621 }
622 }
623
624 return insertPos;
625 }
626
FindSuperCall(const ir::AstNode * parent,bool * hasSuperCall)627 void Transformer::FindSuperCall(const ir::AstNode *parent, bool *hasSuperCall)
628 {
629 parent->Iterate([this, hasSuperCall](auto *childNode) {
630 FindSuperCallInCtorChildNode(childNode, hasSuperCall);
631 });
632 }
633
FindSuperCallInCtorChildNode(const ir::AstNode * childNode,bool * hasSuperCall)634 void Transformer::FindSuperCallInCtorChildNode(const ir::AstNode *childNode, bool *hasSuperCall)
635 {
636 if (*hasSuperCall) {
637 return;
638 }
639 switch (childNode->Type()) {
640 case ir::AstNodeType::CALL_EXPRESSION: {
641 if (childNode->AsCallExpression()->Callee()->IsSuperExpression()) {
642 *hasSuperCall = true;
643 return;
644 }
645 break;
646 }
647 case ir::AstNodeType::CLASS_DEFINITION:
648 case ir::AstNodeType::FUNCTION_DECLARATION:
649 case ir::AstNodeType::FUNCTION_EXPRESSION:
650 case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: {
651 break;
652 }
653 default: {
654 FindSuperCall(childNode, hasSuperCall);
655 break;
656 }
657 }
658 }
659
VisitInstanceProperty(ir::ClassDefinition * node)660 std::vector<ir::ExpressionStatement *> Transformer::VisitInstanceProperty(ir::ClassDefinition *node)
661 {
662 /*
663 * Move class InstanceProperty to constructor.
664 * Transform:
665 * class C {
666 * "prop" = 1;
667 * }
668 *
669 * To:
670 * class C {
671 * constructor () {
672 * this["prop"] = 1;
673 * }
674 * }
675 */
676 std::vector<ir::ClassProperty *> addToCtor;
677 // Non-null computed properties need to be added outside the class. It is a subset of addToCtor.
678 std::vector<ir::ExpressionStatement *> computedProps;
679 for (auto *it : node->Body()) {
680 if (it->IsClassProperty() && !it->AsClassProperty()->IsStatic() &&
681 !it->AsClassProperty()->Key()->IsPrivateIdentifier() && it->AsClassProperty()->Value() != nullptr) {
682 addToCtor.push_back(it->AsClassProperty());
683 }
684 }
685 if (addToCtor.empty()) {
686 return {};
687 }
688
689 auto ctorScopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), node->Ctor()->Function()->Scope());
690
691 ir::BlockStatement *blockStat = node->Ctor()->Function()->Body()->AsBlockStatement();
692 size_t insertPos = GetInsertPosForConstructor(node);
693 for (auto *it : addToCtor) {
694 if (it->IsComputed()) {
695 computedProps.push_back(AllocNode<ir::ExpressionStatement>(it->Key()));
696 }
697
698 ir::MemberExpression *left = nullptr;
699 auto *member = GetClassMemberName(it->Key(), it->IsComputed(), it, false);
700 auto thisExpression = AllocNode<ir::ThisExpression>();
701 // Set the range of the 'this' expression to the property key's range
702 // for accurate debug to the original field. (e.g., the "prop" in '"prop" = 1').
703 thisExpression->SetRange(member->Range());
704 if (member->IsIdentifier() && !it->IsComputed()) {
705 left = AllocNode<ir::MemberExpression>(thisExpression, member,
706 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS,
707 false, false);
708 } else {
709 left = AllocNode<ir::MemberExpression>(thisExpression, member,
710 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
711 true, false);
712 }
713 // Set the range of the property access expression (e.g., this["prop"] or this.prop)
714 // to the property key's range for accurate debug.
715 left->SetRange(member->Range());
716 auto assignment = AllocNode<ir::AssignmentExpression>(left, it->Value(),
717 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
718
719 ResetParentScopeForAstNode(assignment, Scope());
720 blockStat->AddStatementAtPos(insertPos, AllocNode<ir::ExpressionStatement>(assignment));
721 insertPos++;
722 }
723 return computedProps;
724 }
725
VisitTSParameterProperty(ir::ClassDefinition * node)726 void Transformer::VisitTSParameterProperty(ir::ClassDefinition *node)
727 {
728 /*
729 * Add class property for the parameter property declaration in constructor
730 * Transform:
731 * class C {
732 * constructor(public a = 1) {}
733 * }
734 *
735 * To:
736 * class C {
737 * constructor(public a = 1) {
738 * this.a = a;
739 * }
740 * }
741 */
742 auto *func = node->Ctor()->Function();
743 auto *body = func->Body();
744 if (body == nullptr) {
745 return;
746 }
747 auto blockStatement = body->AsBlockStatement();
748 size_t insertPos = GetInsertPosForConstructor(node);
749 for (auto *it : func->Params()) {
750 if (!it->IsTSParameterProperty()) {
751 continue;
752 }
753 auto *parameter = it->AsTSParameterProperty()->Parameter();
754 util::StringView name;
755 // TSParameterPropert only can be identifier or assignment pattern
756 if (parameter->IsIdentifier()) {
757 name = parameter->AsIdentifier()->Name();
758 } else {
759 ASSERT(parameter->IsAssignmentPattern());
760 auto *left = parameter->AsAssignmentPattern()->Left();
761 ASSERT(left->IsIdentifier());
762 name = left->AsIdentifier()->Name();
763 }
764 auto left = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(),
765 AllocNode<ir::Identifier>(name),
766 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
767 auto right = CreateReferenceIdentifier(name);
768 auto assignment = AllocNode<ir::AssignmentExpression>(left, right,
769 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
770 blockStatement->AddStatementAtPos(insertPos, AllocNode<ir::ExpressionStatement>(assignment));
771 insertPos++;
772 }
773 }
774
VisitAutoAccessorProperty(ir::ClassDefinition * node)775 void Transformer::VisitAutoAccessorProperty(ir::ClassDefinition *node)
776 {
777 ASSERT(node != nullptr);
778 std::vector<ir::ClassProperty *> autoAccessorPropertyList;
779 for (auto *it : node->Body()) {
780 if (!it->IsClassProperty()) {
781 continue;
782 }
783 auto* prop = it->AsClassProperty();
784 if (prop->IsAutoAccessor()) {
785 autoAccessorPropertyList.push_back(prop);
786 }
787 }
788 // Must process after iterating complete(can't add node during iterating).
789 for (auto *prop : autoAccessorPropertyList) {
790 ProcessAutoAccessorProperty(prop, node);
791 }
792 }
793
CopyClassKeyExpression(ir::Expression * orginalExpr)794 ir::Expression *Transformer::CopyClassKeyExpression(ir::Expression *orginalExpr)
795 {
796 ir::Expression *newExpr = nullptr;
797 switch (orginalExpr->Type()) {
798 case ir::AstNodeType::IDENTIFIER: {
799 ir::Identifier *ident = orginalExpr->AsIdentifier();
800 newExpr = AllocNode<ir::Identifier>(ident->Name());
801 break;
802 }
803 case ir::AstNodeType::PRIVATE_IDENTIFIER: {
804 ir::PrivateIdentifier *ident = orginalExpr->AsPrivateIdentifier();
805 newExpr = AllocNode<ir::PrivateIdentifier>(ident->Name());
806 break;
807 }
808 case ir::AstNodeType::TS_PRIVATE_IDENTIFIER: {
809 ir::Identifier *ident = orginalExpr->AsTSPrivateIdentifier()->Key()->AsIdentifier();
810 newExpr = AllocNode<ir::Identifier>(ident->Name());
811 break;
812 }
813 case ir::AstNodeType::STRING_LITERAL: {
814 ir::StringLiteral *stringLiteral = orginalExpr->AsStringLiteral();
815 newExpr = AllocNode<ir::StringLiteral>(stringLiteral->Str());
816 break;
817 }
818 case ir::AstNodeType::BIGINT_LITERAL: {
819 ir::BigIntLiteral *bigIntLiteral = orginalExpr->AsBigIntLiteral();
820 newExpr = AllocNode<ir::BigIntLiteral>(bigIntLiteral->Str());
821 break;
822 }
823 case ir::AstNodeType::NUMBER_LITERAL: {
824 auto *numberLiteral = orginalExpr->AsNumberLiteral();
825 newExpr = AllocNode<ir::NumberLiteral>(numberLiteral->Number(), numberLiteral->Str());
826 break;
827 }
828 default: {
829 UNREACHABLE();
830 }
831 }
832 newExpr->SetRange(orginalExpr->Range());
833 return newExpr;
834 }
835
ProcessAutoAccessorProperty(ir::ClassProperty * node,ir::ClassDefinition * classDefinition)836 void Transformer::ProcessAutoAccessorProperty(ir::ClassProperty *node, ir::ClassDefinition *classDefinition)
837 {
838 /*
839 * Transform for auto accessor
840 * class A {
841 * accessor name:string;
842 * }
843 *
844 * To:
845 *
846 * class A {
847 * #__name:string;
848 * get name() {
849 * return this.#__name;
850 * }
851 * set name(value: string) {
852 * this.#__name == value;
853 * }
854 * }
855 *
856 * For computed auto accessor property:
857 * class A {
858 * accessor [name]:string;
859 * }
860 *
861 * To:
862 * var #var_1; // unique name
863 * class A {
864 * #__name:string;
865 * get [#var_1 = name]() {
866 * return this.#__name;
867 * }
868 * set [#var_1](value: string) {
869 * this.#__name == value;
870 * }
871 * }
872 */
873
874 // 1. Create a private property
875 ASSERT(node->Key() != nullptr);
876 auto *originKeyNode = node->Key();
877 auto transformedName = CreatePrivateElementBindName(AUTO_ACCESSOR_STORAGE_NAME);
878 auto *internalIdentifier = AllocNode<ir::Identifier>(transformedName);
879 internalIdentifier->SetRange(originKeyNode->Range());
880 internalIdentifier->SetParent(originKeyNode->Parent());
881 node->SetKey(internalIdentifier);
882
883 util::StringView backupVarName;
884 bool computed = node->IsComputed();
885 if (computed) {
886 backupVarName = CreateNewVariable(true);
887 node->SetComputed(false); // Transform this property to internal property, and removed the computed type.
888 }
889 // 2. Add get and set accessor
890 ir::ModifierFlags modifierMask = ir::ModifierFlags::ACCESS | ir::ModifierFlags::STATIC;
891 ir::ModifierFlags modifiers = static_cast<ir::ModifierFlags>(node->Modifiers() & modifierMask);
892
893 MethodInfo getMethodInfo = {CopyClassKeyExpression(originKeyNode), backupVarName, ir::MethodDefinitionKind::GET,
894 modifiers, computed};
895 AddGeneratedSetOrGetMethodToClass(classDefinition, node, getMethodInfo);
896 MethodInfo setMethodInfo = {CopyClassKeyExpression(originKeyNode), backupVarName, ir::MethodDefinitionKind::SET,
897 modifiers, computed};
898 AddGeneratedSetOrGetMethodToClass(classDefinition, node, setMethodInfo);
899 }
900
AddMethodToClass(ir::ClassDefinition * classDefinition,const MethodInfo & methodInfo,ArenaVector<ir::Expression * > & params,ArenaVector<ir::Statement * > & statements)901 ir::MethodDefinition* Transformer::AddMethodToClass(ir::ClassDefinition *classDefinition,
902 const MethodInfo& methodInfo,
903 ArenaVector<ir::Expression *> ¶ms,
904 ArenaVector<ir::Statement *> &statements)
905 {
906 CHECK_NOT_NULL(classDefinition);
907 ASSERT((methodInfo.kind == ir::MethodDefinitionKind::GET) || (methodInfo.kind == ir::MethodDefinitionKind::SET));
908
909 auto *paramScope = Binder()->Allocator()->New<binder::FunctionParamScope>(Allocator(), Binder()->GetScope());
910 CHECK_NOT_NULL(paramScope);
911 for (auto ¶m : params) {
912 paramScope->AddParamDecl(Allocator(), param);
913 }
914 auto *scope = Binder()->Allocator()->New<binder::FunctionScope>(Allocator(), paramScope);
915 CHECK_NOT_NULL(scope);
916 paramScope->BindFunctionScope(scope);
917 auto *body = AllocNode<ir::BlockStatement>(scope, std::move(statements));
918 auto *func = AllocNode<ir::ScriptFunction>(scope, std::move(params), nullptr, body, nullptr,
919 ir::ScriptFunctionFlags::METHOD, false, false);
920 scope->BindNode(func);
921 scope->BindParamScope(paramScope);
922 paramScope->BindNode(func);
923
924 auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
925 ir::Expression *keyNode = nullptr;
926 if (!methodInfo.isComputed) {
927 keyNode = methodInfo.key;
928 } else {
929 if (methodInfo.kind == ir::MethodDefinitionKind::GET) {
930 auto *backupNode = CreateReferenceIdentifier(methodInfo.backupName);
931 keyNode = AllocNode<ir::AssignmentExpression>(backupNode, methodInfo.key,
932 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
933 } else {
934 auto *backupNode = CreateReferenceIdentifier(methodInfo.backupName);
935 keyNode = backupNode;
936 }
937 }
938
939 ArenaVector<ir::Decorator *> decorators(Allocator()->Adapter());
940 ArenaVector<ir::Annotation *> annotations(Allocator()->Adapter());
941 ArenaVector<ir::ParamDecorators> paramDecorators(Allocator()->Adapter());
942 auto *method = AllocNode<ir::MethodDefinition>(methodInfo.kind, keyNode, funcExpr,
943 methodInfo.modifiers, Allocator(), std::move(decorators),
944 std::move(annotations), std::move(paramDecorators),
945 methodInfo.isComputed);
946 classDefinition->AddToBody(method);
947 if (methodInfo.isComputed) {
948 AddComputedPropertyBinding(method, methodInfo.backupName);
949 }
950 return method;
951 }
952
AddGeneratedMethodToClass(ir::ClassDefinition * classDefinition,const MethodInfo & methodInfo,util::StringView propName)953 ir::MethodDefinition* Transformer::AddGeneratedMethodToClass(ir::ClassDefinition *classDefinition,
954 const MethodInfo &methodInfo,
955 util::StringView propName)
956 {
957 ASSERT(classDefinition != nullptr);
958 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
959 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
960
961 if (methodInfo.kind == ir::MethodDefinitionKind::GET) {
962 /*
963 * Add `return this.prop` to function body.
964 */
965 auto *identNode = AllocNode<ir::Identifier>(propName);
966 auto *returnExpr = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), identNode,
967 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
968 ir::ReturnStatement *returnStatement = AllocNode<ir::ReturnStatement>(returnExpr);
969 statements.push_back(returnStatement);
970 } else if (methodInfo.kind == ir::MethodDefinitionKind::SET) {
971 /*
972 * 1. Add `value` to params
973 * 2. Add `this.prop = value` to function body
974 */
975 util::StringView paramName = util::UString("value", Allocator()).View();
976 auto *identNode = AllocNode<ir::Identifier>(paramName);
977 params.push_back(identNode);
978
979 auto *identNodeProp = AllocNode<ir::Identifier>(propName);
980 auto *propAccessExpr = AllocNode<ir::MemberExpression>(AllocNode<ir::ThisExpression>(), identNodeProp,
981 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
982 auto *identNodeRight = AllocNode<ir::Identifier>(paramName);
983 auto *setExpr = AllocNode<ir::AssignmentExpression>(propAccessExpr, identNodeRight,
984 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
985 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(setExpr);
986 statements.push_back(exprStatementNode);
987 } else {
988 UNREACHABLE();
989 }
990 auto *method = AddMethodToClass(classDefinition, methodInfo, params, statements);
991 return method;
992 }
993
AddGeneratedSetOrGetMethodToClass(ir::ClassDefinition * classDefinition,ir::ClassProperty * propertyNode,const MethodInfo & methodInfo)994 void Transformer::AddGeneratedSetOrGetMethodToClass(ir::ClassDefinition *classDefinition,
995 ir::ClassProperty *propertyNode,
996 const MethodInfo &methodInfo)
997 {
998 ASSERT(classDefinition != nullptr);
999 ASSERT(propertyNode != nullptr);
1000 // The key of the property can only be Idetifier here.
1001 auto propName = propertyNode->Key()->AsIdentifier()->Name();
1002 auto *method = AddGeneratedMethodToClass(classDefinition, methodInfo, propName);
1003 method->SetOriginal(propertyNode);
1004 method->SetRange(propertyNode->Range());
1005 }
1006
VisitStaticProperty(ir::ClassDefinition * node,util::StringView name)1007 std::vector<ir::ExpressionStatement *> Transformer::VisitStaticProperty(ir::ClassDefinition *node,
1008 util::StringView name)
1009 {
1010 /*
1011 * Create statement for static class property
1012 * If it's a conputed property, we should initialize it's new variable first.
1013 * Transform:
1014 * var ##var_1;
1015 * class C {
1016 * static a = 1
1017 * static [##var_1 = s] = 1
1018 * }
1019 *
1020 * To:
1021 * var ##var_1;
1022 * class C {
1023 * }
1024 * C.a = 1;
1025 * ##var_1 = s;
1026 * C[##var_1] = 1;
1027 *
1028 * TODO(xucheng): should support static private property
1029 */
1030
1031 // When targetApiVersion is greater than 10, for classes with decorators,
1032 // the static public class properties in them will go through the transform process.
1033 // The number 10 is used to indicate the target api version
1034 if (program_->TargetApiVersion() > 10 && !(node->IsClassDecoratorPresent())) {
1035 return {};
1036 }
1037
1038 std::vector<ir::ExpressionStatement *> res;
1039 auto classDefinitionBody = node->Body();
1040 for (auto *it : classDefinitionBody) {
1041 if (!it->IsClassProperty()) {
1042 continue;
1043 }
1044 auto *classProperty = it->AsClassProperty();
1045 if (!classProperty->IsStatic()) {
1046 continue;
1047 }
1048
1049 // if property in the form of `static #a`, it will not be processed.
1050 if (classProperty->IsPrivate()) {
1051 continue;
1052 }
1053
1054 if (classProperty->IsComputed()) {
1055 res.push_back(AllocNode<ir::ExpressionStatement>(classProperty->Key()));
1056 }
1057 auto right = classProperty->Value();
1058 if (right == nullptr) {
1059 continue;
1060 }
1061
1062 ir::MemberExpression *left = nullptr;
1063 auto *member = GetClassMemberName(classProperty->Key(), classProperty->IsComputed(), classProperty, false);
1064 if (member->IsIdentifier() && !classProperty->IsComputed()) {
1065 left = AllocNode<ir::MemberExpression>(CreateReferenceIdentifier(name), member,
1066 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS,
1067 false, false);
1068 } else {
1069 left = AllocNode<ir::MemberExpression>(CreateReferenceIdentifier(name), member,
1070 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
1071 true, false);
1072 }
1073 auto assignment = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1074
1075 // When TargetApiVersion is greater than 10, for classes with decorators,
1076 // the value of the public static class property in the class will be assigned to nullptr,
1077 // and the value will be assigned outside the class.
1078 // The number 10 is used to indicate the target api version
1079 if (program_->TargetApiVersion() > 10) {
1080 classProperty->RemoveValue();
1081 }
1082 res.push_back(AllocNode<ir::ExpressionStatement>(assignment));
1083 }
1084 return res;
1085 }
1086
VisitClassDeclaration(ir::ClassDeclaration * node)1087 ir::UpdateNodes Transformer::VisitClassDeclaration(ir::ClassDeclaration *node)
1088 {
1089 auto name = node->Definition()->GetName();
1090 std::vector<ir::AstNode *> res;
1091 bool hasClassDecorators = node->HasDecorators();
1092 if (hasClassDecorators) {
1093 auto aliasName = GetClassAliasName();
1094 res.push_back(CreateVariableDeclarationWithIdentify(aliasName, VariableParsingFlags::VAR, nullptr, false));
1095 auto *clsExpression = AllocNode<ir::ClassExpression>(node->Definition());
1096 auto *assignExpr = AllocNode<ir::AssignmentExpression>(CreateReferenceIdentifier(aliasName), clsExpression,
1097 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1098 res.push_back(CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::LET, node, false,
1099 assignExpr, false));
1100 } else {
1101 res.push_back(node);
1102 }
1103
1104 auto instanceComputedProperty = VisitInstanceProperty(node->Definition());
1105 // instanceComputedProperty has been transformed by VisitComputedPerporty before, here is an assignmentExpression.
1106 if (!instanceComputedProperty.empty()) {
1107 res.insert(res.end(), instanceComputedProperty.begin(), instanceComputedProperty.end());
1108 }
1109
1110 VisitTSParameterProperty(node->Definition());
1111
1112 auto staticProperty = VisitStaticProperty(node->Definition(), name);
1113 if (!staticProperty.empty()) {
1114 res.insert(res.end(), staticProperty.begin(), staticProperty.end());
1115 }
1116
1117 auto classDefinitionBody = node->Definition()->Body();
1118 bool hasPrivateIdentifier = HasPrivateIdentifierInDecorators(node->Definition());
1119 ir::ClassStaticBlock *staticBlock = CreateClassStaticBlock(node, hasPrivateIdentifier);
1120
1121 // decorators of static members, should be called after instance members
1122 std::vector<ir::AstNode *> staticMemberDecorators;
1123 for (auto *it : classDefinitionBody) {
1124 auto scopeCtx = binder::LexicalScope<binder::Scope>::Enter(Binder(),
1125 hasPrivateIdentifier ? staticBlock->GetBody()->Scope() : Scope());
1126 if (it->IsMethodDefinition()) {
1127 auto *definition = it->AsMethodDefinition();
1128 bool isStatic = definition->IsStatic();
1129
1130 auto variableDeclarations = CreateVariableDeclarationForDecorators(definition);
1131 if (isStatic) {
1132 staticMemberDecorators.insert(staticMemberDecorators.end(),
1133 variableDeclarations.begin(), variableDeclarations.end());
1134 } else if (!hasPrivateIdentifier) {
1135 res.insert(res.end(), variableDeclarations.begin(), variableDeclarations.end());
1136 }
1137
1138 auto paramDecorators = CreateParamDecorators(name, definition, variableDeclarations, false, isStatic);
1139 if (isStatic) {
1140 staticMemberDecorators.insert(staticMemberDecorators.end(),
1141 paramDecorators.begin(), paramDecorators.end());
1142 } else if (!hasPrivateIdentifier) {
1143 res.insert(res.end(), paramDecorators.begin(), paramDecorators.end());
1144 }
1145
1146 if (!definition->HasDecorators()) {
1147 continue;
1148 }
1149
1150 auto methodDecorators = CreateMethodDecorators(name, definition, variableDeclarations, isStatic);
1151 if (isStatic) {
1152 staticMemberDecorators.insert(staticMemberDecorators.end(),
1153 methodDecorators.begin(), methodDecorators.end());
1154 } else if (!hasPrivateIdentifier) {
1155 res.insert(res.end(), methodDecorators.begin(), methodDecorators.end());
1156 }
1157
1158 if (hasPrivateIdentifier && !isStatic) {
1159 for (auto *it : variableDeclarations) {
1160 staticBlock->GetBody()->AddStatementAtPos(
1161 staticBlock->GetBody()->Statements().size(), it->AsStatement());
1162 }
1163 for (auto *it : paramDecorators) {
1164 staticBlock->GetBody()->AddStatementAtPos(
1165 staticBlock->GetBody()->Statements().size(), it->AsStatement());
1166 }
1167 for (auto *it : methodDecorators) {
1168 staticBlock->GetBody()->AddStatementAtPos(
1169 staticBlock->GetBody()->Statements().size(), it->AsStatement());
1170 }
1171 }
1172 } else if (it->IsClassProperty()) {
1173 auto *classProperty = it->AsClassProperty();
1174 bool isStatic = classProperty->IsStatic();
1175 if (!classProperty->HasDecorators()) {
1176 continue;
1177 }
1178
1179 if (classProperty->IsComputed() && !isStatic && classProperty->Value() == nullptr) {
1180 res.push_back(AllocNode<ir::ExpressionStatement>(classProperty->Key()));
1181 }
1182
1183 auto variableDeclarations = CreateVariableDeclarationForDecorators(classProperty);
1184 if (isStatic) {
1185 staticMemberDecorators.insert(staticMemberDecorators.end(),
1186 variableDeclarations.begin(), variableDeclarations.end());
1187 } else if (!hasPrivateIdentifier) {
1188 res.insert(res.end(), variableDeclarations.begin(), variableDeclarations.end());
1189 }
1190
1191 auto propertyDecorators = CreatePropertyDecorators(name, classProperty, variableDeclarations, isStatic);
1192 if (isStatic) {
1193 staticMemberDecorators.insert(staticMemberDecorators.end(),
1194 propertyDecorators.begin(), propertyDecorators.end());
1195 } else if (!hasPrivateIdentifier) {
1196 res.insert(res.end(), propertyDecorators.begin(), propertyDecorators.end());
1197 }
1198
1199 if (hasPrivateIdentifier && !isStatic) {
1200 for (auto *it : variableDeclarations) {
1201 staticBlock->GetBody()->AddStatementAtPos(
1202 staticBlock->GetBody()->Statements().size(), it->AsStatement());
1203 }
1204 for (auto *it : propertyDecorators) {
1205 staticBlock->GetBody()->AddStatementAtPos(
1206 staticBlock->GetBody()->Statements().size(), it->AsStatement());
1207 }
1208 }
1209 }
1210 }
1211
1212 if (!staticMemberDecorators.empty()) {
1213 if (hasPrivateIdentifier) {
1214 for (auto *it : staticMemberDecorators) {
1215 staticBlock->GetBody()->AddStatementAtPos(
1216 staticBlock->GetBody()->Statements().size(), it->AsStatement());
1217 }
1218 } else {
1219 res.insert(res.end(), staticMemberDecorators.begin(), staticMemberDecorators.end());
1220 }
1221 }
1222
1223 auto variableDeclarationsForCtorOrClass = CreateVariableDeclarationForDecorators(node);
1224 res.insert(res.end(), variableDeclarationsForCtorOrClass.begin(), variableDeclarationsForCtorOrClass.end());
1225
1226 // constructor decorators
1227 auto *ctor = node->Definition()->Ctor();
1228 auto ctorParamDecorators = CreateParamDecorators(name, ctor, variableDeclarationsForCtorOrClass, true, false);
1229 res.insert(res.end(), ctorParamDecorators.begin(), ctorParamDecorators.end());
1230
1231 // class decorators
1232 if (hasClassDecorators) {
1233 auto classDecorators = CreateClassDecorators(node, variableDeclarationsForCtorOrClass);
1234 res.insert(res.end(), classDecorators.begin(), classDecorators.end());
1235 }
1236 if (res.size() == 1) {
1237 return res.front();
1238 }
1239 return res;
1240 }
1241
CreateClassStaticBlock(ir::ClassDeclaration * node,bool hasPrivateIdentifer)1242 ir::ClassStaticBlock *Transformer::CreateClassStaticBlock(ir::ClassDeclaration *node, bool hasPrivateIdentifer)
1243 {
1244 if (!hasPrivateIdentifer) {
1245 return nullptr;
1246 }
1247
1248 ir::MethodDefinition *staticInitializer = node->Definition()->StaticInitializer();
1249 auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(),
1250 staticInitializer->Function()->Scope());
1251
1252 auto lexScope = binder::LexicalScope<binder::StaticBlockScope>(Binder());
1253 ir::BlockStatement *blockStatement = nullptr;
1254
1255 {
1256 auto localCtx = binder::LexicalScope<binder::LocalScope>(Binder());
1257 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
1258 blockStatement = AllocNode<ir::BlockStatement>(localCtx.GetScope(), std::move(statements));
1259 localCtx.GetScope()->BindNode(blockStatement);
1260 }
1261
1262 ir::ClassStaticBlock *staticBlock = AllocNode<ir::ClassStaticBlock>(lexScope.GetScope(), blockStatement);
1263 lexScope.GetScope()->BindNode(staticBlock);
1264 node->Definition()->AddToBody(staticBlock);
1265
1266 return staticBlock;
1267 }
1268
HasPrivateIdentifierInDecorators(const ir::ClassDefinition * classDefinition)1269 bool Transformer::HasPrivateIdentifierInDecorators(const ir::ClassDefinition *classDefinition)
1270 {
1271 bool hasPrivateIdentifer = false;
1272 for (auto *it : classDefinition->Body()) {
1273 if (it->IsMethodDefinition()) {
1274 auto methodDecorators = it->AsMethodDefinition()->Decorators();
1275 for (size_t i = 0; i < methodDecorators.size(); i++) {
1276 FindPrivateIdentifierInDecorator(methodDecorators[i]->Expr(), &hasPrivateIdentifer);
1277 if (hasPrivateIdentifer) {
1278 return true;
1279 }
1280 }
1281
1282 auto paramsDecorators = it->AsMethodDefinition()->GetParamDecorators();
1283 for (size_t i = 0; i < paramsDecorators.size(); i++) {
1284 auto paramDecorators = paramsDecorators[i].decorators;
1285 for (size_t j = 0; j < paramDecorators.size(); j++) {
1286 FindPrivateIdentifierInDecorator(paramDecorators[j]->Expr(), &hasPrivateIdentifer);
1287 if (hasPrivateIdentifer) {
1288 return true;
1289 }
1290 }
1291 }
1292 } else if (it->IsClassProperty()) {
1293 auto propDecorators = it->AsClassProperty()->Decorators();
1294 for (size_t i = 0; i < propDecorators.size(); i++) {
1295 FindPrivateIdentifierInDecorator(propDecorators[i]->Expr(), &hasPrivateIdentifer);
1296 if (hasPrivateIdentifer) {
1297 return true;
1298 }
1299 }
1300 }
1301 }
1302
1303 return hasPrivateIdentifer;
1304 }
1305
FindPrivateIdentifierInDecorator(const ir::AstNode * parent,bool * hasprivateIdentifier)1306 void Transformer::FindPrivateIdentifierInDecorator(const ir::AstNode *parent, bool *hasprivateIdentifier)
1307 {
1308 parent->Iterate([this, hasprivateIdentifier](auto *childNode) {
1309 FindPrivateIdentifierInChildNode(childNode, hasprivateIdentifier);
1310 });
1311 }
1312
FindPrivateIdentifierInChildNode(const ir::AstNode * childNode,bool * hasprivateIdentifier)1313 void Transformer::FindPrivateIdentifierInChildNode(const ir::AstNode *childNode, bool *hasprivateIdentifier)
1314 {
1315 if (*hasprivateIdentifier) {
1316 return;
1317 }
1318
1319 switch (childNode->Type()) {
1320 case ir::AstNodeType::MEMBER_EXPRESSION: {
1321 if (childNode->AsMemberExpression()->Property()->IsPrivateIdentifier()) {
1322 *hasprivateIdentifier = true;
1323 return;
1324 }
1325 break;
1326 }
1327 default: {
1328 FindPrivateIdentifierInDecorator(childNode, hasprivateIdentifier);
1329 break;
1330 }
1331 }
1332 }
1333
CreateVariableDeclarationForDecorators(ir::AstNode * node)1334 std::vector<ir::AstNode *> Transformer::CreateVariableDeclarationForDecorators(ir::AstNode *node)
1335 {
1336 std::vector<ir::AstNode *> res;
1337
1338 switch (node->Type()) {
1339 case ir::AstNodeType::METHOD_DEFINITION: {
1340 auto methodDecorators = node->AsMethodDefinition()->Decorators();
1341 for (size_t i = 0; i < methodDecorators.size(); i++) {
1342 util::StringView varName = CreateNewVariable(false);
1343 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr,
1344 false, methodDecorators[i]->Expr(), true));
1345 }
1346
1347 auto paramsDecorators = node->AsMethodDefinition()->GetParamDecorators();
1348 for (size_t i = 0; i < paramsDecorators.size(); i++) {
1349 auto paramDecorators = paramsDecorators[i].decorators;
1350 for (size_t j = 0; j < paramDecorators.size(); j++) {
1351 util::StringView varName = CreateNewVariable(false);
1352 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr,
1353 false, paramDecorators[j]->Expr(), true));
1354 }
1355 }
1356 return res;
1357 }
1358 case ir::AstNodeType::CLASS_PROPERTY: {
1359 auto propDecorators = node->AsClassProperty()->Decorators();
1360 for (size_t i = 0; i < propDecorators.size(); i++) {
1361 util::StringView varName = CreateNewVariable(false);
1362 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr,
1363 false, propDecorators[i]->Expr(), true));
1364 }
1365 return res;
1366 }
1367 case ir::AstNodeType::CLASS_DECLARATION: {
1368 auto classDecorators = node->AsClassDeclaration()->Decorators();
1369 for (size_t i = 0; i < classDecorators.size(); i++) {
1370 util::StringView varName = CreateNewVariable(false);
1371 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr,
1372 false, classDecorators[i]->Expr(), true));
1373 }
1374
1375 auto ctorParamsDecorators = node->AsClassDeclaration()->Definition()->Ctor()->GetParamDecorators();
1376 for (size_t i = 0; i < ctorParamsDecorators.size(); i++) {
1377 auto ctorParamDecorators = ctorParamsDecorators[i].decorators;
1378 for (size_t j = 0; j < ctorParamDecorators.size(); j++) {
1379 util::StringView varName = CreateNewVariable(false);
1380 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr,
1381 false, ctorParamDecorators[j]->Expr(), true));
1382 }
1383 }
1384 return res;
1385 }
1386 default: {
1387 UNREACHABLE();
1388 }
1389 }
1390 }
1391
CreateParamDecorators(util::StringView className,ir::MethodDefinition * node,const std::vector<ir::AstNode * > & variableDeclarations,bool isConstructor,bool isStatic)1392 std::vector<ir::AstNode *> Transformer::CreateParamDecorators(util::StringView className,
1393 ir::MethodDefinition *node,
1394 const std::vector<ir::AstNode *> &variableDeclarations,
1395 bool isConstructor,
1396 bool isStatic)
1397 {
1398 /*
1399 * Param decorators
1400 * Transform:
1401 * class C {
1402 * f(@g a){}
1403 * }
1404 *
1405 * To:
1406 * class C {
1407 * f(a){}
1408 * }
1409 * g(C.prototype, "f", 0)
1410 *
1411 * Static method or constructor will use constructor function of the class instead of prototype of class
1412 */
1413 std::vector<ir::AstNode *> res;
1414 size_t pos = variableDeclarations.size();
1415 auto paramsDecorators = node->GetParamDecorators();
1416 for (int i = static_cast<int>(paramsDecorators.size()) - 1; i >= 0; i--) {
1417 auto paramIndex = paramsDecorators[i].paramIndex;
1418 auto decorators = paramsDecorators[i].decorators;
1419 for (int j = static_cast<int>(decorators.size()) - 1; j >= 0; j--) {
1420 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1421 arguments.push_back(CreateDecoratorTarget(className, isConstructor || isStatic));
1422 arguments.push_back(isConstructor ?
1423 CreateReferenceIdentifier(CONSTRUCTOR_NAME) :
1424 GetClassMemberName(node->Key(), node->Computed(), node));
1425 arguments.push_back(AllocNode<ir::NumberLiteral>(paramIndex));
1426 auto *callExpr = AllocNode<ir::CallExpression>(
1427 variableDeclarations[--pos]->AsVariableDeclaration()->Declarators().front()->Id(),
1428 std::move(arguments), nullptr, false);
1429 res.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
1430 }
1431 }
1432 return res;
1433 }
1434
CreatePropertyDecorators(util::StringView className,ir::ClassProperty * node,const std::vector<ir::AstNode * > & variableDeclarations,bool isStatic)1435 std::vector<ir::AstNode *> Transformer::CreatePropertyDecorators(util::StringView className,
1436 ir::ClassProperty *node,
1437 const std::vector<ir::AstNode *> &variableDeclarations,
1438 bool isStatic)
1439 {
1440 /*
1441 * Property decorators
1442 * Transform:
1443 * class C {
1444 * @f a = 1
1445 * }
1446 *
1447 * To:
1448 * class C {
1449 * a = 1
1450 * }
1451 * f(C.prototype, "a")
1452 *
1453 * Static property will use constructor function of the class instead of prototype of class
1454 */
1455 std::vector<ir::AstNode *> res;
1456 auto decorators = node->Decorators();
1457 for (int i = static_cast<int>(decorators.size() - 1); i >= 0; i--) {
1458 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1459 arguments.push_back(CreateDecoratorTarget(className, isStatic));
1460 arguments.push_back(GetClassMemberName(node->Key(), node->IsComputed(), node));
1461 auto *callExpr = AllocNode<ir::CallExpression>(
1462 variableDeclarations[i]->AsVariableDeclaration()->Declarators().front()->Id(),
1463 std::move(arguments), nullptr, false);
1464
1465 res.push_back(AllocNode<ir::ExpressionStatement>(callExpr));
1466 }
1467 return res;
1468 }
1469
CreateMethodDecorators(util::StringView className,ir::MethodDefinition * node,const std::vector<ir::AstNode * > & variableDeclarations,bool isStatic)1470 std::vector<ir::AstNode *> Transformer::CreateMethodDecorators(util::StringView className,
1471 ir::MethodDefinition *node,
1472 const std::vector<ir::AstNode *> &variableDeclarations,
1473 bool isStatic)
1474 {
1475 /*
1476 * Method decorators and accessor decorators
1477 * Transform:
1478 * class C {
1479 * @g
1480 * f(){}
1481 * }
1482 *
1483 * To:
1484 * class C {
1485 * f(){}
1486 * }
1487 * var ###a = Object.getOwnPropertyDescriptor(C.prototype, "f");
1488 * Object.defineProperty(C.prototype, "f",
1489 * g(C.prototype, "f", ###a) || ###a);
1490 *
1491 * static method will use constructor function of the class instead of prototype of class
1492 * If the decorator has a return value, it will be set as the new property of the method
1493 */
1494 std::vector<ir::AstNode *> res;
1495 size_t pos = node->Decorators().size();
1496 auto decorators = node->Decorators();
1497 for (int i = static_cast<int>(decorators.size() - 1); i >= 0; i--) {
1498 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1499 arguments.push_back(CreateDecoratorTarget(className, isStatic));
1500 arguments.push_back(GetClassMemberName(node->Key(), node->Computed(), node));
1501 util::StringView varName = CreateNewVariable(false);
1502 auto getOwnPropertyDescriptorCall = CreateGetOwnPropertyDescriptorCall(
1503 CreateDecoratorTarget(className, isStatic), GetClassMemberName(node->Key(), node->Computed(), node));
1504 res.push_back(CreateVariableDeclarationWithIdentify(varName, VariableParsingFlags::LET, nullptr,
1505 false, getOwnPropertyDescriptorCall, true));
1506 arguments.push_back(AllocNode<ir::Identifier>(varName));
1507 auto *callExpr = AllocNode<ir::CallExpression>(
1508 variableDeclarations[--pos]->AsVariableDeclaration()->Declarators().front()->Id(),
1509 std::move(arguments), nullptr, false);
1510
1511 auto newValue = AllocNode<ir::BinaryExpression>(callExpr, AllocNode<ir::Identifier>(varName),
1512 lexer::TokenType::PUNCTUATOR_LOGICAL_OR);
1513
1514 auto *defineProperty = CreateDefinePropertyCall(CreateDecoratorTarget(className, isStatic),
1515 GetClassMemberName(node->Key(), node->Computed(), node), newValue);
1516
1517 res.push_back(AllocNode<ir::ExpressionStatement>(defineProperty));
1518 }
1519 return res;
1520 }
1521
CreateDecoratorTarget(util::StringView className,bool isStatic)1522 ir::Expression *Transformer::CreateDecoratorTarget(util::StringView className, bool isStatic)
1523 {
1524 if (isStatic) {
1525 return CreateReferenceIdentifier(className);
1526 }
1527 return CreateClassPrototype(className);
1528 }
1529
CreateClassPrototype(util::StringView className)1530 ir::MemberExpression *Transformer::CreateClassPrototype(util::StringView className)
1531 {
1532 auto *cls = CreateReferenceIdentifier(className);
1533 return AllocNode<ir::MemberExpression>(cls, AllocNode<ir::Identifier>(CLASS_PROTOTYPE),
1534 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1535 }
1536
CreateDefinePropertyCall(ir::Expression * target,ir::Expression * key,ir::Expression * value)1537 ir::CallExpression *Transformer::CreateDefinePropertyCall(ir::Expression *target,
1538 ir::Expression *key,
1539 ir::Expression *value)
1540 {
1541 auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME);
1542 auto *caller = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(FUNC_NAME_OF_DEFINE_PROPERTY),
1543 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1544 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1545 arguments.push_back(target);
1546 arguments.push_back(key);
1547 arguments.push_back(value);
1548 return AllocNode<ir::CallExpression>(caller, std::move(arguments), nullptr, false);
1549 }
1550
CreateGetOwnPropertyDescriptorCall(ir::Expression * target,ir::Expression * key)1551 ir::CallExpression *Transformer::CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key)
1552 {
1553 auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME);
1554 auto *caller = AllocNode<ir::MemberExpression>(id,
1555 AllocNode<ir::Identifier>(FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR),
1556 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1557 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1558 arguments.push_back(target);
1559 arguments.push_back(key);
1560 return AllocNode<ir::CallExpression>(caller, std::move(arguments), nullptr, false);
1561 }
1562
GetClassMemberName(ir::Expression * key,bool isComputed,ir::Statement * node,bool inDecorator)1563 ir::Expression *Transformer::GetClassMemberName(ir::Expression *key, bool isComputed,
1564 ir::Statement *node, bool inDecorator)
1565 {
1566 if (isComputed) {
1567 auto name = GetComputedPropertyBinding(node);
1568 auto *ident = AllocNode<ir::Identifier>(name);
1569 ident->SetRange(key->Range());
1570 return ident;
1571 }
1572 if (key->IsIdentifier()) {
1573 if (inDecorator) {
1574 auto *strLiteral = AllocNode<ir::StringLiteral>(key->AsIdentifier()->Name());
1575 strLiteral->SetRange(key->AsIdentifier()->Range());
1576 return strLiteral;
1577 } else {
1578 auto *ident = AllocNode<ir::Identifier>(key->AsIdentifier()->Name());
1579 ident->SetRange(key->AsIdentifier()->Range());
1580 return ident;
1581 }
1582 } else if (key->IsStringLiteral()) {
1583 auto *strLiteral = AllocNode<ir::StringLiteral>(key->AsStringLiteral()->Str());
1584 strLiteral->SetRange(key->AsStringLiteral()->Range());
1585 return strLiteral;
1586 } else if (key->IsNumberLiteral()) {
1587 auto *numLiteral = AllocNode<ir::NumberLiteral>(key->AsNumberLiteral()->Number(),
1588 key->AsNumberLiteral()->Str());
1589 numLiteral->SetRange(key->AsNumberLiteral()->Range());
1590 return numLiteral;
1591 } else if (key->IsBigIntLiteral()) {
1592 auto *bigIntLiteral = AllocNode<ir::BigIntLiteral>(key->AsBigIntLiteral()->Str());
1593 bigIntLiteral->SetRange(key->AsBigIntLiteral()->Range());
1594 return bigIntLiteral;
1595 }
1596 UNREACHABLE();
1597 return nullptr;
1598 }
1599
CreateClassDecorators(ir::ClassDeclaration * node,const std::vector<ir::AstNode * > & variableDeclarations)1600 std::vector<ir::AstNode *> Transformer::CreateClassDecorators(ir::ClassDeclaration *node,
1601 const std::vector<ir::AstNode *> &variableDeclarations)
1602 {
1603 /*
1604 * Class decorators
1605 * Transform:
1606 * @f
1607 * class C {
1608 * }
1609 *
1610 * To:
1611 * class C {
1612 * }
1613 * C = f(C) || C;
1614 *
1615 * If the decorator has a return value, it will be used as the new declaration of the class
1616 */
1617 auto name = node->Definition()->GetName();
1618 auto decorators = node->Decorators();
1619 auto size = decorators.size();
1620 size_t pos = size;
1621 std::vector<ir::AstNode *> res;
1622 for (int i = static_cast<int>(size - 1); i >= 0; i--) {
1623 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1624 arguments.push_back(CreateReferenceIdentifier(name));
1625 auto *callExpr = AllocNode<ir::CallExpression>(
1626 variableDeclarations[--pos]->AsVariableDeclaration()->Declarators().front()->Id(),
1627 std::move(arguments), nullptr, false);
1628
1629 auto left = CreateReferenceIdentifier(name);
1630 auto id = CreateReferenceIdentifier(name);
1631 auto right = AllocNode<ir::BinaryExpression>(callExpr, id, lexer::TokenType::PUNCTUATOR_LOGICAL_OR);
1632 auto middle = CreateReferenceIdentifier(GetClassAliasName());
1633 auto innerAssignExpr = AllocNode<ir::AssignmentExpression>(middle, right,
1634 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1635 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, innerAssignExpr,
1636 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1637
1638 res.push_back(AllocNode<ir::ExpressionStatement>(assignExpr));
1639 }
1640 return res;
1641 }
1642
VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration * node)1643 ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node)
1644 {
1645 if (!IsInstantiatedImportEquals(node, Scope())) {
1646 return node;
1647 }
1648 auto *express = node->ModuleReference();
1649 auto name = node->Id()->Name();
1650 if (IsTsModule() && node->IsExport()) {
1651 auto moduleName = GetCurrentTSModuleName();
1652 auto *id = CreateReferenceIdentifier(moduleName);
1653 auto *left = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name),
1654 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1655 ir::Expression *right = CreateMemberExpressionFromQualified(express);
1656 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right,
1657 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1658 auto *res = AllocNode<ir::ExpressionStatement>(assignExpr);
1659 return res;
1660 }
1661
1662 ir::Expression *init = CreateMemberExpressionFromQualified(express);
1663 ir::Statement *res = CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::VAR, node,
1664 node->IsExport(), init);
1665 if (node->IsExport()) {
1666 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
1667 res = AllocNode<ir::ExportNamedDeclaration>(res, std::move(specifiers));
1668 AddExportLocalEntryItem(name, node->Id());
1669 }
1670 return res;
1671 }
1672
IsInstantiatedImportEquals(const ir::TSImportEqualsDeclaration * node,binder::Scope * scope) const1673 bool Transformer::IsInstantiatedImportEquals(const ir::TSImportEqualsDeclaration *node, binder::Scope *scope) const
1674 {
1675 if (!node) {
1676 return false;
1677 }
1678 bool isType = true;
1679 auto *var = FindTSModuleVariable(node->ModuleReference(), scope, &isType);
1680 if (var == nullptr) {
1681 return !isType;
1682 }
1683 auto *decl = var->Declaration();
1684 ASSERT(decl->IsNamespaceDecl());
1685 return decl->AsNamespaceDecl()->IsInstantiated();
1686 return false;
1687 }
1688
FindTSModuleVariable(const ir::Expression * node,const binder::Scope * scope,bool * isType) const1689 binder::Variable *Transformer::FindTSModuleVariable(const ir::Expression *node,
1690 const binder::Scope *scope,
1691 bool *isType) const
1692 {
1693 if (node == nullptr || !(node->IsTSQualifiedName() || node->IsIdentifier())) {
1694 return nullptr;
1695 }
1696 if (node->IsTSQualifiedName()) {
1697 auto *tsQualifiedName = node->AsTSQualifiedName();
1698 auto *var = FindTSModuleVariable(tsQualifiedName->Left(), scope, isType);
1699 if (var == nullptr) {
1700 // If it's not a namespace, we would set isType flag before. So we don't set isType here.
1701 return nullptr;
1702 }
1703 auto *exportTSBindings = var->AsNamespaceVariable()->GetExportBindings();
1704 auto name = tsQualifiedName->Right()->Name();
1705 binder::Variable *res = exportTSBindings->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
1706 if (res != nullptr) {
1707 return res;
1708 }
1709 res = exportTSBindings->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
1710 if (res != nullptr) {
1711 auto *node = res->Declaration()->Node();
1712 return FindTSModuleVariable(node->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(),
1713 res->AsImportEqualsVariable()->GetScope(), isType);
1714 }
1715
1716 // We process namespace and import equals before. So it should be a type, if it's not a js value or enum.
1717 // And const enum was processed as enum in es2abc, so we don't thought it as type here.
1718 // We should process const enum as type, if we change const enum to literal in es2abc later.
1719 *isType = exportTSBindings->FindExportVariable(name) == nullptr &&
1720 exportTSBindings->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name) == nullptr;
1721
1722 return nullptr;
1723 }
1724
1725 auto name = node->AsIdentifier()->Name();
1726 auto *currentScope = scope;
1727 while (currentScope != nullptr) {
1728 auto *res = FindTSVariable<binder::TSBindingType::NAMESPACE>(currentScope, name);
1729 if (res != nullptr) {
1730 return res;
1731 }
1732
1733 res = FindTSVariable<binder::TSBindingType::IMPORT_EQUALS>(currentScope, name);
1734 if (res != nullptr) {
1735 auto *node = res->Declaration()->Node();
1736 return FindTSModuleVariable(node->Parent()->AsTSImportEqualsDeclaration()->ModuleReference(),
1737 res->AsImportEqualsVariable()->GetScope(), isType);
1738 }
1739
1740 // Enum is not a module, so we return null here.
1741 // Const enum was processed as enum in es2abc, so we don't process it as type here.
1742 res = FindTSVariable<binder::TSBindingType::ENUMLITERAL>(currentScope, name);
1743 if (res != nullptr) {
1744 *isType = false;
1745 return nullptr;
1746 }
1747
1748 res = currentScope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS);
1749 if (res != nullptr) {
1750 *isType = false;
1751 return nullptr;
1752 }
1753
1754 currentScope = currentScope->Parent();
1755 }
1756
1757 // can not find variable
1758 *isType = true;
1759 return nullptr;
1760 }
1761
1762 template <binder::TSBindingType type>
FindTSVariable(const binder::Scope * scope,const util::StringView & name) const1763 binder::Variable *Transformer::FindTSVariable(const binder::Scope *scope, const util::StringView &name) const
1764 {
1765 binder::Variable *res = scope->FindLocalTSVariable<type>(name);
1766 if (res == nullptr && scope->IsTSModuleScope()) {
1767 res = scope->AsTSModuleScope()->FindExportTSVariable<type>(name);
1768 }
1769 return res;
1770 }
1771
VisitExportNamedVariable(ir::Statement * decl)1772 std::vector<ir::AstNode *> Transformer::VisitExportNamedVariable(ir::Statement *decl)
1773 {
1774 std::vector<ir::AstNode *> res;
1775 if (decl->IsVariableDeclaration()) {
1776 auto declarators = decl->AsVariableDeclaration()->Declarators();
1777 for (auto *it : declarators) {
1778 if (it->Init()) {
1779 auto *left = std::get<ir::AstNode *>(VisitTSNode(it->Id()))->AsExpression();
1780 auto *right = std::get<ir::AstNode *>(VisitTSNode(it->Init()))->AsExpression();
1781 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right,
1782 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1783 res.push_back(AllocNode<ir::ExpressionStatement>(assignExpr));
1784 }
1785 }
1786 } else if (decl->IsFunctionDeclaration() || decl->IsClassDeclaration()) {
1787 auto newDecl = VisitTSNode(decl);
1788 if (std::holds_alternative<ir::AstNode *>(newDecl)) {
1789 res.push_back(std::get<ir::AstNode *>(newDecl));
1790 } else {
1791 auto statements = std::get<std::vector<ir::AstNode *>>(newDecl);
1792 res.insert(res.end(), statements.begin(), statements.end());
1793 }
1794
1795 auto name = decl->IsFunctionDeclaration() ?
1796 decl->AsFunctionDeclaration()->Function()->Id() :
1797 decl->AsClassDeclaration()->Definition()->Ident();
1798 ASSERT(name != nullptr);
1799 res.push_back(CreateTsModuleAssignment(name->Name()));
1800 }
1801 return res;
1802 }
1803
CreateMemberExpressionFromQualified(ir::Expression * node)1804 ir::Expression *Transformer::CreateMemberExpressionFromQualified(ir::Expression *node)
1805 {
1806 if (node->IsTSQualifiedName()) {
1807 auto *tsQualifiedName = node->AsTSQualifiedName();
1808 auto *left = CreateMemberExpressionFromQualified(tsQualifiedName->Left());
1809 auto *right = AllocNode<ir::Identifier>(tsQualifiedName->Right()->Name());
1810 return AllocNode<ir::MemberExpression>(left, right,
1811 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1812 }
1813 ASSERT(node->IsIdentifier());
1814 auto *id = CreateReferenceIdentifier(node->AsIdentifier()->Name());
1815 return id;
1816 }
1817
SetOriginalNode(ir::UpdateNodes res,ir::AstNode * originalNode) const1818 void Transformer::SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const
1819 {
1820 if (std::holds_alternative<ir::AstNode *>(res)) {
1821 auto *node = std::get<ir::AstNode *>(res);
1822 if (node == nullptr || node == originalNode) {
1823 return;
1824 }
1825 node->SetOriginal(originalNode);
1826 node->SetRange(originalNode->Range());
1827 } else {
1828 auto nodes = std::get<std::vector<ir::AstNode *>>(res);
1829 for (auto *it : nodes) {
1830 it->SetOriginal(originalNode);
1831 it->SetRange(originalNode->Range());
1832 }
1833 }
1834 }
1835
ResetParentScope(ir::UpdateNodes res,binder::Scope * parentScope) const1836 void Transformer::ResetParentScope(ir::UpdateNodes res, binder::Scope *parentScope) const
1837 {
1838 if (std::holds_alternative<ir::AstNode *>(res)) {
1839 auto *node = std::get<ir::AstNode *>(res);
1840 if (node == nullptr) {
1841 return;
1842 }
1843 ResetParentScopeForAstNode(node, parentScope);
1844 } else {
1845 auto nodes = std::get<std::vector<ir::AstNode *>>(res);
1846 for (auto *it : nodes) {
1847 ResetParentScopeForAstNode(it, parentScope);
1848 }
1849 }
1850 }
1851
CreateTsModuleAssignment(util::StringView name)1852 ir::ExpressionStatement *Transformer::CreateTsModuleAssignment(util::StringView name)
1853 {
1854 auto moduleName = GetCurrentTSModuleName();
1855 auto *id = CreateReferenceIdentifier(moduleName);
1856 auto *left = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(name),
1857 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1858 auto *right = CreateReferenceIdentifier(name);
1859 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
1860 return AllocNode<ir::ExpressionStatement>(assignExpr);
1861 }
1862
GetNameFromModuleDeclaration(ir::TSModuleDeclaration * node) const1863 util::StringView Transformer::GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const
1864 {
1865 return node->Name()->AsIdentifier()->Name();
1866 }
1867
CreateVariableDeclarationWithIdentify(util::StringView name,VariableParsingFlags flags,ir::AstNode * node,bool isExport,ir::Expression * init,bool needBinding)1868 ir::VariableDeclaration *Transformer::CreateVariableDeclarationWithIdentify(util::StringView name,
1869 VariableParsingFlags flags,
1870 ir::AstNode *node,
1871 bool isExport,
1872 ir::Expression *init,
1873 bool needBinding)
1874 {
1875 auto *ident = CreateReferenceIdentifier(name);
1876 auto *declarator = AllocNode<ir::VariableDeclarator>(ident, init);
1877 ArenaVector<ir::VariableDeclarator *> declarators(Allocator()->Adapter());
1878 declarators.push_back(declarator);
1879
1880 auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR;
1881 if (flags & VariableParsingFlags::VAR) {
1882 } else if (flags & VariableParsingFlags::LET) {
1883 varKind = ir::VariableDeclaration::VariableDeclarationKind::LET;
1884 } else {
1885 varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST;
1886 }
1887 auto *declaration = AllocNode<ir::VariableDeclaration>(varKind, std::move(declarators), false);
1888
1889 lexer::SourcePosition startPos(0, 0);
1890 if (node != nullptr) {
1891 startPos = node->Start();
1892 }
1893 if (needBinding) {
1894 binder::Decl *decl = nullptr;
1895 binder::DeclarationFlags declflag = isExport ?
1896 binder::DeclarationFlags::EXPORT :
1897 binder::DeclarationFlags::NONE;
1898 if (flags & VariableParsingFlags::VAR) {
1899 decl = Binder()->AddDecl<binder::VarDecl>(startPos, declflag, false, name);
1900 } else if (flags & VariableParsingFlags::LET) {
1901 decl = Binder()->AddDecl<binder::LetDecl>(startPos, declflag, false, name);
1902 } else {
1903 decl = Binder()->AddDecl<binder::ConstDecl>(startPos, declflag, false, name);
1904 }
1905 decl->BindNode(declaration);
1906 }
1907
1908 return declaration;
1909 }
1910
GetParamName(ir::AstNode * node,util::StringView name) const1911 util::StringView Transformer::GetParamName(ir::AstNode *node, util::StringView name) const
1912 {
1913 if (node->IsTSModuleDeclaration()) {
1914 auto scope = node->AsTSModuleDeclaration()->Scope();
1915 if (scope && !scope->HasVariableName(name)) {
1916 return name;
1917 }
1918 }
1919 if (node->IsTSEnumDeclaration()) {
1920 auto scope = node->AsTSEnumDeclaration()->Scope();
1921 if (scope && !scope->HasDeclarationName(name)) {
1922 return name;
1923 }
1924 }
1925
1926 auto uniqueName = CreateUniqueName(std::string(name) + std::string(INDEX_DIVISION));
1927 return uniqueName;
1928 }
1929
CreateCallExpressionForTsModule(ir::TSModuleDeclaration * node,util::StringView name,bool isExport)1930 ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node,
1931 util::StringView name,
1932 bool isExport)
1933 {
1934 ir::ScriptFunction *funcNode = nullptr;
1935
1936 binder::FunctionScope *funcScope = node->Scope();
1937 binder::FunctionParamScope *funcParamScope = funcScope->ParamScope();
1938 auto paramName = GetParamName(node, name);
1939 {
1940 auto paramScopeCtx = binder::LexicalScope<binder::FunctionParamScope>::Enter(Binder(), funcParamScope);
1941
1942 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1943 auto *parameter = CreateReferenceIdentifier(paramName);
1944 Binder()->AddParamDecl(parameter);
1945 params.push_back(parameter);
1946
1947 ir::BlockStatement *blockNode = nullptr;
1948 {
1949 auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), funcScope);
1950 tsModuleList_.push_back({paramName, funcScope});
1951 if (node->Body()->IsTSModuleDeclaration()) {
1952 auto *tsModule = node->Body()->AsTSModuleDeclaration();
1953 auto body = std::get<std::vector<ir::AstNode *>>(VisitTsModuleDeclaration(tsModule, true));
1954 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
1955 for (auto *it : body) {
1956 statements.push_back(static_cast<ir::Statement *>(it));
1957 }
1958 blockNode = AllocNode<ir::BlockStatement>(funcScope, std::move(statements));
1959 } else {
1960 auto body = VisitTSNodes(node->Body());
1961 blockNode = AllocNode<ir::BlockStatement>(funcScope,
1962 std::move(body->AsTSModuleBlock()->Statements()));
1963 }
1964 tsModuleList_.pop_back();
1965 funcScope->AddBindsFromParam();
1966 }
1967
1968 funcNode = AllocNode<ir::ScriptFunction>(funcScope, std::move(params), nullptr, blockNode, nullptr,
1969 ir::ScriptFunctionFlags::NONE, false, Extension() == ScriptExtension::TS);
1970
1971 funcScope->BindNode(funcNode);
1972 funcParamScope->BindNode(funcNode);
1973 }
1974
1975 auto *funcExpr = AllocNode<ir::FunctionExpression>(funcNode);
1976
1977 ArenaVector<ir::Expression *> arguments = CreateCallExpressionArguments(name, isExport);
1978 auto *callExpr = AllocNode<ir::CallExpression>(funcExpr, std::move(arguments), nullptr, false);
1979
1980 return callExpr;
1981 }
1982
CreateTsModuleParam(util::StringView paramName,bool isExport)1983 ir::Expression *Transformer::CreateTsModuleParam(util::StringView paramName, bool isExport)
1984 {
1985 if (isExport) {
1986 auto moduleName = GetCurrentTSModuleName();
1987 auto *id = CreateReferenceIdentifier(moduleName);
1988 return AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(paramName),
1989 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1990 }
1991
1992 auto *id = CreateReferenceIdentifier(paramName);
1993 return id;
1994 }
1995
AddExportLocalEntryItem(util::StringView name,const ir::Identifier * identifier)1996 void Transformer::AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier)
1997 {
1998 auto moduleRecord = GetSourceTextModuleRecord();
1999 auto *entry = moduleRecord->NewEntry<SourceTextModuleRecord::ExportEntry>(name, name, identifier, identifier);
2000 [[maybe_unused]] bool res = moduleRecord->AddLocalExportEntry(entry);
2001 ASSERT(res);
2002 }
2003
VisitTsModuleDeclaration(ir::TSModuleDeclaration * node,bool isExport)2004 ir::UpdateNodes Transformer::VisitTsModuleDeclaration(ir::TSModuleDeclaration *node, bool isExport)
2005 {
2006 std::vector<ir::AstNode *> res;
2007
2008 util::StringView name = GetNameFromModuleDeclaration(node);
2009
2010 auto findRes = Scope()->FindLocal(name, binder::ResolveBindingOptions::BINDINGS);
2011 if (findRes == nullptr) {
2012 res.push_back(CreateVariableDeclarationForTSEnumOrTSModule(name, node, isExport));
2013 }
2014
2015 auto *callExpr = CreateCallExpressionForTsModule(node, name, isExport && IsTsModule());
2016 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr);
2017 res.push_back(exprStatementNode);
2018
2019 return res;
2020 }
2021
CreateReferenceIdentifier(util::StringView name)2022 ir::Identifier *Transformer::CreateReferenceIdentifier(util::StringView name)
2023 {
2024 auto *node = AllocNode<ir::Identifier>(name);
2025 node->AsIdentifier()->SetReference();
2026 return node;
2027 }
2028
VisitTsEnumDeclaration(ir::TSEnumDeclaration * node,bool isExport)2029 ir::UpdateNodes Transformer::VisitTsEnumDeclaration(ir::TSEnumDeclaration *node, bool isExport)
2030 {
2031 std::vector<ir::AstNode *> res;
2032
2033 util::StringView name = GetNameFromTsEnumDeclaration(node);
2034
2035 auto findRes = Scope()->FindLocal(name); // Find if the variable with the same name is already defined
2036 if (findRes == nullptr) {
2037 res.push_back(CreateVariableDeclarationForTSEnumOrTSModule(name, node, isExport));
2038 }
2039
2040 auto *callExpr = CreateCallExpressionForTsEnum(node, name, isExport && IsTsModule());
2041 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr);
2042 res.push_back(exprStatementNode);
2043
2044 return res;
2045 }
2046
CreateVariableDeclarationForTSEnumOrTSModule(util::StringView name,ir::AstNode * node,bool isExport)2047 ir::AstNode *Transformer::CreateVariableDeclarationForTSEnumOrTSModule(util::StringView name,
2048 ir::AstNode *node, bool isExport)
2049 {
2050 auto flag = Scope()->Parent() == nullptr ? VariableParsingFlags::VAR : VariableParsingFlags::LET;
2051 auto *variableDeclaration = CreateVariableDeclarationWithIdentify(name, flag, node, isExport);
2052 bool doExport = isExport && !IsTsModule();
2053 if (doExport) { // export var
2054 ArenaVector<ir::ExportSpecifier *> specifiers(Allocator()->Adapter());
2055 auto *exportDeclaration = AllocNode<ir::ExportNamedDeclaration>(variableDeclaration, std::move(specifiers));
2056 auto *ident = node->IsTSEnumDeclaration() ?
2057 node->AsTSEnumDeclaration()->Key()->AsIdentifier() : node->AsTSModuleDeclaration()->Name()->AsIdentifier();
2058 AddExportLocalEntryItem(name, ident);
2059 return exportDeclaration;
2060 }
2061 return variableDeclaration;
2062 }
2063
GetNameFromTsEnumDeclaration(const ir::TSEnumDeclaration * node) const2064 util::StringView Transformer::GetNameFromTsEnumDeclaration(const ir::TSEnumDeclaration *node) const
2065 {
2066 auto *name = node->AsTSEnumDeclaration()->Key();
2067 return name->AsIdentifier()->Name();
2068 }
2069
CreateCallExpressionForTsEnum(ir::TSEnumDeclaration * node,util::StringView name,bool isExport)2070 ir::CallExpression *Transformer::CreateCallExpressionForTsEnum(ir::TSEnumDeclaration *node, util::StringView name,
2071 bool isExport)
2072 {
2073 ir::ScriptFunction *funcNode = nullptr;
2074
2075 binder::FunctionScope *funcScope = node->Scope();
2076 binder::FunctionParamScope *funcParamScope = funcScope->ParamScope();
2077 util::StringView paramName = GetParamName(node, name); // modify the name of the function param
2078 {
2079 auto paramScopeCtx = binder::LexicalScope<binder::FunctionParamScope>::Enter(Binder(), funcParamScope);
2080 // create function param
2081 ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2082 auto *parameter = CreateReferenceIdentifier(paramName);
2083 Binder()->AddParamDecl(parameter);
2084 params.push_back(parameter);
2085 // create function body
2086 ir::BlockStatement *blockNode = nullptr;
2087 {
2088 auto scopeCtx = binder::LexicalScope<binder::FunctionScope>::Enter(Binder(), funcScope);
2089 tsEnumList_.push_back({paramName, funcScope});
2090
2091 ArenaVector<ir::TSEnumMember *> members = node->Members();
2092 ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2093 ir::TSEnumMember *preTsEnumMember = nullptr;
2094 for (auto member : members) {
2095 auto *currTsEnumMember = member->AsTSEnumMember();
2096 auto statement = CreateTsEnumMember(currTsEnumMember, preTsEnumMember, paramName);
2097 preTsEnumMember = currTsEnumMember;
2098 statements.push_back(statement);
2099 }
2100
2101 blockNode = AllocNode<ir::BlockStatement>(funcScope, std::move(statements));
2102 tsEnumList_.pop_back();
2103 funcScope->AddBindsFromParam();
2104 }
2105 funcNode = AllocNode<ir::ScriptFunction>(funcScope, std::move(params), nullptr, blockNode, nullptr,
2106 ir::ScriptFunctionFlags::NONE, false, Extension() == ScriptExtension::TS);
2107
2108 funcScope->BindNode(funcNode);
2109 funcParamScope->BindNode(funcNode);
2110 }
2111 auto *funcExpr = AllocNode<ir::FunctionExpression>(funcNode);
2112
2113 ArenaVector<ir::Expression *> arguments = CreateCallExpressionArguments(name, isExport);
2114 auto *callExpr = AllocNode<ir::CallExpression>(funcExpr, std::move(arguments), nullptr, false);
2115
2116 return callExpr;
2117 }
2118
CreateCallExpressionArguments(util::StringView name,bool isExport)2119 ArenaVector<ir::Expression *> Transformer::CreateCallExpressionArguments(util::StringView name, bool isExport)
2120 {
2121 ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
2122 ArenaVector<ir::Expression *> properties(Allocator()->Adapter());
2123 auto *objectExpression = AllocNode<ir::ObjectExpression>(ir::AstNodeType::OBJECT_EXPRESSION,
2124 std::move(properties),
2125 false);
2126 auto assignExpr = AllocNode<ir::AssignmentExpression>(CreateTsModuleParam(name, isExport),
2127 objectExpression,
2128 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2129 auto argument = AllocNode<ir::BinaryExpression>(CreateTsModuleParam(name, isExport),
2130 assignExpr,
2131 lexer::TokenType::PUNCTUATOR_LOGICAL_OR);
2132 if (isExport) {
2133 auto *id = CreateReferenceIdentifier(name);
2134 arguments.push_back(AllocNode<ir::AssignmentExpression>(id, argument,
2135 lexer::TokenType::PUNCTUATOR_SUBSTITUTION));
2136 } else {
2137 arguments.push_back(argument);
2138 }
2139
2140 return arguments;
2141 }
2142
CreateTsEnumMember(ir::TSEnumMember * node,ir::TSEnumMember * preNode,util::StringView enumLiteralName)2143 ir::ExpressionStatement *Transformer::CreateTsEnumMember(ir::TSEnumMember *node, ir::TSEnumMember *preNode,
2144 util::StringView enumLiteralName)
2145 {
2146 util::StringView enumMemberName = GetNameFromEnumMember(node);
2147 binder::Variable *enumVar = Scope()->AsTSEnumScope()->FindEnumMemberVariable(enumMemberName);
2148 CHECK_NOT_NULL(enumVar);
2149 if (node->Init() != nullptr) {
2150 bool isStringInit = enumVar->AsEnumVariable()->StringInit();
2151 if (!enumVar->AsEnumVariable()->IsVisited()) {
2152 isStringInit = IsStringInitForEnumMember(node->Init(), Scope());
2153 if (isStringInit) {
2154 enumVar->AsEnumVariable()->SetStringInit();
2155 }
2156 enumVar->AsEnumVariable()->SetVisited();
2157 }
2158 return isStringInit ? CreateTsEnumMemberWithStringInit(node, enumLiteralName, enumMemberName) :
2159 CreateTsEnumMemberWithNumberInit(node, enumLiteralName, enumMemberName);
2160 }
2161
2162 enumVar->AsEnumVariable()->SetVisited();
2163 return CreateTsEnumMemberWithoutInit(node, preNode, enumLiteralName, enumMemberName);
2164 }
2165
CreateTsEnumMemberWithStringInit(ir::TSEnumMember * node,util::StringView enumLiteralName,util::StringView enumMemberName)2166 ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithStringInit(ir::TSEnumMember *node,
2167 util::StringView enumLiteralName,
2168 util::StringView enumMemberName)
2169 {
2170 // transform to the shape like E["a"] = "str";
2171 auto *object = CreateReferenceIdentifier(enumLiteralName);
2172 auto *property = AllocNode<ir::StringLiteral>(enumMemberName);
2173 auto *left = AllocNode<ir::MemberExpression>(object, property,
2174 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
2175 true, false);
2176 auto *right = std::get<ir::AstNode *>(VisitTSNode(node->Init()))->AsExpression();
2177
2178 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2179 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(assignExpr);
2180
2181 return exprStatementNode;
2182 }
2183
CreateTsEnumMemberWithNumberInit(ir::TSEnumMember * node,util::StringView enumLiteralName,util::StringView enumMemberName)2184 ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithNumberInit(ir::TSEnumMember *node,
2185 util::StringView enumLiteralName,
2186 util::StringView enumMemberName)
2187 {
2188 // transform to the shape like E[E["a"] = init] = "a";
2189 auto *innerObject = CreateReferenceIdentifier(enumLiteralName);
2190 auto *innerProperty = AllocNode<ir::StringLiteral>(enumMemberName);
2191 auto *innerLeft = AllocNode<ir::MemberExpression>(innerObject, innerProperty,
2192 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
2193 true, false);
2194 auto *innerRight = std::get<ir::AstNode *>(VisitTSNode(node->Init()))->AsExpression();
2195
2196 auto *object = CreateReferenceIdentifier(enumLiteralName);
2197 auto *property = AllocNode<ir::AssignmentExpression>(innerLeft, innerRight,
2198 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2199 auto *left = AllocNode<ir::MemberExpression>(object, property,
2200 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
2201 true, false);
2202
2203 auto *right = AllocNode<ir::StringLiteral>(enumMemberName);
2204
2205 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2206 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(assignExpr);
2207
2208 return exprStatementNode;
2209 }
2210
CreateTsEnumMemberWithoutInit(ir::TSEnumMember * node,ir::TSEnumMember * preNode,util::StringView enumLiteralName,util::StringView enumMemberName)2211 ir::ExpressionStatement *Transformer::CreateTsEnumMemberWithoutInit(ir::TSEnumMember *node,
2212 ir::TSEnumMember *preNode,
2213 util::StringView enumLiteralName,
2214 util::StringView enumMemberName)
2215 {
2216 // transform to the shape like E[E["a"] = value] = "a";
2217 auto *innerObject = CreateReferenceIdentifier(enumLiteralName);
2218 auto *innerProperty = AllocNode<ir::StringLiteral>(enumMemberName);
2219 auto *innerLeft = AllocNode<ir::MemberExpression>(innerObject, innerProperty,
2220 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
2221 true, false);
2222
2223 ir::AssignmentExpression *property = nullptr;
2224 if (preNode == nullptr) { // first enumMember, value = 0
2225 auto *innerRight = AllocNode<ir::NumberLiteral>(0);
2226 property = AllocNode<ir::AssignmentExpression>(innerLeft, innerRight,
2227 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2228 } else { // not first enumMember, value = E.prenode + 1
2229 auto *innerRightObject = CreateReferenceIdentifier(enumLiteralName);
2230 auto *innerPropertyForMemberExpr = AllocNode<ir::Identifier>(GetNameFromEnumMember(preNode));
2231 auto *innerMemberExpr = AllocNode<ir::MemberExpression>(innerRightObject, innerPropertyForMemberExpr,
2232 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
2233 auto *innerRight = AllocNode<ir::BinaryExpression>(innerMemberExpr, AllocNode<ir::NumberLiteral>(1),
2234 lexer::TokenType::PUNCTUATOR_PLUS);
2235 property = AllocNode<ir::AssignmentExpression>(innerLeft, innerRight,
2236 lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2237 }
2238 auto *object = CreateReferenceIdentifier(enumLiteralName);
2239 auto *left = AllocNode<ir::MemberExpression>(object, property,
2240 ir::MemberExpression::MemberExpressionKind::ELEMENT_ACCESS,
2241 true, false);
2242
2243 auto *right = AllocNode<ir::StringLiteral>(enumMemberName);
2244
2245 auto *assignExpr = AllocNode<ir::AssignmentExpression>(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION);
2246 auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(assignExpr);
2247
2248 return exprStatementNode;
2249 }
2250
IsStringInitForEnumMember(const ir::Expression * expr,binder::Scope * scope) const2251 bool Transformer::IsStringInitForEnumMember(const ir::Expression *expr, binder::Scope *scope) const
2252 {
2253 if (expr == nullptr) {
2254 return false;
2255 }
2256
2257 // The string enumMember is either initialized with a string literal, or with another string enumMember.
2258 switch (expr->Type()) {
2259 case ir::AstNodeType::STRING_LITERAL:
2260 case ir::AstNodeType::TEMPLATE_LITERAL: {
2261 // TemplateLiteral in Enum must be a string literal.
2262 return true;
2263 }
2264 case ir::AstNodeType::IDENTIFIER: {
2265 // Return true if this identifier is a string enumMember of the current Enum.
2266 util::StringView identName = expr->AsIdentifier()->Name();
2267 ASSERT(scope && scope->IsTSEnumScope());
2268 binder::Variable *v = scope->AsTSEnumScope()->FindEnumMemberVariable(identName);
2269 if (v == nullptr) {
2270 return false;
2271 }
2272 if (!v->AsEnumVariable()->IsVisited()) { // visit the quoted item
2273 auto *initExpr = v->AsEnumVariable()->Declaration()->Node()->AsTSEnumMember()->Init();
2274 if (IsStringInitForEnumMember(initExpr, scope)) {
2275 v->AsEnumVariable()->SetStringInit();
2276 }
2277 v->AsEnumVariable()->SetVisited();
2278 }
2279 if (v->AsEnumVariable()->IsVisited() && v->AsEnumVariable()->StringInit()) {
2280 return true;
2281 }
2282
2283 return false;
2284 }
2285 case ir::AstNodeType::MEMBER_EXPRESSION: {
2286 return IsStringForMemberExpression(expr->AsMemberExpression(), scope);
2287 }
2288 case ir::AstNodeType::BINARY_EXPRESSION: {
2289 auto *left = expr->AsBinaryExpression()->Left();
2290 auto *right = expr->AsBinaryExpression()->Right();
2291 if (expr->AsBinaryExpression()->OperatorType() == lexer::TokenType::PUNCTUATOR_PLUS &&
2292 IsStringInitForEnumMember(right, scope) && IsStringInitForEnumMember(left, scope)) {
2293 return true;
2294 }
2295 return false;
2296 }
2297 default:
2298 return false;
2299 }
2300
2301 return false;
2302 }
2303
IsStringForMemberExpression(const ir::MemberExpression * memberExpr,binder::Scope * scope) const2304 bool Transformer::IsStringForMemberExpression(const ir::MemberExpression *memberExpr, binder::Scope *scope) const
2305 {
2306 // Return true only if memberExpression is a string enumMember.
2307 const ir::Expression *expr = memberExpr;
2308 ArenaDeque<const ir::Expression *> members(Allocator()->Adapter());
2309 while (expr->IsMemberExpression()) {
2310 if (expr->AsMemberExpression()->Property()->IsIdentifier() ||
2311 expr->AsMemberExpression()->Property()->IsStringLiteral() ||
2312 expr->AsMemberExpression()->Property()->IsTemplateLiteral()) {
2313 members.push_front(expr->AsMemberExpression()->Property());
2314 expr = expr->AsMemberExpression()->Object();
2315 } else {
2316 return false;
2317 }
2318 }
2319 if (!expr->IsIdentifier()) {
2320 return false;
2321 }
2322 members.push_front(expr->AsIdentifier());
2323
2324 // Find front Ident TSVariables
2325 ArenaVector<binder::Variable *> findRes = FindFrontIdentifierTSVariables(members.front()->AsIdentifier(), scope);
2326 members.pop_front();
2327
2328 for (auto currVar : findRes) {
2329 if (VerifyMemberExpressionDeque(currVar, members)) {
2330 return true;
2331 }
2332 }
2333 return false;
2334 }
2335
FindFrontIdentifierTSVariables(const ir::Identifier * ident,binder::Scope * scope) const2336 ArenaVector<binder::Variable *> Transformer::FindFrontIdentifierTSVariables(const ir::Identifier *ident,
2337 binder::Scope *scope) const
2338 {
2339 util::StringView name = ident->Name();
2340 binder::Variable *v = nullptr;
2341 ArenaVector<binder::Variable *> findRes(Allocator()->Adapter());
2342 while (scope != nullptr) {
2343 // find enumMemberBindings_
2344 if (scope->IsTSEnumScope()) {
2345 v = scope->AsTSEnumScope()->FindEnumMemberVariable(name);
2346 if (v != nullptr) {
2347 break;
2348 }
2349 }
2350
2351 const std::vector<binder::TSBindingType> types = {binder::TSBindingType::NAMESPACE,
2352 binder::TSBindingType::ENUMLITERAL,
2353 binder::TSBindingType::IMPORT_EQUALS};
2354 // find tsBindings_
2355 FindLocalTSVariables(scope, name, types, findRes);
2356 // find exportTSBindings_
2357 if (scope->IsTSModuleScope()) {
2358 FindExportTSVariables(scope, name, types, findRes);
2359 }
2360
2361 if (!findRes.empty()) {
2362 break;
2363 }
2364
2365 // find js variable
2366 v = scope->FindLocal(name);
2367 if (v != nullptr) {
2368 if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) { // v may be converted from ts variable
2369 v = scope->Parent()->FindLocal(name);
2370 if (v == nullptr) {
2371 break;
2372 }
2373 } else {
2374 break;
2375 }
2376 }
2377 if (scope->IsTSModuleScope()) {
2378 v = scope->AsTSModuleScope()->FindExportVariable(name);
2379 if (v != nullptr) {
2380 break;
2381 }
2382 }
2383
2384 if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) {
2385 scope = scope->Parent();
2386 }
2387 scope = scope->Parent();
2388 }
2389
2390 return findRes;
2391 }
2392
IsInstantiatedNamespaceVariable(binder::Variable * var) const2393 bool Transformer::IsInstantiatedNamespaceVariable(binder::Variable *var) const
2394 {
2395 ASSERT(var->IsNamespaceVariable());
2396 auto *decl = var->AsNamespaceVariable()->Declaration();
2397 ASSERT(decl->IsNamespaceDecl());
2398 ArenaVector<ir::TSModuleDeclaration *> nodes = decl->AsNamespaceDecl()->Decls();
2399 for (ir::TSModuleDeclaration *node : nodes) {
2400 if (node->IsInstantiated()) {
2401 return true;
2402 }
2403 }
2404 return false;
2405 }
2406
FindLocalTSVariables(binder::Scope * scope,const util::StringView name,const std::vector<binder::TSBindingType> & types,ArenaVector<binder::Variable * > & findRes) const2407 void Transformer::FindLocalTSVariables(binder::Scope *scope, const util::StringView name,
2408 const std::vector<binder::TSBindingType> &types,
2409 ArenaVector<binder::Variable *> &findRes) const
2410 {
2411 for (binder::TSBindingType type : types) {
2412 binder::Variable *v = nullptr;
2413 switch (type) {
2414 case binder::TSBindingType::NAMESPACE: {
2415 v = scope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
2416 if (v != nullptr && !IsInstantiatedNamespaceVariable(v)) {
2417 v = nullptr;
2418 }
2419 break;
2420 }
2421 case binder::TSBindingType::ENUMLITERAL: {
2422 v = scope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name);
2423 break;
2424 }
2425 case binder::TSBindingType::IMPORT_EQUALS: {
2426 v = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
2427 if (v != nullptr &&
2428 !IsInstantiatedImportEquals(v->AsImportEqualsVariable()->Declaration()->Node()->
2429 Parent()->AsTSImportEqualsDeclaration(), scope)) {
2430 v = nullptr;
2431 }
2432 break;
2433 }
2434 default:
2435 continue;
2436 }
2437 if (v != nullptr) {
2438 findRes.push_back(v);
2439 }
2440 }
2441 }
2442
FindExportTSVariables(binder::Scope * scope,const util::StringView name,const std::vector<binder::TSBindingType> & types,ArenaVector<binder::Variable * > & findRes) const2443 void Transformer::FindExportTSVariables(binder::Scope *scope, const util::StringView name,
2444 const std::vector<binder::TSBindingType> &types,
2445 ArenaVector<binder::Variable *> &findRes) const
2446 {
2447 for (binder::TSBindingType type : types) {
2448 binder::Variable *v = nullptr;
2449 switch (type) {
2450 case binder::TSBindingType::NAMESPACE: {
2451 v = scope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
2452 if (v != nullptr && !IsInstantiatedNamespaceVariable(v)) {
2453 v = nullptr;
2454 }
2455 break;
2456 }
2457 case binder::TSBindingType::ENUMLITERAL: {
2458 v = scope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name);
2459 break;
2460 }
2461 case binder::TSBindingType::IMPORT_EQUALS: {
2462 v = scope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
2463 if (v != nullptr &&
2464 !IsInstantiatedImportEquals(v->AsImportEqualsVariable()->Declaration()->Node()->
2465 Parent()->AsTSImportEqualsDeclaration(), scope)) {
2466 v = nullptr;
2467 }
2468 break;
2469 }
2470 default:
2471 continue;
2472 }
2473 if (v != nullptr) {
2474 findRes.push_back(v);
2475 }
2476 }
2477 }
2478
VerifyMemberExpressionDeque(binder::Variable * currVar,ArenaDeque<const ir::Expression * > members) const2479 bool Transformer::VerifyMemberExpressionDeque(binder::Variable *currVar,
2480 ArenaDeque<const ir::Expression *> members) const
2481 {
2482 ASSERT(!members.empty());
2483 switch (currVar->Flags()) {
2484 case binder::VariableFlags::ENUM_LITERAL: {
2485 // the recursion ends.
2486 util::StringView enumMemberName = GetNameForMemberExpressionItem(members.front());
2487 members.pop_front();
2488 if (!members.empty()) {
2489 return false;
2490 }
2491 binder::Variable *enumMemberVar = currVar->AsEnumLiteralVariable()->FindEnumMemberVariable(enumMemberName);
2492 if (enumMemberVar == nullptr) {
2493 return false;
2494 }
2495 if (!enumMemberVar->AsEnumVariable()->IsVisited()) { // visit the quoted item
2496 auto *scope = enumMemberVar->AsEnumVariable()->Declaration()->
2497 Node()->Parent()->AsTSEnumDeclaration()->Scope();
2498 auto *initExpr = enumMemberVar->AsEnumVariable()->Declaration()->Node()->AsTSEnumMember()->Init();
2499 if (IsStringInitForEnumMember(initExpr, scope)) {
2500 enumMemberVar->AsEnumVariable()->SetStringInit();
2501 }
2502 enumMemberVar->AsEnumVariable()->SetVisited();
2503 }
2504 if (enumMemberVar->AsEnumVariable()->IsVisited() && enumMemberVar->AsEnumVariable()->StringInit()) {
2505 return true;
2506 }
2507
2508 return false;
2509 }
2510 case binder::VariableFlags::NAMESPACE: {
2511 auto *exportTSBindings = currVar->AsNamespaceVariable()->GetExportBindings();
2512 if (exportTSBindings != nullptr) {
2513 ArenaVector<binder::Variable *> findRes(Allocator()->Adapter());
2514 util::StringView name = GetNameForMemberExpressionItem(members.front());
2515 binder::Variable *v = exportTSBindings->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name);
2516 if (v != nullptr && IsInstantiatedNamespaceVariable(v)) {
2517 findRes.push_back(v);
2518 }
2519 v = exportTSBindings->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name);
2520 if (v != nullptr) {
2521 findRes.push_back(v);
2522 }
2523 v = exportTSBindings->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
2524 if (v != nullptr) {
2525 findRes.push_back(v);
2526 }
2527 members.pop_front();
2528
2529 for (auto itemVar : findRes) {
2530 if (VerifyMemberExpressionDeque(itemVar, members)) {
2531 return true;
2532 }
2533 }
2534 return false;
2535 }
2536 return false;
2537 }
2538 case binder::VariableFlags::IMPORT_EQUALS: {
2539 // Replace import_equal
2540 auto *node = currVar->Declaration()->Node()->Parent()->AsTSImportEqualsDeclaration()->ModuleReference();
2541 while (node->IsTSQualifiedName()) {
2542 members.push_front(node->AsTSQualifiedName()->Right()->AsIdentifier());
2543 node = node->AsTSQualifiedName()->Left();
2544 }
2545 members.push_front(node->AsIdentifier());
2546
2547 ArenaVector<binder::Variable *> findRes = FindFrontIdentifierTSVariables(
2548 members.front()->AsIdentifier(), currVar->AsImportEqualsVariable()->GetScope());
2549 members.pop_front();
2550
2551 for (auto itemVar : findRes) {
2552 if (VerifyMemberExpressionDeque(itemVar, members)) {
2553 return true;
2554 }
2555 }
2556 return false;
2557 }
2558 default:
2559 return false;
2560 }
2561
2562 return false;
2563 }
2564
GetNameForMemberExpressionItem(const ir::Expression * node) const2565 util::StringView Transformer::GetNameForMemberExpressionItem(const ir::Expression *node) const
2566 {
2567 util::StringView name {};
2568 if (node->IsIdentifier()) {
2569 name = node->AsIdentifier()->Name();
2570 } else if (node->IsStringLiteral()) {
2571 name = node->AsStringLiteral()->Str();
2572 } else if (node->IsTemplateLiteral()) {
2573 name = node->AsTemplateLiteral()->Quasis().front()->Raw();
2574 }
2575 return name;
2576 }
2577
GetNameFromEnumMember(const ir::TSEnumMember * node) const2578 util::StringView Transformer::GetNameFromEnumMember(const ir::TSEnumMember *node) const
2579 {
2580 util::StringView name {};
2581 if (node->Key()->IsIdentifier()) {
2582 name = node->Key()->AsIdentifier()->Name();
2583 } else if (node->Key()->IsStringLiteral()) {
2584 name = node->Key()->AsStringLiteral()->Str();
2585 } else if (node->Key()->IsTemplateLiteral()) {
2586 // Because enum does not support Tagged template literal, Quasis can only have one element
2587 name = node->Key()->AsTemplateLiteral()->Quasis().front()->Cooked();
2588 }
2589 return name;
2590 }
2591
FindEnumMemberScope(const util::StringView name) const2592 binder::Scope *Transformer::FindEnumMemberScope(const util::StringView name) const
2593 {
2594 // Transform is required only if ident is an enumMember.
2595 auto scope = Scope();
2596 while (scope != nullptr) {
2597 if (scope->InLocalTSBindings(name)) {
2598 return nullptr;
2599 }
2600 if (scope->IsTSModuleScope() && scope->AsTSModuleScope()->InExportBindings(name)) {
2601 return nullptr;
2602 }
2603 if (scope->IsTSEnumScope() && scope->AsTSEnumScope()->FindEnumMemberVariable(name)) {
2604 return scope;
2605 }
2606 if (scope->FindLocal(name)) {
2607 return nullptr;
2608 }
2609
2610 if (scope->IsTSModuleScope() || scope->IsTSEnumScope()) {
2611 scope = scope->Parent();
2612 }
2613 scope = scope->Parent();
2614 }
2615
2616 return nullptr;
2617 }
2618
CreateMemberExpressionFromIdentifier(binder::Scope * scope,ir::Identifier * node)2619 ir::MemberExpression *Transformer::CreateMemberExpressionFromIdentifier(binder::Scope *scope, ir::Identifier *node)
2620 {
2621 auto identName = node->Name();
2622 auto moduleName = scope->IsTSEnumScope() ? FindTSEnumNameByScope(scope) : FindTSModuleNameByScope(scope);
2623 auto *id = CreateReferenceIdentifier(moduleName);
2624 auto *res = AllocNode<ir::MemberExpression>(id, AllocNode<ir::Identifier>(identName),
2625 ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS,
2626 false, false);
2627 SetOriginalNode(res, node);
2628 return res;
2629 }
2630
CheckTransformedAstStructure(const Program * program) const2631 void Transformer::CheckTransformedAstStructure(const Program *program) const
2632 {
2633 bool passed = true;
2634 CheckTransformedAstNodes(program->Ast(), &passed);
2635 if (passed) {
2636 std::cout << "Transformed AST structure check passed." << std::endl;
2637 }
2638 }
2639
CheckTransformedAstNodes(const ir::AstNode * parent,bool * passed) const2640 void Transformer::CheckTransformedAstNodes(const ir::AstNode *parent, bool *passed) const
2641 {
2642 parent->Iterate([this, parent, passed](auto *childNode) { CheckTransformedAstNode(parent, childNode, passed); });
2643 }
2644
CheckTransformedAstNode(const ir::AstNode * parent,ir::AstNode * childNode,bool * passed) const2645 void Transformer::CheckTransformedAstNode(const ir::AstNode *parent, ir::AstNode *childNode, bool *passed) const
2646 {
2647 if (!(*passed)) {
2648 return;
2649 }
2650 if (childNode->IsClassProperty() &&
2651 (childNode->AsClassProperty()->IsStatic() || childNode->AsClassProperty()->Value() != nullptr)) {
2652 return;
2653 }
2654 if (childNode->IsMethodDefinition() &&
2655 childNode->AsMethodDefinition()->Kind() == ir::MethodDefinitionKind::CONSTRUCTOR) {
2656 return;
2657 }
2658 if (childNode->IsDecorator()) {
2659 return;
2660 }
2661 if (childNode->Parent() != parent) {
2662 std::cout << "Illegal ast structure after transform." << std::endl;
2663 *passed = false;
2664 return;
2665 }
2666 CheckTransformedAstNodes(childNode, passed);
2667 }
2668
ResetParentScopeForAstNodes(const ir::AstNode * parent,binder::Scope * parentScope) const2669 void Transformer::ResetParentScopeForAstNodes(const ir::AstNode *parent, binder::Scope *parentScope) const
2670 {
2671 parent->Iterate([this, parentScope](auto *childNode) { ResetParentScopeForAstNode(childNode, parentScope); });
2672 }
2673
ResetParentScopeForAstNode(ir::AstNode * childNode,binder::Scope * parentScope) const2674 void Transformer::ResetParentScopeForAstNode(ir::AstNode *childNode, binder::Scope *parentScope) const
2675 {
2676 switch (childNode->Type()) {
2677 case ir::AstNodeType::SCRIPT_FUNCTION: {
2678 auto scope = childNode->AsScriptFunction()->Scope();
2679 ASSERT(scope != nullptr);
2680 scope->SetParent(parentScope);
2681 break;
2682 }
2683 case ir::AstNodeType::CATCH_CLAUSE: {
2684 auto scope = childNode->AsCatchClause()->Scope();
2685 ASSERT(scope != nullptr);
2686 scope->SetParent(parentScope);
2687 break;
2688 }
2689 case ir::AstNodeType::CLASS_DEFINITION: {
2690 auto scope = childNode->AsClassDefinition()->Scope();
2691 ASSERT(scope != nullptr);
2692 scope->SetParent(parentScope);
2693 break;
2694 }
2695 case ir::AstNodeType::BLOCK_STATEMENT: {
2696 auto scope = childNode->AsBlockStatement()->Scope();
2697 ASSERT(scope != nullptr);
2698 scope->SetParent(parentScope);
2699 break;
2700 }
2701 case ir::AstNodeType::DO_WHILE_STATEMENT: {
2702 auto scope = childNode->AsDoWhileStatement()->Scope();
2703 ASSERT(scope != nullptr);
2704 scope->SetParent(parentScope);
2705 break;
2706 }
2707 case ir::AstNodeType::WHILE_STATEMENT: {
2708 auto scope = childNode->AsWhileStatement()->Scope();
2709 ASSERT(scope != nullptr);
2710 scope->SetParent(parentScope);
2711 break;
2712 }
2713 case ir::AstNodeType::FOR_IN_STATEMENT: {
2714 auto scope = childNode->AsForInStatement()->Scope();
2715 ASSERT(scope != nullptr);
2716 scope->SetParent(parentScope);
2717 break;
2718 }
2719 case ir::AstNodeType::FOR_OF_STATEMENT: {
2720 auto scope = childNode->AsForOfStatement()->Scope();
2721 ASSERT(scope != nullptr);
2722 scope->SetParent(parentScope);
2723 break;
2724 }
2725 case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
2726 auto scope = childNode->AsForUpdateStatement()->Scope();
2727 ASSERT(scope != nullptr);
2728 scope->SetParent(parentScope);
2729 break;
2730 }
2731 case ir::AstNodeType::SWITCH_STATEMENT: {
2732 auto scope = childNode->AsSwitchStatement()->Scope();
2733 ASSERT(scope != nullptr);
2734 scope->SetParent(parentScope);
2735 break;
2736 }
2737 case ir::AstNodeType::TS_ENUM_DECLARATION: {
2738 auto scope = childNode->AsTSEnumDeclaration()->Scope();
2739 ASSERT(scope != nullptr);
2740 scope->SetParent(parentScope);
2741 break;
2742 }
2743 case ir::AstNodeType::TS_INTERFACE_DECLARATION: {
2744 auto scope = childNode->AsTSInterfaceDeclaration()->Scope();
2745 ASSERT(scope != nullptr);
2746 scope->SetParent(parentScope);
2747 break;
2748 }
2749 case ir::AstNodeType::TS_METHOD_SIGNATURE: {
2750 auto scope = childNode->AsTSMethodSignature()->Scope();
2751 ASSERT(scope != nullptr);
2752 scope->SetParent(parentScope);
2753 break;
2754 }
2755 case ir::AstNodeType::TS_MODULE_DECLARATION: {
2756 auto scope = childNode->AsTSModuleDeclaration()->Scope();
2757 ASSERT(scope != nullptr);
2758 scope->SetParent(parentScope);
2759 break;
2760 }
2761 case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
2762 auto scope = childNode->AsTSSignatureDeclaration()->Scope();
2763 ASSERT(scope != nullptr);
2764 scope->SetParent(parentScope);
2765 break;
2766 }
2767 case ir::AstNodeType::TS_TYPE_PARAMETER_DECLARATION: {
2768 auto scope = childNode->AsTSTypeParameterDeclaration()->Scope();
2769 ASSERT(scope != nullptr);
2770 scope->SetParent(parentScope);
2771 break;
2772 }
2773 case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: {
2774 auto scope = childNode->AsTSConstructorType()->Scope();
2775 ASSERT(scope != nullptr);
2776 scope->SetParent(parentScope);
2777 break;
2778 }
2779 case ir::AstNodeType::TS_FUNCTION_TYPE: {
2780 auto scope = childNode->AsTSFunctionType()->Scope();
2781 ASSERT(scope != nullptr);
2782 scope->SetParent(parentScope);
2783 break;
2784 }
2785 default: {
2786 ResetParentScopeForAstNodes(childNode, parentScope);
2787 break;
2788 }
2789 }
2790 }
2791
IsValueReference(ir::Identifier * node)2792 bool Transformer::IsValueReference(ir::Identifier *node)
2793 {
2794 auto scope = Scope();
2795 ASSERT(scope != nullptr);
2796 auto name = node->Name();
2797 // If it's js value or enum, it won't be a type.
2798 // Const enum was processed as enum in es2abc, so we don't process it as type here.
2799 if (scope->FindLocal(name, binder::ResolveBindingOptions::BINDINGS) != nullptr ||
2800 scope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name) != nullptr) {
2801 return true;
2802 }
2803
2804 binder::Variable *var = nullptr;
2805
2806 var = scope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name);
2807 if (var != nullptr) {
2808 auto *decl = var->Declaration()->AsNamespaceDecl();
2809 return decl->IsInstantiated();
2810 }
2811
2812 var = scope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name);
2813 if (var != nullptr) {
2814 auto *node = var->Declaration()->Node()->AsTSImportEqualsDeclaration();
2815 return IsInstantiatedImportEquals(node, scope);
2816 }
2817
2818 return false;
2819 }
2820
RemoveDefaultLocalExportEntry()2821 void Transformer::RemoveDefaultLocalExportEntry()
2822 {
2823 auto *moduleRecord = GetSourceTextModuleRecord();
2824 moduleRecord->RemoveDefaultLocalExportEntry();
2825 }
2826
2827 } // namespace panda::es2panda::parser
2828