• 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 "varbinder.h"
17 
18 #include "varbinder/privateBinding.h"
19 #include "parser/program/program.h"
20 #include "util/helpers.h"
21 #include "varbinder/scope.h"
22 #include "varbinder/tsBinding.h"
23 #include "compiler/core/compilerContext.h"
24 #include "es2panda.h"
25 #include "ir/astNode.h"
26 #include "ir/base/catchClause.h"
27 #include "ir/base/classDefinition.h"
28 #include "ir/base/classProperty.h"
29 #include "ir/base/classStaticBlock.h"
30 #include "ir/base/methodDefinition.h"
31 #include "ir/base/property.h"
32 #include "ir/base/scriptFunction.h"
33 #include "ir/base/spreadElement.h"
34 #include "ir/expressions/arrayExpression.h"
35 #include "ir/expressions/assignmentExpression.h"
36 #include "ir/expressions/memberExpression.h"
37 #include "ir/expressions/identifier.h"
38 #include "ir/expressions/objectExpression.h"
39 #include "ir/statements/blockStatement.h"
40 #include "ir/statements/doWhileStatement.h"
41 #include "ir/statements/forInStatement.h"
42 #include "ir/statements/forOfStatement.h"
43 #include "ir/statements/forUpdateStatement.h"
44 #include "ir/statements/ifStatement.h"
45 #include "ir/statements/switchStatement.h"
46 #include "ir/statements/variableDeclaration.h"
47 #include "ir/statements/variableDeclarator.h"
48 #include "ir/statements/whileStatement.h"
49 #include "ir/module/exportNamedDeclaration.h"
50 #include "ir/module/importDeclaration.h"
51 #include "ir/ts/tsFunctionType.h"
52 #include "ir/ts/tsConstructorType.h"
53 #include "ir/ts/tsTypeParameterDeclaration.h"
54 #include "ir/ts/tsTypeAliasDeclaration.h"
55 #include "ir/ts/tsTypeReference.h"
56 #include "ir/ts/tsInterfaceDeclaration.h"
57 #include "ir/ets/etsNewClassInstanceExpression.h"
58 #include "ir/ets/etsTypeReference.h"
59 #include "ir/base/tsSignatureDeclaration.h"
60 #include "ir/base/tsMethodSignature.h"
61 
62 namespace panda::es2panda::varbinder {
InitTopScope()63 void VarBinder::InitTopScope()
64 {
65     if (program_->Kind() == parser::ScriptKind::MODULE) {
66         topScope_ = Allocator()->New<ModuleScope>(Allocator());
67     } else {
68         topScope_ = Allocator()->New<GlobalScope>(Allocator());
69     }
70 
71     scope_ = topScope_;
72     varScope_ = topScope_;
73 }
74 
AddParamDecl(ir::AstNode * param)75 std::tuple<ParameterDecl *, Variable *> VarBinder::AddParamDecl(ir::AstNode *param)
76 {
77     ASSERT(scope_->IsFunctionParamScope() || scope_->IsCatchParamScope());
78     auto [decl, node, var] = static_cast<ParamScope *>(scope_)->AddParamDecl(Allocator(), param);
79 
80     if (node == nullptr) {
81         return {decl, var};
82     }
83 
84     ThrowRedeclaration(node->Start(), decl->Name());
85 }
86 
ThrowRedeclaration(const lexer::SourcePosition & pos,const util::StringView & name) const87 void VarBinder::ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name) const
88 {
89     std::stringstream ss;
90     ss << "Variable '" << name << "' has already been declared.";
91     ThrowError(pos, ss.str());
92 }
93 
ThrowUnresolvableVariable(const lexer::SourcePosition & pos,const util::StringView & name) const94 void VarBinder::ThrowUnresolvableVariable(const lexer::SourcePosition &pos, const util::StringView &name) const
95 {
96     std::stringstream ss;
97     ss << "Cannot find variable '" << name << "'.";
98     ThrowError(pos, ss.str());
99 }
100 
ThrowUnresolvableType(const lexer::SourcePosition & pos,const util::StringView & name) const101 void VarBinder::ThrowUnresolvableType(const lexer::SourcePosition &pos, const util::StringView &name) const
102 {
103     std::stringstream ss;
104     ss << "Cannot find type '" << name << "'.";
105     ThrowError(pos, ss.str());
106 }
107 
ThrowTDZ(const lexer::SourcePosition & pos,const util::StringView & name) const108 void VarBinder::ThrowTDZ(const lexer::SourcePosition &pos, const util::StringView &name) const
109 {
110     std::stringstream ss;
111     ss << "Variable '" << name << "' is accessed before it's initialization.";
112     ThrowError(pos, ss.str());
113 }
114 
ThrowInvalidCapture(const lexer::SourcePosition & pos,const util::StringView & name) const115 void VarBinder::ThrowInvalidCapture(const lexer::SourcePosition &pos, const util::StringView &name) const
116 {
117     std::stringstream ss;
118     ss << "Cannot capture variable'" << name << "'.";
119     ThrowError(pos, ss.str());
120 }
121 
ThrowPrivateFieldMismatch(const lexer::SourcePosition & pos,const util::StringView & name) const122 void VarBinder::ThrowPrivateFieldMismatch(const lexer::SourcePosition &pos, const util::StringView &name) const
123 {
124     std::stringstream ss;
125     ss << "Private field '" << name << "' must be declared in an enclosing class";
126 
127     ThrowError(pos, ss.str());
128 }
129 
ThrowError(const lexer::SourcePosition & pos,const std::string_view & msg) const130 void VarBinder::ThrowError(const lexer::SourcePosition &pos, const std::string_view &msg) const
131 {
132     lexer::LineIndex index(program_->SourceCode());
133     lexer::SourceLocation loc = index.GetLocation(pos);
134 
135     throw Error(ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), msg, loc.line, loc.col);
136 }
137 
IdentifierAnalysis()138 void VarBinder::IdentifierAnalysis()
139 {
140     ASSERT(program_->Ast());
141     ASSERT(scope_ == topScope_);
142     ASSERT(varScope_ == topScope_);
143 
144     functionScopes_.push_back(topScope_);
145     topScope_->BindName(MAIN);
146     topScope_->BindInternalName(BuildFunctionName(MAIN, 0));
147 
148     topScope_->CheckDirectEval(compilerCtx_);
149 
150     ResolveReferences(program_->Ast());
151     AddMandatoryParams();
152 }
153 
LookupReference(const util::StringView & name)154 void VarBinder::LookupReference(const util::StringView &name)
155 {
156     auto res = scope_->Find(name);
157     if (res.level == 0) {
158         return;
159     }
160 
161     ASSERT(res.variable);
162     res.variable->SetLexical(res.scope);
163 }
164 
InstantiateArgumentsImpl(Scope ** scope,Scope * iter,const ir::AstNode * node)165 bool VarBinder::InstantiateArgumentsImpl(Scope **scope, Scope *iter, const ir::AstNode *node)
166 {
167     if (node->AsScriptFunction()->IsArrow()) {
168         return false;
169     }
170     auto *argumentsVariable =
171         (*scope)->AddDecl<ConstDecl, LocalVariable>(Allocator(), FUNCTION_ARGUMENTS, VariableFlags::INITIALIZED);
172     if (iter->IsFunctionParamScope()) {
173         if (argumentsVariable == nullptr) {
174             return true;
175         }
176 
177         *scope = iter->AsFunctionParamScope()->GetFunctionScope();
178         (*scope)->InsertBinding(argumentsVariable->Name(), argumentsVariable);
179     }
180 
181     (*scope)->AddFlag(ScopeFlags::USE_ARGS);
182     return true;
183 }
184 
InstantiateArguments()185 void VarBinder::InstantiateArguments()
186 {
187     auto *iter = scope_;
188     while (true) {
189         Scope *scope = iter->IsFunctionParamScope() ? iter : iter->EnclosingVariableScope();
190 
191         const auto *node = scope->Node();
192 
193         if (scope->IsLoopScope()) {
194             iter = scope->Parent();
195             continue;
196         }
197 
198         if (!node->IsScriptFunction()) {
199             break;
200         }
201 
202         if (InstantiateArgumentsImpl(&scope, iter, node)) {
203             break;
204         }
205 
206         iter = scope->Parent();
207     }
208 }
209 
PropagateDirectEval() const210 void VarBinder::PropagateDirectEval() const
211 {
212     auto *iter = scope_;
213 
214     do {
215         VariableScope *scope = iter->IsFunctionParamScope() ? iter->AsFunctionParamScope()->GetFunctionScope()
216                                                             : iter->EnclosingVariableScope();
217 
218         scope->AddFlag(ScopeFlags::NO_REG_STORE);
219         iter = iter->Parent();
220     } while (iter != nullptr);
221 }
222 
InstantiatePrivateContext(const ir::Identifier * ident) const223 void VarBinder::InstantiatePrivateContext(const ir::Identifier *ident) const
224 {
225     auto *classDef = util::Helpers::GetContainingClassDefinition(ident);
226 
227     while (classDef != nullptr) {
228         auto *scope = classDef->Scope();
229         Variable *variable = scope->FindLocal(classDef->PrivateId(), varbinder::ResolveBindingOptions::BINDINGS);
230 
231         if (!variable->HasFlag(VariableFlags::INITIALIZED)) {
232             break;
233         }
234 
235         if (classDef->HasMatchingPrivateKey(ident->Name())) {
236             variable->SetLexical(scope);
237             return;
238         }
239 
240         classDef = util::Helpers::GetContainingClassDefinition(classDef->Parent());
241     }
242 
243     ThrowPrivateFieldMismatch(ident->Start(), ident->Name());
244 }
245 
LookupIdentReference(ir::Identifier * ident)246 void VarBinder::LookupIdentReference(ir::Identifier *ident)
247 {
248     if (!ident->IsReference()) {
249         return;
250     }
251 
252     if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
253         InstantiateArguments();
254     }
255 
256     if (ident->IsPrivateIdent()) {
257         InstantiatePrivateContext(ident);
258         return;
259     }
260 
261     auto res = scope_->Find(ident->Name(), BindingOptions());
262     if (res.level != 0) {
263         ASSERT(res.variable);
264         res.variable->SetLexical(res.scope);
265     }
266 
267     if (res.variable == nullptr) {
268         return;
269     }
270 
271     if (res.variable->Declaration()->IsLetOrConstDecl() && !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
272         ident->SetTdz();
273     }
274 
275     ident->SetVariable(res.variable);
276 }
277 
BuildFunctionName(util::StringView name,uint32_t idx)278 util::StringView VarBinder::BuildFunctionName(util::StringView name, uint32_t idx)
279 {
280     std::stringstream ss;
281     ss << "func_" << name << "_" << std::to_string(idx);
282     util::UString internalName(ss.str(), Allocator());
283 
284     return internalName.View();
285 }
286 
BuildInternalName(ir::ScriptFunction * scriptFunc)287 bool VarBinder::BuildInternalName(ir::ScriptFunction *scriptFunc)
288 {
289     auto *funcScope = scriptFunc->Scope();
290     auto name = util::Helpers::FunctionName(Allocator(), scriptFunc);
291 
292     uint32_t idx = functionScopes_.size();
293     funcScope->BindName(name);
294     funcScope->BindInternalName(BuildFunctionName(name, idx));
295 
296     return !scriptFunc->IsOverload();
297 }
298 
BuildVarDeclaratorId(ir::AstNode * childNode)299 void VarBinder::BuildVarDeclaratorId(ir::AstNode *childNode)
300 {
301     switch (childNode->Type()) {
302         case ir::AstNodeType::IDENTIFIER: {
303             auto *ident = childNode->AsIdentifier();
304             const auto &name = ident->Name();
305 
306             if (util::Helpers::IsGlobalIdentifier(name)) {
307                 break;
308             }
309 
310             auto *variable = scope_->FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS);
311             ident->SetVariable(variable);
312             BuildSignatureDeclarationBaseParams(ident->TypeAnnotation());
313             variable->AddFlag(VariableFlags::INITIALIZED);
314             break;
315         }
316         case ir::AstNodeType::OBJECT_PATTERN: {
317             auto *objPattern = childNode->AsObjectPattern();
318 
319             for (auto *prop : objPattern->Properties()) {
320                 BuildVarDeclaratorId(prop);
321             }
322 
323             BuildSignatureDeclarationBaseParams(objPattern->TypeAnnotation());
324             break;
325         }
326         case ir::AstNodeType::ARRAY_PATTERN: {
327             auto *arrayPattern = childNode->AsArrayPattern();
328 
329             for (auto *element : childNode->AsArrayPattern()->Elements()) {
330                 BuildVarDeclaratorId(element);
331             }
332 
333             BuildSignatureDeclarationBaseParams(arrayPattern->TypeAnnotation());
334             break;
335         }
336         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
337             ResolveReference(childNode->AsAssignmentPattern()->Right());
338             BuildVarDeclaratorId(childNode->AsAssignmentPattern()->Left());
339             break;
340         }
341         case ir::AstNodeType::PROPERTY: {
342             ResolveReference(childNode->AsProperty()->Key());
343             BuildVarDeclaratorId(childNode->AsProperty()->Value());
344             break;
345         }
346         case ir::AstNodeType::REST_ELEMENT: {
347             BuildVarDeclaratorId(childNode->AsRestElement()->Argument());
348             break;
349         }
350         default:
351             break;
352     }
353 }
354 
BuildVarDeclarator(ir::VariableDeclarator * varDecl)355 void VarBinder::BuildVarDeclarator(ir::VariableDeclarator *varDecl)
356 {
357     if (varDecl->Parent()->AsVariableDeclaration()->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) {
358         ResolveReferences(varDecl);
359         return;
360     }
361 
362     if (varDecl->Init() != nullptr) {
363         ResolveReference(varDecl->Init());
364     }
365 
366     BuildVarDeclaratorId(varDecl->Id());
367 }
368 
BuildClassProperty(const ir::ClassProperty * prop)369 void VarBinder::BuildClassProperty(const ir::ClassProperty *prop)
370 {
371     const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(prop);
372     auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, ctor->Scope());
373 
374     ResolveReferences(prop);
375 }
376 
InitializeClassBinding(ir::ClassDefinition * classDef)377 void VarBinder::InitializeClassBinding(ir::ClassDefinition *classDef)
378 {
379     auto res = scope_->Find(classDef->Ident()->Name());
380 
381     ASSERT(res.variable && res.variable->Declaration()->IsLetDecl());
382     res.variable->AddFlag(VariableFlags::INITIALIZED);
383 }
384 
InitializeClassIdent(ir::ClassDefinition * classDef)385 void VarBinder::InitializeClassIdent(ir::ClassDefinition *classDef)
386 {
387     auto res = scope_->Find(classDef->Ident()->Name());
388 
389     ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
390     res.variable->AddFlag(VariableFlags::INITIALIZED);
391 }
392 
BuildClassDefinition(ir::ClassDefinition * classDef)393 void VarBinder::BuildClassDefinition(ir::ClassDefinition *classDef)
394 {
395     if (classDef->Parent()->IsClassDeclaration() || classDef->Parent()->IsETSStructDeclaration()) {
396         InitializeClassBinding(classDef);
397     }
398 
399     auto scopeCtx = LexicalScope<LocalScope>::Enter(this, classDef->Scope());
400 
401     if (classDef->Super() != nullptr) {
402         ResolveReference(classDef->Super());
403     }
404 
405     Variable *variable = scope_->FindLocal(classDef->PrivateId(), varbinder::ResolveBindingOptions::BINDINGS);
406     variable->AddFlag(VariableFlags::INITIALIZED);
407 
408     if (classDef->Ident() != nullptr) {
409         InitializeClassIdent(classDef);
410     }
411 
412     ResolveReference(classDef->Ctor());
413 
414     for (auto *stmt : classDef->Body()) {
415         ResolveReference(stmt);
416     }
417 }
418 
BuildForUpdateLoop(ir::ForUpdateStatement * forUpdateStmt)419 void VarBinder::BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt)
420 {
421     auto *loopScope = forUpdateStmt->Scope();
422 
423     auto declScopeCtx = LexicalScope<LoopDeclarationScope>::Enter(this, loopScope->DeclScope());
424 
425     if (forUpdateStmt->Init() != nullptr) {
426         ResolveReference(forUpdateStmt->Init());
427     }
428 
429     if (forUpdateStmt->Update() != nullptr) {
430         ResolveReference(forUpdateStmt->Update());
431     }
432 
433     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
434 
435     if (forUpdateStmt->Test() != nullptr) {
436         ResolveReference(forUpdateStmt->Test());
437     }
438 
439     ResolveReference(forUpdateStmt->Body());
440 
441     loopCtx.GetScope()->ConvertToVariableScope(Allocator());
442 }
443 
BuildForInOfLoop(varbinder::LoopScope * loopScope,ir::AstNode * left,ir::Expression * right,ir::Statement * body)444 void VarBinder::BuildForInOfLoop(varbinder::LoopScope *loopScope, ir::AstNode *left, ir::Expression *right,
445                                  ir::Statement *body)
446 {
447     auto declScopeCtx = LexicalScope<LoopDeclarationScope>::Enter(this, loopScope->DeclScope());
448 
449     ResolveReference(right);
450     ResolveReference(left);
451 
452     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
453 
454     ResolveReference(body);
455     loopCtx.GetScope()->ConvertToVariableScope(Allocator());
456 }
457 
BuildCatchClause(ir::CatchClause * catchClauseStmt)458 void VarBinder::BuildCatchClause(ir::CatchClause *catchClauseStmt)
459 {
460     if (catchClauseStmt->Param() != nullptr) {
461         auto paramScopeCtx = LexicalScope<CatchParamScope>::Enter(this, catchClauseStmt->Scope()->ParamScope());
462         ResolveReference(catchClauseStmt->Param());
463     }
464 
465     auto scopeCtx = LexicalScope<CatchScope>::Enter(this, catchClauseStmt->Scope());
466     ResolveReference(catchClauseStmt->Body());
467 }
468 
BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration * const typeAliasDecl)469 void VarBinder::BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration *const typeAliasDecl)
470 {
471     if (typeAliasDecl->TypeParams() != nullptr) {
472         const auto typeAliasScope = LexicalScope<LocalScope>::Enter(this, typeAliasDecl->TypeParams()->Scope());
473         ResolveReferences(typeAliasDecl);
474         return;
475     }
476 
477     ResolveReferences(typeAliasDecl);
478 }
479 
AddCompilableFunction(ir::ScriptFunction * func)480 void VarBinder::AddCompilableFunction(ir::ScriptFunction *func)
481 {
482     if (func->IsArrow()) {
483         VariableScope *outerVarScope = scope_->EnclosingVariableScope();
484         outerVarScope->AddFlag(ScopeFlags::INNER_ARROW);
485     }
486 
487     AddCompilableFunctionScope(func->Scope());
488 }
489 
AddCompilableFunctionScope(varbinder::FunctionScope * funcScope)490 void VarBinder::AddCompilableFunctionScope(varbinder::FunctionScope *funcScope)
491 {
492     functionScopes_.push_back(funcScope);
493 }
494 
VisitScriptFunction(ir::ScriptFunction * func)495 void VarBinder::VisitScriptFunction(ir::ScriptFunction *func)
496 {
497     auto *funcScope = func->Scope();
498     {
499         auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, funcScope->ParamScope());
500 
501         for (auto *param : func->Params()) {
502             ResolveReference(param);
503         }
504     }
505 
506     if (func->ReturnTypeAnnotation() != nullptr) {
507         ResolveReference(func->ReturnTypeAnnotation());
508     }
509 
510     if (!BuildInternalName(func)) {
511         return;
512     }
513 
514     AddCompilableFunction(func);
515 
516     auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
517 
518     if (func->Body() != nullptr) {
519         ResolveReference(func->Body());
520     }
521 }
522 
VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction * func)523 void VarBinder::VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func)
524 {
525     if (func->TypeParams() != nullptr) {
526         auto typeParamScopeCtx = LexicalScope<Scope>::Enter(this, func->TypeParams()->Scope());
527         VisitScriptFunction(func);
528         return;
529     }
530 
531     VisitScriptFunction(func);
532 }
533 
ResolveReference(ir::AstNode * childNode)534 void VarBinder::ResolveReference(ir::AstNode *childNode)
535 {
536     switch (childNode->Type()) {
537         case ir::AstNodeType::IDENTIFIER: {
538             auto *ident = childNode->AsIdentifier();
539 
540             LookupIdentReference(ident);
541             ResolveReferences(childNode);
542             break;
543         }
544         case ir::AstNodeType::SUPER_EXPRESSION: {
545             VariableScope *varScope = scope_->EnclosingVariableScope();
546             varScope->AddFlag(ScopeFlags::USE_SUPER);
547             ResolveReferences(childNode);
548             break;
549         }
550         case ir::AstNodeType::SCRIPT_FUNCTION: {
551             VisitScriptFunctionWithPotentialTypeParams(childNode->AsScriptFunction());
552             break;
553         }
554         case ir::AstNodeType::VARIABLE_DECLARATOR: {
555             BuildVarDeclarator(childNode->AsVariableDeclarator());
556             break;
557         }
558         case ir::AstNodeType::CLASS_DEFINITION: {
559             BuildClassDefinition(childNode->AsClassDefinition());
560             break;
561         }
562         case ir::AstNodeType::CLASS_PROPERTY: {
563             BuildClassProperty(childNode->AsClassProperty());
564             break;
565         }
566         case ir::AstNodeType::BLOCK_STATEMENT: {
567             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsBlockStatement()->Scope());
568 
569             ResolveReferences(childNode);
570             break;
571         }
572         case ir::AstNodeType::SWITCH_STATEMENT: {
573             auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
574 
575             ResolveReferences(childNode);
576             break;
577         }
578         case ir::AstNodeType::DO_WHILE_STATEMENT: {
579             auto *doWhileStatement = childNode->AsDoWhileStatement();
580 
581             {
582                 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
583                 ResolveReference(doWhileStatement->Body());
584             }
585 
586             ResolveReference(doWhileStatement->Test());
587             break;
588         }
589         case ir::AstNodeType::WHILE_STATEMENT: {
590             auto *whileStatement = childNode->AsWhileStatement();
591             ResolveReference(whileStatement->Test());
592 
593             auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
594             ResolveReference(whileStatement->Body());
595 
596             break;
597         }
598         case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
599             BuildForUpdateLoop(childNode->AsForUpdateStatement());
600             break;
601         }
602         case ir::AstNodeType::FOR_IN_STATEMENT: {
603             auto *forInStmt = childNode->AsForInStatement();
604             BuildForInOfLoop(forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
605 
606             break;
607         }
608         case ir::AstNodeType::FOR_OF_STATEMENT: {
609             auto *forOfStmt = childNode->AsForOfStatement();
610             BuildForInOfLoop(forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
611             break;
612         }
613         case ir::AstNodeType::CATCH_CLAUSE: {
614             BuildCatchClause(childNode->AsCatchClause());
615             break;
616         }
617         case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: {
618             BuildTypeAliasDeclaration(childNode->AsTSTypeAliasDeclaration());
619             break;
620         }
621         default: {
622             HandleCustomNodes(childNode);
623             break;
624         }
625     }
626 }
627 
ResolveReferences(const ir::AstNode * parent)628 void VarBinder::ResolveReferences(const ir::AstNode *parent)
629 {
630     parent->Iterate([this](auto *childNode) { ResolveReference(childNode); });
631 }
632 
AddMandatoryParam(const std::string_view & name)633 LocalVariable *VarBinder::AddMandatoryParam(const std::string_view &name)
634 {
635     ASSERT(scope_->IsFunctionParamScope());
636 
637     auto *decl = Allocator()->New<ParameterDecl>(name);
638     auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
639 
640     auto &funcParams = scope_->AsFunctionParamScope()->Params();
641 
642     funcParams.insert(funcParams.begin(), param);
643     scope_->AsFunctionParamScope()->GetFunctionScope()->InsertBinding(decl->Name(), param);
644     scope_->InsertBinding(decl->Name(), param);
645 
646     return param;
647 }
648 
LookUpMandatoryReferences(const FunctionScope * funcScope,bool needLexicalFuncObj)649 void VarBinder::LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj)
650 {
651     LookupReference(MANDATORY_PARAM_NEW_TARGET);
652     LookupReference(MANDATORY_PARAM_THIS);
653 
654     if (funcScope->HasFlag(ScopeFlags::USE_ARGS)) {
655         LookupReference(FUNCTION_ARGUMENTS);
656     }
657 
658     if (needLexicalFuncObj) {
659         LookupReference(MANDATORY_PARAM_FUNC);
660     }
661 }
662 
AddMandatoryParams()663 void VarBinder::AddMandatoryParams()
664 {
665     ASSERT(scope_ == topScope_);
666     ASSERT(!functionScopes_.empty());
667     auto iter = functionScopes_.begin();
668     [[maybe_unused]] auto *funcScope = *iter++;
669 
670     ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
671 
672     if (compilerCtx_->IsDirectEval()) {
673         AddMandatoryParams(EVAL_SCRIPT_MANDATORY_PARAMS);
674         topScope_->ParamScope()->Params().back()->SetLexical(topScope_);
675     } else {
676         AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
677     }
678 
679     if (compilerCtx_->IsFunctionEval()) {
680         ASSERT(iter != functionScopes_.end());
681         funcScope = *iter++;
682         auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
683         AddMandatoryParams(ARROW_MANDATORY_PARAMS);
684         LookUpMandatoryReferences(funcScope, false);
685     }
686 
687     for (; iter != functionScopes_.end(); iter++) {
688         funcScope = *iter;
689         const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
690 
691         auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
692 
693         if (!scriptFunc->IsArrow()) {
694             AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
695             continue;
696         }
697 
698         const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
699         bool lexicalFunctionObject {};
700 
701         if (ctor != nullptr && util::Helpers::GetClassDefiniton(ctor)->Super() != nullptr &&
702             funcScope->HasFlag(ScopeFlags::USE_SUPER)) {
703             ASSERT(ctor->Scope()->HasFlag(ScopeFlags::INNER_ARROW));
704             ctor->Scope()->AddFlag(ScopeFlags::SET_LEXICAL_FUNCTION);
705             lexicalFunctionObject = true;
706             AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
707         } else {
708             AddMandatoryParams(ARROW_MANDATORY_PARAMS);
709         }
710 
711         LookUpMandatoryReferences(funcScope, lexicalFunctionObject);
712     }
713 }
714 }  // namespace panda::es2panda::varbinder
715