• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 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 "binder.h"
17 
18 #include <util/helpers.h>
19 #include <binder/scope.h>
20 #include <binder/tsBinding.h>
21 #include <es2panda.h>
22 #include <ir/astNode.h>
23 #include <ir/base/catchClause.h>
24 #include <ir/base/classDefinition.h>
25 #include <ir/base/methodDefinition.h>
26 #include <ir/base/property.h>
27 #include <ir/base/scriptFunction.h>
28 #include <ir/base/spreadElement.h>
29 #include <ir/expressions/arrayExpression.h>
30 #include <ir/expressions/assignmentExpression.h>
31 #include <ir/expressions/identifier.h>
32 #include <ir/expressions/objectExpression.h>
33 #include <ir/module/exportNamedDeclaration.h>
34 #include <ir/module/exportSpecifier.h>
35 #include <ir/statements/blockStatement.h>
36 #include <ir/statements/doWhileStatement.h>
37 #include <ir/statements/forInStatement.h>
38 #include <ir/statements/forOfStatement.h>
39 #include <ir/statements/forUpdateStatement.h>
40 #include <ir/statements/ifStatement.h>
41 #include <ir/statements/switchCaseStatement.h>
42 #include <ir/statements/switchStatement.h>
43 #include <ir/statements/variableDeclaration.h>
44 #include <ir/statements/variableDeclarator.h>
45 #include <ir/statements/whileStatement.h>
46 #include <ir/ts/tsConstructorType.h>
47 #include <ir/ts/tsFunctionType.h>
48 #include <ir/ts/tsMethodSignature.h>
49 #include <ir/ts/tsModuleBlock.h>
50 #include <ir/ts/tsModuleDeclaration.h>
51 #include <ir/ts/tsSignatureDeclaration.h>
52 #include <util/concurrent.h>
53 #include <util/helpers.h>
54 
55 namespace panda::es2panda::binder {
InitTopScope()56 void Binder::InitTopScope()
57 {
58     if (program_->Kind() == parser::ScriptKind::MODULE) {
59         topScope_ = Allocator()->New<ModuleScope>(Allocator());
60     } else {
61         topScope_ = Allocator()->New<GlobalScope>(Allocator());
62     }
63 
64     scope_ = topScope_;
65 }
66 
AddParamDecl(const ir::AstNode * param)67 ParameterDecl *Binder::AddParamDecl(const ir::AstNode *param)
68 {
69     ASSERT(scope_->IsFunctionParamScope() || scope_->IsCatchParamScope());
70     auto [decl, node] = static_cast<ParamScope *>(scope_)->AddParamDecl(Allocator(), param);
71 
72     if (!node) {
73         return decl;
74     }
75 
76     ThrowRedeclaration(node->Start(), decl->Name());
77 }
78 
ThrowRedeclaration(const lexer::SourcePosition & pos,const util::StringView & name)79 void Binder::ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name)
80 {
81     lexer::LineIndex index(program_->SourceCode());
82     lexer::SourceLocation loc = index.GetLocation(pos);
83 
84     std::stringstream ss;
85     ss << "Variable '" << name << "' has already been declared.";
86     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
87 }
88 
ThrowUndeclaredExport(const lexer::SourcePosition & pos,const util::StringView & name)89 void Binder::ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util::StringView &name)
90 {
91     lexer::LineIndex index(program_->SourceCode());
92     lexer::SourceLocation loc = index.GetLocation(pos);
93 
94     std::stringstream ss;
95     ss << "Export name '" << name << "' is not defined.";
96     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
97 }
98 
ThrowInvalidDstrTarget(const lexer::SourcePosition & pos,const util::StringView & name)99 void Binder::ThrowInvalidDstrTarget(const lexer::SourcePosition &pos, const util::StringView &name)
100 {
101     lexer::LineIndex index(program_->SourceCode());
102     lexer::SourceLocation loc = index.GetLocation(pos);
103 
104     std::stringstream ss;
105     ss << "Invalid destructuring assignment target: " << name;
106     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
107 }
108 
CheckMandatoryArguments(const ir::Identifier * ident)109 void Binder::CheckMandatoryArguments(const ir::Identifier *ident)
110 {
111     const auto *iter = static_cast<const ir::AstNode *>(ident);
112     bool isPatternMember = false;
113     while (iter) {
114         if (iter->IsArrayExpression() || iter->IsArrayPattern()) {
115             isPatternMember = true;
116             break;
117         }
118 
119         if (iter->IsObjectExpression() || iter->IsObjectPattern()) {
120             isPatternMember = util::Helpers::IsObjectPropertyValue(iter->AsObjectExpression(), ident);
121             break;
122         }
123         iter = iter->Parent();
124     }
125 
126     if (!isPatternMember) {
127         return;
128     }
129 
130     auto *patternNode = iter;
131 
132     while (iter) {
133         if (iter->IsAssignmentExpression() || iter->IsVariableDeclarator() || iter->IsForInStatement() ||
134             iter->IsForOfStatement()) {
135             break;
136         }
137 
138         iter = iter->Parent();
139     }
140 
141     if (!iter) {
142         return;
143     }
144 
145     const ir::AstNode *potentialParent = iter;
146 
147     if (iter->IsAssignmentExpression()) {
148         potentialParent = iter->AsAssignmentExpression()->Left();
149     } else if (iter->IsVariableDeclarator()) {
150         potentialParent = iter->AsVariableDeclarator()->Id();
151     } else {
152         potentialParent = iter->IsForInStatement() ? iter->AsForInStatement()->Left() :
153                                                      iter->AsForOfStatement()->Left();
154     }
155 
156     if (!util::Helpers::IsChild(potentialParent, patternNode)) {
157         return;
158     }
159 
160     ThrowInvalidDstrTarget(ident->Start(), ident->Name());
161 }
162 
AssignIndexToModuleVariable()163 void Binder::AssignIndexToModuleVariable()
164 {
165     ASSERT(program_->ModuleRecord());
166     program_->ModuleRecord()->AssignIndexToModuleVariable(topScope_->AsModuleScope());
167 }
168 
IdentifierAnalysis(ResolveBindingFlags flags)169 void Binder::IdentifierAnalysis(ResolveBindingFlags flags)
170 {
171     ASSERT(program_->Ast());
172     ASSERT(scope_ == topScope_);
173 
174     bindingFlags_ = flags;
175     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
176         ResolveReferences(program_->Ast());
177     } else if (bindingFlags_ & ResolveBindingFlags::ALL) {
178         BuildFunction(topScope_, MAIN_FUNC_NAME);
179         ResolveReferences(program_->Ast());
180         AddMandatoryParams();
181         if (topScope_->IsModuleScope()) {
182             AssignIndexToModuleVariable();
183         }
184     }
185 }
186 
ValidateExportDecl(const ir::ExportNamedDeclaration * exportDecl)187 void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl)
188 {
189     if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr) {
190         return;
191     }
192 
193     ASSERT(topScope_->IsModuleScope());
194     for (auto *it : exportDecl->Specifiers()) {
195         auto localName = it->AsExportSpecifier()->Local()->Name();
196         if (topScope_->FindLocal(localName) == nullptr) {
197             ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
198         }
199         topScope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName);
200     }
201 }
202 
LookupReference(const util::StringView & name)203 void Binder::LookupReference(const util::StringView &name)
204 {
205     ScopeFindResult res = scope_->Find(name);
206     if (res.level == 0) {
207         return;
208     }
209 
210     ASSERT(res.variable);
211     res.variable->SetLexical(res.scope, program_->HotfixHelper());
212 }
213 
InstantiateArguments()214 void Binder::InstantiateArguments()
215 {
216     auto *iter = scope_;
217     while (true) {
218         Scope *scope = iter->IsFunctionParamScope() ? iter : iter->EnclosingVariableScope();
219 
220         const auto *node = scope->Node();
221 
222         if (scope->IsLoopScope()) {
223             iter = scope->Parent();
224             continue;
225         }
226 
227         if (!node->IsScriptFunction()) {
228             break;
229         }
230 
231         if (!node->AsScriptFunction()->IsArrow()) {
232             auto *argumentsVariable =
233                 scope->AddDecl<ConstDecl, LocalVariable>(Allocator(), FUNCTION_ARGUMENTS, VariableFlags::INITIALIZED);
234 
235             if (iter->IsFunctionParamScope()) {
236                 if (!argumentsVariable) {
237                     break;
238                 }
239 
240                 scope = iter->AsFunctionParamScope()->GetFunctionScope();
241                 scope->Bindings().insert({argumentsVariable->Name(), argumentsVariable});
242             }
243 
244             scope->AsVariableScope()->AddFlag(VariableScopeFlags::USE_ARGS);
245 
246             break;
247         }
248 
249         iter = scope->Parent();
250     }
251 }
252 
LookupIdentReference(ir::Identifier * ident)253 void Binder::LookupIdentReference(ir::Identifier *ident)
254 {
255     if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
256         InstantiateArguments();
257     }
258 
259     ScopeFindResult res = scope_->Find(ident->Name(), bindingOptions_);
260 
261     if (res.level != 0) {
262         ASSERT(res.variable);
263         util::Concurrent::VerifyImportVarForConcurrentFunction(Program()->GetLineIndex(), ident, res);
264         res.variable->SetLexical(res.scope, program_->HotfixHelper());
265     }
266 
267     if (!res.variable) {
268         return;
269     }
270 
271     auto decl = res.variable->Declaration();
272     if (decl->IsLetOrConstOrClassDecl() && !decl->HasFlag(DeclarationFlags::NAMESPACE_IMPORT) &&
273         !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
274         ident->SetTdz();
275     }
276 
277     ident->SetVariable(res.variable);
278 }
279 
BuildFunction(FunctionScope * funcScope,util::StringView name,const ir::ScriptFunction * func)280 void Binder::BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func)
281 {
282     functionScopes_.push_back(funcScope);
283 
284     bool funcNameWithoutDot = (name.Find(".") == std::string::npos);
285     bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos);
286     if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot && funcNameWithoutBackslash && !functionNames_.count(name)) {
287         auto internalName = std::string(program_->FormatedRecordName()) + std::string(name);
288         functionNames_.insert(name);
289         funcScope->BindName(name, util::UString(internalName, Allocator()).View());
290         return;
291     }
292     std::stringstream ss;
293     ss << std::string(program_->FormatedRecordName());
294     uint32_t idx = functionNameIndex_++;
295     ss << "#" << std::to_string(idx) << "#";
296     if (name == ANONYMOUS_FUNC_NAME && func != nullptr) {
297         anonymousFunctionNames_[func] = util::UString(ss.str(), Allocator()).View();
298     }
299     if (funcNameWithoutDot && funcNameWithoutBackslash) {
300         ss << name;
301     }
302     util::UString internalName(ss.str(), Allocator());
303     funcScope->BindName(name, internalName.View());
304 }
305 
BuildScriptFunction(Scope * outerScope,const ir::ScriptFunction * scriptFunc)306 void Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc)
307 {
308     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
309         return;
310     }
311 
312     if (scriptFunc->IsArrow()) {
313         VariableScope *outerVarScope = outerScope->EnclosingVariableScope();
314         outerVarScope->AddFlag(VariableScopeFlags::INNER_ARROW);
315     }
316 
317     ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope());
318     BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(scriptFunc), scriptFunc);
319 }
320 
BuildVarDeclaratorId(const ir::AstNode * parent,ir::AstNode * childNode)321 void Binder::BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode)
322 {
323     childNode->SetParent(parent);
324 
325     switch (childNode->Type()) {
326         case ir::AstNodeType::IDENTIFIER: {
327             auto *ident = childNode->AsIdentifier();
328             const auto &name = ident->Name();
329             if (name.Is(FUNCTION_ARGUMENTS)) {
330                 CheckMandatoryArguments(ident);
331             }
332 
333             if (util::Helpers::IsGlobalIdentifier(name)) {
334                 break;
335             }
336 
337             auto *variable = scope_->FindLocal(name);
338 
339             if (Program()->Extension() == ScriptExtension::TS) {
340                 ident->SetVariable(variable);
341                 BuildTSSignatureDeclarationBaseParams(ident->TypeAnnotation());
342             }
343 
344             variable->AddFlag(VariableFlags::INITIALIZED);
345             break;
346         }
347         case ir::AstNodeType::OBJECT_PATTERN: {
348             auto *objPattern = childNode->AsObjectPattern();
349 
350             for (auto *prop : objPattern->Properties()) {
351                 BuildVarDeclaratorId(childNode, prop);
352             }
353 
354             BuildTSSignatureDeclarationBaseParams(objPattern->TypeAnnotation());
355             break;
356         }
357         case ir::AstNodeType::ARRAY_PATTERN: {
358             auto *arrayPattern = childNode->AsArrayPattern();
359 
360             for (auto *element : childNode->AsArrayPattern()->Elements()) {
361                 BuildVarDeclaratorId(childNode, element);
362             }
363 
364             BuildTSSignatureDeclarationBaseParams(arrayPattern->TypeAnnotation());
365             break;
366         }
367         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
368             ResolveReference(childNode, childNode->AsAssignmentPattern()->Right());
369             BuildVarDeclaratorId(childNode, childNode->AsAssignmentPattern()->Left());
370             break;
371         }
372         case ir::AstNodeType::PROPERTY: {
373             ResolveReference(childNode, childNode->AsProperty()->Key());
374             BuildVarDeclaratorId(childNode, childNode->AsProperty()->Value());
375             break;
376         }
377         case ir::AstNodeType::REST_ELEMENT: {
378             BuildVarDeclaratorId(childNode, childNode->AsRestElement()->Argument());
379             break;
380         }
381         default:
382             break;
383     }
384 }
385 
BuildTSSignatureDeclarationBaseParams(const ir::AstNode * typeNode)386 void Binder::BuildTSSignatureDeclarationBaseParams(const ir::AstNode *typeNode)
387 {
388     if (!typeNode) {
389         return;
390     }
391 
392     Scope *scope = nullptr;
393 
394     switch (typeNode->Type()) {
395         case ir::AstNodeType::TS_FUNCTION_TYPE: {
396             scope = typeNode->AsTSFunctionType()->Scope();
397             break;
398         }
399         case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: {
400             scope = typeNode->AsTSConstructorType()->Scope();
401             break;
402         }
403         case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
404             scope = typeNode->AsTSSignatureDeclaration()->Scope();
405             break;
406         }
407         case ir::AstNodeType::TS_METHOD_SIGNATURE: {
408             scope = typeNode->AsTSMethodSignature()->Scope();
409             break;
410         }
411         default: {
412             ResolveReferences(typeNode);
413             return;
414         }
415     }
416 
417     ASSERT(scope && scope->IsFunctionParamScope());
418 
419     auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope->AsFunctionParamScope());
420     ResolveReferences(typeNode);
421 }
422 
BuildVarDeclarator(ir::VariableDeclarator * varDecl)423 void Binder::BuildVarDeclarator(ir::VariableDeclarator *varDecl)
424 {
425     if (varDecl->Parent()->AsVariableDeclaration()->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) {
426         ResolveReferences(varDecl);
427         return;
428     }
429 
430     if (varDecl->Init()) {
431         ResolveReference(varDecl, varDecl->Init());
432     }
433 
434     BuildVarDeclaratorId(varDecl, varDecl->Id());
435 }
436 
BuildClassDefinition(ir::ClassDefinition * classDef)437 void Binder::BuildClassDefinition(ir::ClassDefinition *classDef)
438 {
439     if (classDef->Parent()->IsClassDeclaration()) {
440         util::StringView className = classDef->GetName();
441         ASSERT(!className.Empty());
442         ScopeFindResult res = scope_->Find(className);
443 
444         ASSERT(res.variable && res.variable->Declaration()->IsClassDecl());
445         res.variable->AddFlag(VariableFlags::INITIALIZED);
446     }
447 
448     auto scopeCtx = LexicalScope<LocalScope>::Enter(this, classDef->Scope());
449 
450     if (classDef->Super()) {
451         ResolveReference(classDef, classDef->Super());
452     }
453 
454     if (classDef->Ident()) {
455         ScopeFindResult res = scope_->Find(classDef->Ident()->Name());
456 
457         ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
458         res.variable->AddFlag(VariableFlags::INITIALIZED);
459     }
460 
461     ResolveReference(classDef, classDef->Ctor());
462 
463     for (auto *stmt : classDef->Body()) {
464         ResolveReference(classDef, stmt);
465     }
466 }
467 
BuildForUpdateLoop(ir::ForUpdateStatement * forUpdateStmt)468 void Binder::BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt)
469 {
470     auto *loopScope = forUpdateStmt->Scope();
471 
472     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
473 
474     if (forUpdateStmt->Init()) {
475         ResolveReference(forUpdateStmt, forUpdateStmt->Init());
476     }
477 
478     if (forUpdateStmt->Update()) {
479         ResolveReference(forUpdateStmt, forUpdateStmt->Update());
480     }
481 
482     if (forUpdateStmt->Test()) {
483         ResolveReference(forUpdateStmt, forUpdateStmt->Test());
484     }
485 
486     ResolveReference(forUpdateStmt, forUpdateStmt->Body());
487 
488     loopCtx.GetScope()->InitVariable();
489 }
490 
BuildForInOfLoop(const ir::Statement * parent,binder::LoopScope * loopScope,ir::AstNode * left,ir::Expression * right,ir::Statement * body)491 void Binder::BuildForInOfLoop(const ir::Statement *parent, binder::LoopScope *loopScope, ir::AstNode *left,
492                               ir::Expression *right, ir::Statement *body)
493 {
494     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
495 
496     ResolveReference(parent, right);
497     ResolveReference(parent, left);
498 
499     ResolveReference(parent, body);
500     loopCtx.GetScope()->InitVariable();
501 }
502 
BuildCatchClause(ir::CatchClause * catchClauseStmt)503 void Binder::BuildCatchClause(ir::CatchClause *catchClauseStmt)
504 {
505     if (catchClauseStmt->Param()) {
506         auto paramScopeCtx = LexicalScope<CatchParamScope>::Enter(this, catchClauseStmt->Scope()->ParamScope());
507         ResolveReference(catchClauseStmt, catchClauseStmt->Param());
508     }
509 
510     auto scopeCtx = LexicalScope<CatchScope>::Enter(this, catchClauseStmt->Scope());
511     ResolveReference(catchClauseStmt, catchClauseStmt->Body());
512 }
513 
ResolveReference(const ir::AstNode * parent,ir::AstNode * childNode)514 void Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode)
515 {
516     childNode->SetParent(parent);
517 
518     switch (childNode->Type()) {
519         case ir::AstNodeType::IDENTIFIER: {
520             auto *ident = childNode->AsIdentifier();
521 
522             if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
523                 CheckMandatoryArguments(ident);
524             }
525 
526             if (ident->IsReference()) {
527                 LookupIdentReference(ident);
528             }
529 
530             ResolveReferences(childNode);
531             break;
532         }
533         case ir::AstNodeType::SUPER_EXPRESSION: {
534             VariableScope *varScope = scope_->EnclosingVariableScope();
535             varScope->AddFlag(VariableScopeFlags::USE_SUPER);
536 
537             ResolveReferences(childNode);
538             break;
539         }
540         case ir::AstNodeType::SCRIPT_FUNCTION: {
541             auto *scriptFunc = childNode->AsScriptFunction();
542             util::Concurrent::SetConcurrent(const_cast<ir::ScriptFunction *>(scriptFunc), Program()->GetLineIndex());
543             auto *funcScope = scriptFunc->Scope();
544 
545             auto *outerScope = scope_;
546 
547             {
548                 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, funcScope->ParamScope());
549 
550                 for (auto *param : scriptFunc->Params()) {
551                     ResolveReference(scriptFunc, param);
552                 }
553             }
554 
555             if (Program()->Extension() == ScriptExtension::TS) {
556                 if (scriptFunc->ReturnTypeAnnotation()) {
557                     ResolveReference(scriptFunc, scriptFunc->ReturnTypeAnnotation());
558                 }
559 
560                 if (scriptFunc->IsOverload() || scriptFunc->Declare()) {
561                     break;
562                 }
563             }
564 
565             auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
566 
567             BuildScriptFunction(outerScope, scriptFunc);
568 
569             ResolveReference(scriptFunc, scriptFunc->Body());
570             break;
571         }
572         case ir::AstNodeType::VARIABLE_DECLARATOR: {
573             BuildVarDeclarator(childNode->AsVariableDeclarator());
574 
575             break;
576         }
577         case ir::AstNodeType::CLASS_DEFINITION: {
578             BuildClassDefinition(childNode->AsClassDefinition());
579 
580             break;
581         }
582         case ir::AstNodeType::CLASS_PROPERTY: {
583             const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(childNode->AsClassProperty());
584             auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, ctor->Scope());
585 
586             ResolveReferences(childNode);
587             break;
588         }
589         case ir::AstNodeType::BLOCK_STATEMENT: {
590             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsBlockStatement()->Scope());
591 
592             ResolveReferences(childNode);
593             break;
594         }
595         case ir::AstNodeType::SWITCH_STATEMENT: {
596             auto *switchStatement = childNode->AsSwitchStatement();
597             ResolveReference(switchStatement, switchStatement->Discriminant());
598 
599             auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
600             for (auto *it : switchStatement->Cases()) {
601                 ResolveReference(switchStatement, it);
602             }
603             break;
604         }
605         case ir::AstNodeType::DO_WHILE_STATEMENT: {
606             auto *doWhileStatement = childNode->AsDoWhileStatement();
607 
608             {
609                 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
610                 ResolveReference(doWhileStatement, doWhileStatement->Body());
611                 loopScopeCtx.GetScope()->InitVariable();
612             }
613 
614             ResolveReference(doWhileStatement, doWhileStatement->Test());
615             break;
616         }
617         case ir::AstNodeType::WHILE_STATEMENT: {
618             auto *whileStatement = childNode->AsWhileStatement();
619             ResolveReference(whileStatement, whileStatement->Test());
620 
621             auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
622             ResolveReference(whileStatement, whileStatement->Body());
623             loopScopeCtx.GetScope()->InitVariable();
624             break;
625         }
626         case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
627             BuildForUpdateLoop(childNode->AsForUpdateStatement());
628             break;
629         }
630         case ir::AstNodeType::FOR_IN_STATEMENT: {
631             auto *forInStmt = childNode->AsForInStatement();
632             BuildForInOfLoop(forInStmt, forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
633 
634             break;
635         }
636         case ir::AstNodeType::FOR_OF_STATEMENT: {
637             auto *forOfStmt = childNode->AsForOfStatement();
638             BuildForInOfLoop(forOfStmt, forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
639             break;
640         }
641         case ir::AstNodeType::CATCH_CLAUSE: {
642             BuildCatchClause(childNode->AsCatchClause());
643             break;
644         }
645         case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
646             ValidateExportDecl(childNode->AsExportNamedDeclaration());
647 
648             ResolveReferences(childNode);
649             break;
650         }
651         // TypeScript specific part
652         case ir::AstNodeType::TS_FUNCTION_TYPE:
653         case ir::AstNodeType::TS_CONSTRUCTOR_TYPE:
654         case ir::AstNodeType::TS_METHOD_SIGNATURE:
655         case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
656             BuildTSSignatureDeclarationBaseParams(childNode);
657             break;
658         }
659         case ir::AstNodeType::TS_MODULE_DECLARATION: {
660             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSModuleDeclaration()->Scope());
661             ResolveReferences(childNode);
662             break;
663         }
664         default: {
665             ResolveReferences(childNode);
666             break;
667         }
668     }
669 }
ResolveReferences(const ir::AstNode * parent)670 void Binder::ResolveReferences(const ir::AstNode *parent)
671 {
672     parent->Iterate([this, parent](auto *childNode) { ResolveReference(parent, childNode); });
673 }
674 
AddMandatoryParam(const std::string_view & name)675 void Binder::AddMandatoryParam(const std::string_view &name)
676 {
677     ASSERT(scope_->IsFunctionVariableScope());
678 
679     auto *decl = Allocator()->New<ParameterDecl>(name);
680     auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
681 
682     auto &funcParams = scope_->AsFunctionVariableScope()->ParamScope()->Params();
683     funcParams.insert(funcParams.begin(), param);
684     scope_->AsFunctionVariableScope()->ParamScope()->Bindings().insert({decl->Name(), param});
685     scope_->AsFunctionVariableScope()->Bindings().insert({decl->Name(), param});
686 }
687 
AddMandatoryParams()688 void Binder::AddMandatoryParams()
689 {
690     ASSERT(scope_ == topScope_);
691     ASSERT(!functionScopes_.empty());
692     auto iter = functionScopes_.begin();
693     [[maybe_unused]] auto *funcScope = *iter++;
694 
695     ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
696 
697     if (program_->Kind() == parser::ScriptKind::COMMONJS) {
698         AddMandatoryParams(CJS_MAINFUNC_MANDATORY_PARAMS);
699     } else {
700         AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
701     }
702 
703     for (; iter != functionScopes_.end(); iter++) {
704         funcScope = *iter;
705         const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
706 
707         auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
708 
709         if (!scriptFunc->IsArrow()) {
710             AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
711             continue;
712         }
713 
714         const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
715         bool lexicalFunctionObject {};
716 
717         if (ctor && util::Helpers::GetClassDefiniton(ctor)->Super() &&
718             funcScope->HasFlag(VariableScopeFlags::USE_SUPER)) {
719             ASSERT(ctor->Scope()->HasFlag(VariableScopeFlags::INNER_ARROW));
720             ctor->Scope()->AddFlag(VariableScopeFlags::SET_LEXICAL_FUNCTION);
721             lexicalFunctionObject = true;
722             AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
723         } else {
724             AddMandatoryParams(ARROW_MANDATORY_PARAMS);
725         }
726 
727         LookupReference(MANDATORY_PARAM_NEW_TARGET);
728         LookupReference(MANDATORY_PARAM_THIS);
729 
730         if (funcScope->HasFlag(VariableScopeFlags::USE_ARGS)) {
731             LookupReference(FUNCTION_ARGUMENTS);
732         }
733 
734         if (lexicalFunctionObject) {
735             LookupReference(MANDATORY_PARAM_FUNC);
736         }
737     }
738 }
739 
AddDeclarationName(const util::StringView & name)740 void Binder::AddDeclarationName(const util::StringView &name)
741 {
742     if (extension_ != ScriptExtension::TS) {
743         return;
744     }
745     variableNames_.insert(name);
746     auto *scope = GetScope();
747     while (scope != nullptr) {
748         if (scope->IsTSModuleScope()) {
749             scope->AsTSModuleScope()->AddDeclarationName(name);
750         }
751         scope = scope->Parent();
752     }
753 }
754 
HasVariableName(const util::StringView & name) const755 bool Binder::HasVariableName(const util::StringView &name) const
756 {
757     return variableNames_.find(name) != variableNames_.end();
758 }
759 
760 }  // namespace panda::es2panda::binder
761