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