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