• 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 "binder/scope.h"
19 #include "binder/tsBinding.h"
20 #include "es2panda.h"
21 #include "ir/astNode.h"
22 #include "ir/base/catchClause.h"
23 #include "ir/base/classDefinition.h"
24 #include "ir/base/methodDefinition.h"
25 #include "ir/base/property.h"
26 #include "ir/base/scriptFunction.h"
27 #include "ir/base/spreadElement.h"
28 #include "ir/expressions/arrayExpression.h"
29 #include "ir/expressions/assignmentExpression.h"
30 #include "ir/expressions/identifier.h"
31 #include "ir/expressions/objectExpression.h"
32 #include "ir/expressions/literals/numberLiteral.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/tsClassImplements.h"
47 #include "ir/ts/tsConstructorType.h"
48 #include "ir/ts/tsEnumDeclaration.h"
49 #include "ir/ts/tsFunctionType.h"
50 #include "ir/ts/tsIndexSignature.h"
51 #include "ir/ts/tsMethodSignature.h"
52 #include "ir/ts/tsModuleBlock.h"
53 #include "ir/ts/tsModuleDeclaration.h"
54 #include "ir/ts/tsSignatureDeclaration.h"
55 #include "ir/ts/tsTypeParameterDeclaration.h"
56 #include "ir/ts/tsTypeParameterInstantiation.h"
57 #include "util/concurrent.h"
58 #include "util/patchFix.h"
59 
60 namespace panda::es2panda::binder {
InitTopScope()61 void Binder::InitTopScope()
62 {
63     if (program_->Kind() == parser::ScriptKind::MODULE) {
64         topScope_ = Allocator()->New<ModuleScope>(Allocator());
65     } else {
66         topScope_ = Allocator()->New<GlobalScope>(Allocator());
67     }
68 
69     scope_ = topScope_;
70 }
71 
AddParamDecl(const ir::AstNode * param)72 ParameterDecl *Binder::AddParamDecl(const ir::AstNode *param)
73 {
74     ASSERT(scope_->IsFunctionParamScope() || scope_->IsCatchParamScope());
75     auto [decl, node] = static_cast<ParamScope *>(scope_)->AddParamDecl(Allocator(), param);
76 
77     if (!node) {
78         return decl;
79     }
80 
81     ThrowRedeclaration(node->Start(), decl->Name());
82 }
83 
ThrowRedeclaration(const lexer::SourcePosition & pos,const util::StringView & name)84 void Binder::ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name)
85 {
86     lexer::LineIndex index(program_->SourceCode());
87     lexer::SourceLocation loc = index.GetLocation(pos);
88 
89     std::stringstream ss;
90     ss << "Variable '" << name << "' has already been declared.";
91     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
92 }
93 
ThrowUndeclaredExport(const lexer::SourcePosition & pos,const util::StringView & name)94 void Binder::ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util::StringView &name)
95 {
96     lexer::LineIndex index(program_->SourceCode());
97     lexer::SourceLocation loc = index.GetLocation(pos);
98 
99     std::stringstream ss;
100     ss << "Export name '" << name << "' is not defined.";
101     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
102 }
103 
ThrowInvalidDstrTarget(const lexer::SourcePosition & pos,const util::StringView & name)104 void Binder::ThrowInvalidDstrTarget(const lexer::SourcePosition &pos, const util::StringView &name)
105 {
106     lexer::LineIndex index(program_->SourceCode());
107     lexer::SourceLocation loc = index.GetLocation(pos);
108 
109     std::stringstream ss;
110     ss << "Invalid destructuring assignment target: " << name;
111     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
112 }
113 
CheckMandatoryArguments(const ir::Identifier * ident)114 void Binder::CheckMandatoryArguments(const ir::Identifier *ident)
115 {
116     const auto *iter = static_cast<const ir::AstNode *>(ident);
117     bool isPatternMember = false;
118     while (iter) {
119         if (iter->IsArrayExpression() || iter->IsArrayPattern()) {
120             isPatternMember = true;
121             break;
122         }
123 
124         if (iter->IsObjectExpression() || iter->IsObjectPattern()) {
125             auto &properties = iter->IsObjectExpression() ? iter->AsObjectExpression()->Properties() :
126                                                             iter->AsObjectPattern()->Properties();
127             isPatternMember = util::Helpers::IsObjectPropertyValue(properties, ident);
128             break;
129         }
130         iter = iter->Parent();
131     }
132 
133     if (!isPatternMember) {
134         return;
135     }
136 
137     auto *patternNode = iter;
138 
139     while (iter) {
140         if (iter->IsAssignmentExpression() || iter->IsVariableDeclarator() || iter->IsForInStatement() ||
141             iter->IsForOfStatement()) {
142             break;
143         }
144 
145         iter = iter->Parent();
146     }
147 
148     if (!iter) {
149         return;
150     }
151 
152     const ir::AstNode *potentialParent = iter;
153 
154     if (iter->IsAssignmentExpression()) {
155         potentialParent = iter->AsAssignmentExpression()->Left();
156     } else if (iter->IsVariableDeclarator()) {
157         potentialParent = iter->AsVariableDeclarator()->Id();
158     } else {
159         potentialParent = iter->IsForInStatement() ? iter->AsForInStatement()->Left() :
160                                                      iter->AsForOfStatement()->Left();
161     }
162 
163     if (!util::Helpers::IsChild(potentialParent, patternNode)) {
164         return;
165     }
166 
167     ThrowInvalidDstrTarget(ident->Start(), ident->Name());
168 }
169 
AssignIndexToModuleVariable()170 void Binder::AssignIndexToModuleVariable()
171 {
172     ASSERT(program_->ModuleRecord());
173     program_->ModuleRecord()->AssignIndexToModuleVariable(topScope_->AsModuleScope());
174 }
175 
IdentifierAnalysis(ResolveBindingFlags flags)176 void Binder::IdentifierAnalysis(ResolveBindingFlags flags)
177 {
178     ASSERT(program_->Ast());
179     ASSERT(scope_ == topScope_);
180 
181     bindingFlags_ = flags;
182     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
183         ResolveReferences(program_->Ast());
184     } else if (bindingFlags_ & ResolveBindingFlags::ALL) {
185         BuildFunction(topScope_, MAIN_FUNC_NAME);
186         ResolveReferences(program_->Ast());
187         AddMandatoryParams();
188         if (topScope_->IsModuleScope()) {
189             AssignIndexToModuleVariable();
190         }
191     }
192 }
193 
ValidateExportDecl(const ir::ExportNamedDeclaration * exportDecl)194 void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl)
195 {
196     if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr || exportDecl->IsType()) {
197         return;
198     }
199 
200     ASSERT(topScope_->IsModuleScope());
201     for (auto *it : exportDecl->Specifiers()) {
202         auto localName = it->AsExportSpecifier()->Local()->Name();
203         if (scope_->IsTSModuleScope()) {
204             auto currentScope = scope_;
205             while (currentScope != nullptr) {
206                 if (currentScope->FindLocal(localName, ResolveBindingOptions::ALL) != nullptr ||
207                     (currentScope->IsTSModuleScope() && (currentScope->InLocalTSBindings(localName) ||
208                     currentScope->AsTSModuleScope()->InExportBindings(localName)))) {
209                     break;
210                 }
211                 currentScope = currentScope->Parent();
212             }
213             if (currentScope != nullptr) {
214                 continue;
215             }
216             ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
217         }
218         ASSERT(topScope_ == scope_);
219         if (scope_->FindLocal(localName) == nullptr) {
220             // The declaration of ts cannot correspond to the variables of ts before transform,
221             // After the transform, they are all js variables. So it can return directly here.
222             if (scope_->InLocalTSBindings(localName) ||
223                 scope_->FindLocal(localName, ResolveBindingOptions::INTERFACES)) {
224                 continue;
225             }
226             ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
227         }
228         scope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName);
229     }
230 }
231 
LookupReference(const util::StringView & name)232 void Binder::LookupReference(const util::StringView &name)
233 {
234     ScopeFindResult res = scope_->Find(name);
235     if (res.level == 0) {
236         return;
237     }
238 
239     ASSERT(res.variable);
240     res.variable->SetLexical(res.scope, program_->PatchFixHelper());
241 }
242 
InstantiateArguments()243 void Binder::InstantiateArguments()
244 {
245     auto *iter = scope_;
246     while (true) {
247         Scope *scope = iter->IsFunctionParamScope() ? iter : iter->EnclosingVariableScope();
248 
249         const auto *node = scope->Node();
250 
251         if (scope->IsLoopScope()) {
252             iter = scope->Parent();
253             continue;
254         }
255 
256         if (!node->IsScriptFunction()) {
257             break;
258         }
259 
260         if (!node->AsScriptFunction()->IsArrow()) {
261             auto *argumentsVariable =
262                 scope->AddDecl<ConstDecl, LocalVariable>(Allocator(), FUNCTION_ARGUMENTS, VariableFlags::INITIALIZED);
263 
264             if (iter->IsFunctionParamScope()) {
265                 if (!argumentsVariable) {
266                     break;
267                 }
268 
269                 scope = iter->AsFunctionParamScope()->GetFunctionScope();
270                 scope->Bindings().insert({argumentsVariable->Name(), argumentsVariable});
271             }
272 
273             scope->AsVariableScope()->AddFlag(VariableScopeFlags::USE_ARGS);
274 
275             break;
276         }
277 
278         iter = scope->Parent();
279     }
280 }
281 
LookupIdentReference(ir::Identifier * ident)282 void Binder::LookupIdentReference(ir::Identifier *ident)
283 {
284     if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
285         InstantiateArguments();
286     }
287 
288     ScopeFindResult res;
289     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
290         ident->SetTSVariables(FindIdentifierTSVariables(ident, scope_, res));
291     } else {
292         if (ident->Parent()->IsTSTypeReference()) {
293             res = scope_->Find(ident->Name(), ResolveBindingOptions::ALL);
294         } else {
295             res = scope_->Find(ident->Name(), ResolveBindingOptions::BINDINGS);
296         }
297     }
298 
299     if (res.level != 0) {
300         ASSERT(res.variable);
301         if (!res.variable->Declaration()->IsDeclare()) {
302             util::Concurrent::VerifyImportVarForConcurrentFunction(Program()->GetLineIndex(), ident, res);
303             res.variable->SetLexical(res.scope, program_->PatchFixHelper());
304         }
305     }
306 
307     if (res.variable == nullptr) {
308         return;
309     }
310 
311     auto decl = res.variable->Declaration();
312     if (decl->IsLetOrConstOrClassDecl() && !decl->HasFlag(DeclarationFlags::NAMESPACE_IMPORT) &&
313         !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
314         ident->SetTdz();
315     }
316     // in release mode, replace const reference with its initialization
317     if (!this->Program()->IsDebug() && decl->IsConstDecl()) {
318         ReplaceConstReferenceWithInitialization(ident, decl);
319     }
320 
321     ident->SetVariable(res.variable);
322 }
323 
StoreAndCheckSpecialFunctionName(std::string & internalNameStr,std::string recordName)324 void Binder::StoreAndCheckSpecialFunctionName(std::string &internalNameStr, std::string recordName)
325 {
326     if (program_->PatchFixHelper()) {
327         if (program_->PatchFixHelper()->IsDumpSymbolTable()) {
328             // anonymous, special-name and duplicate function index started from 1
329             specialFuncNameIndexMap_.insert({internalNameStr, std::to_string(++globalIndexForSpecialFunc_)});
330             return;
331         }
332         if (program_->PatchFixHelper()->IsHotFix()) {
333             // Adding/removing anonymous, special or duplicate functions is supported for hotReload and coldFix mode,
334             // but forbidden in hotFix mode
335             program_->PatchFixHelper()->CheckAndRestoreSpecialFunctionName(++globalIndexForSpecialFunc_,
336                 internalNameStr, recordName);
337             return;
338         }
339         // else: must be coldfix or hotreload mode
340         ASSERT(program_->PatchFixHelper()->IsColdFix() || program_->PatchFixHelper()->IsHotReload());
341     }
342 }
343 
BuildFunction(FunctionScope * funcScope,util::StringView name,const ir::ScriptFunction * func)344 void Binder::BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func)
345 {
346     if (funcScope->InFunctionScopes()) {
347         return;
348     }
349     functionScopes_.push_back(funcScope);
350     funcScope->SetInFunctionScopes();
351 
352     bool funcNameWithoutDot = (name.Find(".") == std::string::npos);
353     bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos);
354     if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot && funcNameWithoutBackslash && !functionNames_.count(name)) {
355         // function with normal name, and hasn't been recorded
356         auto internalName = std::string(program_->FormatedRecordName()) + std::string(name);
357         functionNames_.insert(name);
358         funcScope->BindName(name, util::UString(internalName, Allocator()).View());
359         return;
360     }
361 
362     std::stringstream ss;
363     ss << std::string(program_->FormatedRecordName());
364 
365     ASSERT(func != nullptr);
366 
367     // For anonymous, special-name and duplicate function, get its source and name, make hash code,
368     // and make #hash_duplicateHashTime#name as its name;
369     auto funcContentNameStr = func->SourceCode(this).Mutf8() + name.Mutf8();
370     ss << ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER << util::Helpers::GetHashString(funcContentNameStr);
371 
372     auto res = functionHashNames_.find(funcContentNameStr);
373     if (res != functionHashNames_.end()) {
374         ss << "_" << res->second++;
375     } else {
376         functionHashNames_.insert({funcContentNameStr, 1});
377     }
378     ss << ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER;
379 
380     if (name == ANONYMOUS_FUNC_NAME) {
381         anonymousFunctionNames_[func] = util::UString(ss.str(), Allocator()).View();
382     }
383     if (funcNameWithoutDot && funcNameWithoutBackslash) {
384         ss << name;
385     }
386     std::string internalNameStr = ss.str();
387     StoreAndCheckSpecialFunctionName(internalNameStr, program_->RecordName().Mutf8());
388     funcScope->BindName(name, util::UString(internalNameStr, Allocator()).View());
389 }
390 
BuildScriptFunction(Scope * outerScope,const ir::ScriptFunction * scriptFunc)391 void Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc)
392 {
393     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
394         return;
395     }
396 
397     if (scriptFunc->IsArrow()) {
398         VariableScope *outerVarScope = outerScope->EnclosingVariableScope();
399         outerVarScope->AddFlag(VariableScopeFlags::INNER_ARROW);
400     }
401 
402     ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope() || scope_->IsTSEnumScope());
403     BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(Allocator(), scriptFunc), scriptFunc);
404 }
405 
BuildVarDeclaratorId(const ir::AstNode * parent,ir::AstNode * childNode)406 void Binder::BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode)
407 {
408     childNode->SetParent(parent);
409 
410     switch (childNode->Type()) {
411         case ir::AstNodeType::IDENTIFIER: {
412             auto *ident = childNode->AsIdentifier();
413             const auto &name = ident->Name();
414             if (name.Is(FUNCTION_ARGUMENTS)) {
415                 CheckMandatoryArguments(ident);
416             }
417 
418             if (util::Helpers::IsGlobalIdentifier(name)) {
419                 break;
420             }
421 
422             auto *variable = scope_->FindLocal(name, ResolveBindingOptions::BINDINGS);
423 
424             if (Program()->Extension() == ScriptExtension::TS) {
425                 ident->SetVariable(variable);
426                 BuildTSSignatureDeclarationBaseParamsWithParent(ident, ident->TypeAnnotation());
427             }
428 
429             variable->AddFlag(VariableFlags::INITIALIZED);
430             break;
431         }
432         case ir::AstNodeType::OBJECT_PATTERN: {
433             auto *objPattern = childNode->AsObjectPattern();
434 
435             for (auto *prop : objPattern->Properties()) {
436                 BuildVarDeclaratorId(childNode, prop);
437             }
438 
439             BuildTSSignatureDeclarationBaseParamsWithParent(objPattern, objPattern->TypeAnnotation());
440             break;
441         }
442         case ir::AstNodeType::ARRAY_PATTERN: {
443             auto *arrayPattern = childNode->AsArrayPattern();
444 
445             for (auto *element : childNode->AsArrayPattern()->Elements()) {
446                 BuildVarDeclaratorId(childNode, element);
447             }
448 
449             BuildTSSignatureDeclarationBaseParamsWithParent(arrayPattern, arrayPattern->TypeAnnotation());
450             break;
451         }
452         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
453             ResolveReference(childNode, childNode->AsAssignmentPattern()->Right());
454             BuildVarDeclaratorId(childNode, childNode->AsAssignmentPattern()->Left());
455             break;
456         }
457         case ir::AstNodeType::PROPERTY: {
458             ResolveReference(childNode, childNode->AsProperty()->Key());
459             BuildVarDeclaratorId(childNode, childNode->AsProperty()->Value());
460             break;
461         }
462         case ir::AstNodeType::REST_ELEMENT: {
463             BuildVarDeclaratorId(childNode, childNode->AsRestElement()->Argument());
464             break;
465         }
466         default:
467             break;
468     }
469 }
470 
BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode * parent,ir::AstNode * typeNode)471 void Binder::BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode *parent, ir::AstNode *typeNode)
472 {
473     if (!typeNode) {
474         return;
475     }
476     typeNode->SetParent(parent);
477     BuildTSSignatureDeclarationBaseParams(typeNode);
478 }
479 
BuildTSSignatureDeclarationBaseParams(const ir::AstNode * typeNode)480 void Binder::BuildTSSignatureDeclarationBaseParams(const ir::AstNode *typeNode)
481 {
482     ASSERT(typeNode != nullptr);
483 
484     Scope *scope = nullptr;
485 
486     switch (typeNode->Type()) {
487         case ir::AstNodeType::TS_FUNCTION_TYPE: {
488             scope = typeNode->AsTSFunctionType()->Scope();
489             break;
490         }
491         case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: {
492             scope = typeNode->AsTSConstructorType()->Scope();
493             break;
494         }
495         case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
496             scope = typeNode->AsTSSignatureDeclaration()->Scope();
497             break;
498         }
499         case ir::AstNodeType::TS_METHOD_SIGNATURE: {
500             scope = typeNode->AsTSMethodSignature()->Scope();
501             break;
502         }
503         default: {
504             ResolveReferences(typeNode);
505             return;
506         }
507     }
508 
509     ASSERT(scope && scope->IsFunctionParamScope());
510 
511     auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope->AsFunctionParamScope());
512     ResolveReferences(typeNode);
513 }
514 
BuildVarDeclarator(ir::VariableDeclarator * varDecl)515 void Binder::BuildVarDeclarator(ir::VariableDeclarator *varDecl)
516 {
517     if (varDecl->Parent()->AsVariableDeclaration()->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) {
518         ResolveReferences(varDecl);
519         return;
520     }
521 
522     if (varDecl->Init()) {
523         ResolveReference(varDecl, varDecl->Init());
524     }
525 
526     BuildVarDeclaratorId(varDecl, varDecl->Id());
527 }
528 
BuildClassDefinition(ir::ClassDefinition * classDef)529 void Binder::BuildClassDefinition(ir::ClassDefinition *classDef)
530 {
531     if (classDef->Parent()->IsClassDeclaration()) {
532         util::StringView className = classDef->GetName();
533         ASSERT(!className.Empty());
534         ScopeFindResult res = scope_->Find(className);
535 
536         ASSERT(res.variable && (res.variable->Declaration()->IsClassDecl() ||
537                (res.variable->Declaration()->IsFunctionDecl() &&
538                res.variable->Declaration()->AsFunctionDecl()->GetDeclClass() != nullptr)));
539         res.variable->AddFlag(VariableFlags::INITIALIZED);
540     }
541 
542     auto scopeCtx = LexicalScope<LocalScope>::Enter(this, classDef->Scope());
543 
544     if (classDef->TypeParams()) {
545         ResolveReference(classDef, classDef->TypeParams());
546     }
547 
548     if (classDef->Super()) {
549         ResolveReference(classDef, classDef->Super());
550     }
551 
552     if (classDef->SuperTypeParams()) {
553         ResolveReference(classDef, classDef->SuperTypeParams());
554     }
555 
556     for (auto *iter : classDef->Implements()) {
557         ResolveReference(classDef, iter);
558     }
559 
560     if (classDef->Ident()) {
561         ScopeFindResult res = scope_->Find(classDef->Ident()->Name());
562 
563         ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
564         res.variable->AddFlag(VariableFlags::INITIALIZED);
565 
566         classDef->Ident()->SetParent(classDef);
567     }
568 
569     ResolveReference(classDef, classDef->Ctor());
570 
571     for (auto *stmt : classDef->Body()) {
572         ResolveReference(classDef, stmt);
573     }
574 
575     for (auto *iter : classDef->IndexSignatures()) {
576         ResolveReference(classDef, iter);
577     }
578 }
579 
BuildForUpdateLoop(ir::ForUpdateStatement * forUpdateStmt)580 void Binder::BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt)
581 {
582     auto *loopScope = forUpdateStmt->Scope();
583 
584     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
585 
586     if (forUpdateStmt->Init()) {
587         ResolveReference(forUpdateStmt, forUpdateStmt->Init());
588     }
589 
590     if (forUpdateStmt->Update()) {
591         ResolveReference(forUpdateStmt, forUpdateStmt->Update());
592     }
593 
594     if (forUpdateStmt->Test()) {
595         ResolveReference(forUpdateStmt, forUpdateStmt->Test());
596     }
597 
598     ResolveReference(forUpdateStmt, forUpdateStmt->Body());
599 
600     loopCtx.GetScope()->InitVariable();
601 }
602 
BuildForInOfLoop(const ir::Statement * parent,binder::LoopScope * loopScope,ir::AstNode * left,ir::Expression * right,ir::Statement * body)603 void Binder::BuildForInOfLoop(const ir::Statement *parent, binder::LoopScope *loopScope, ir::AstNode *left,
604                               ir::Expression *right, ir::Statement *body)
605 {
606     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
607 
608     ResolveReference(parent, right);
609     ResolveReference(parent, left);
610 
611     ResolveReference(parent, body);
612     loopCtx.GetScope()->InitVariable();
613 }
614 
BuildCatchClause(ir::CatchClause * catchClauseStmt)615 void Binder::BuildCatchClause(ir::CatchClause *catchClauseStmt)
616 {
617     if (catchClauseStmt->Param()) {
618         auto paramScopeCtx = LexicalScope<CatchParamScope>::Enter(this, catchClauseStmt->Scope()->ParamScope());
619         ResolveReference(catchClauseStmt, catchClauseStmt->Param());
620     }
621 
622     auto scopeCtx = LexicalScope<CatchScope>::Enter(this, catchClauseStmt->Scope());
623     ResolveReference(catchClauseStmt, catchClauseStmt->Body());
624 }
625 
ResolveReference(const ir::AstNode * parent,ir::AstNode * childNode)626 void Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode)
627 {
628     childNode->SetParent(parent);
629 
630     switch (childNode->Type()) {
631         case ir::AstNodeType::IDENTIFIER: {
632             auto *ident = childNode->AsIdentifier();
633 
634             if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
635                 CheckMandatoryArguments(ident);
636             }
637 
638             if (ident->IsReference()) {
639                 LookupIdentReference(ident);
640             }
641 
642             ResolveReferences(childNode);
643             break;
644         }
645         case ir::AstNodeType::SUPER_EXPRESSION: {
646             VariableScope *varScope = scope_->EnclosingVariableScope();
647             varScope->AddFlag(VariableScopeFlags::USE_SUPER);
648 
649             ResolveReferences(childNode);
650             break;
651         }
652         case ir::AstNodeType::SCRIPT_FUNCTION: {
653             auto *scriptFunc = childNode->AsScriptFunction();
654             util::Helpers::ScanDirectives(const_cast<ir::ScriptFunction *>(scriptFunc),
655                                           Program()->GetLineIndex());
656             auto *funcScope = scriptFunc->Scope();
657 
658             auto *outerScope = scope_;
659 
660             if (scriptFunc->Id() != nullptr) {
661                 scriptFunc->Id()->SetParent(scriptFunc);
662             }
663 
664             {
665                 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, funcScope->ParamScope());
666 
667                 if (Program()->Extension() == ScriptExtension::TS) {
668                     if (scriptFunc->TypeParams() != nullptr) {
669                         ResolveReference(scriptFunc, scriptFunc->TypeParams());
670                     }
671                     if (scriptFunc->ThisParams() != nullptr) {
672                         ResolveReference(scriptFunc, scriptFunc->ThisParams());
673                     }
674                 }
675 
676                 for (auto *param : scriptFunc->Params()) {
677                     ResolveReference(scriptFunc, param);
678                 }
679             }
680 
681             if (Program()->Extension() == ScriptExtension::TS) {
682                 if (scriptFunc->ReturnTypeAnnotation()) {
683                     ResolveReference(scriptFunc, scriptFunc->ReturnTypeAnnotation());
684                 }
685 
686                 if (scriptFunc->IsOverload() || scriptFunc->Declare()) {
687                     break;
688                 }
689             }
690 
691             auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
692 
693             BuildScriptFunction(outerScope, scriptFunc);
694 
695             ResolveReference(scriptFunc, scriptFunc->Body());
696             break;
697         }
698         case ir::AstNodeType::VARIABLE_DECLARATOR: {
699             BuildVarDeclarator(childNode->AsVariableDeclarator());
700 
701             break;
702         }
703         case ir::AstNodeType::CLASS_DEFINITION: {
704             BuildClassDefinition(childNode->AsClassDefinition());
705 
706             break;
707         }
708         case ir::AstNodeType::CLASS_PROPERTY: {
709             const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(childNode->AsClassProperty());
710             auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, ctor->Scope());
711 
712             ResolveReferences(childNode);
713             break;
714         }
715         case ir::AstNodeType::BLOCK_STATEMENT: {
716             auto scope = childNode->AsBlockStatement()->Scope();
717             auto scopeCtx = scope != nullptr ?
718                 LexicalScope<Scope>::Enter(this, scope) :
719                 LexicalScope<Scope>::Enter(this, GetScope());
720 
721             ResolveReferences(childNode);
722             break;
723         }
724         case ir::AstNodeType::SWITCH_STATEMENT: {
725             auto *switchStatement = childNode->AsSwitchStatement();
726             ResolveReference(switchStatement, switchStatement->Discriminant());
727 
728             auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
729             for (auto *it : switchStatement->Cases()) {
730                 ResolveReference(switchStatement, it);
731             }
732             break;
733         }
734         case ir::AstNodeType::DO_WHILE_STATEMENT: {
735             auto *doWhileStatement = childNode->AsDoWhileStatement();
736 
737             {
738                 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
739                 ResolveReference(doWhileStatement, doWhileStatement->Body());
740                 loopScopeCtx.GetScope()->InitVariable();
741             }
742 
743             ResolveReference(doWhileStatement, doWhileStatement->Test());
744             break;
745         }
746         case ir::AstNodeType::WHILE_STATEMENT: {
747             auto *whileStatement = childNode->AsWhileStatement();
748             ResolveReference(whileStatement, whileStatement->Test());
749 
750             auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
751             ResolveReference(whileStatement, whileStatement->Body());
752             loopScopeCtx.GetScope()->InitVariable();
753             break;
754         }
755         case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
756             BuildForUpdateLoop(childNode->AsForUpdateStatement());
757             break;
758         }
759         case ir::AstNodeType::FOR_IN_STATEMENT: {
760             auto *forInStmt = childNode->AsForInStatement();
761             BuildForInOfLoop(forInStmt, forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
762 
763             break;
764         }
765         case ir::AstNodeType::FOR_OF_STATEMENT: {
766             auto *forOfStmt = childNode->AsForOfStatement();
767             BuildForInOfLoop(forOfStmt, forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
768             break;
769         }
770         case ir::AstNodeType::CATCH_CLAUSE: {
771             BuildCatchClause(childNode->AsCatchClause());
772             break;
773         }
774         case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
775             ValidateExportDecl(childNode->AsExportNamedDeclaration());
776 
777             ResolveReferences(childNode);
778             break;
779         }
780         // TypeScript specific part
781         case ir::AstNodeType::TS_FUNCTION_TYPE:
782         case ir::AstNodeType::TS_CONSTRUCTOR_TYPE:
783         case ir::AstNodeType::TS_METHOD_SIGNATURE:
784         case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
785             BuildTSSignatureDeclarationBaseParams(childNode);
786             break;
787         }
788         case ir::AstNodeType::TS_MODULE_DECLARATION: {
789             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSModuleDeclaration()->Scope());
790             ResolveReferences(childNode);
791             break;
792         }
793         case ir::AstNodeType::TS_ENUM_DECLARATION: {
794             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSEnumDeclaration()->Scope());
795             ResolveReferences(childNode);
796             break;
797         }
798         default: {
799             ResolveReferences(childNode);
800             break;
801         }
802     }
803 }
ResolveReferences(const ir::AstNode * parent)804 void Binder::ResolveReferences(const ir::AstNode *parent)
805 {
806     parent->Iterate([this, parent](auto *childNode) { ResolveReference(parent, childNode); });
807 }
808 
AddMandatoryParam(const std::string_view & name)809 void Binder::AddMandatoryParam(const std::string_view &name)
810 {
811     ASSERT(scope_->IsFunctionVariableScope());
812 
813     auto *decl = Allocator()->New<ParameterDecl>(name);
814     auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
815 
816     auto &funcParams = scope_->AsFunctionVariableScope()->ParamScope()->Params();
817     funcParams.insert(funcParams.begin(), param);
818     scope_->AsFunctionVariableScope()->ParamScope()->Bindings().insert({decl->Name(), param});
819     scope_->AsFunctionVariableScope()->Bindings().insert({decl->Name(), param});
820 }
821 
AddMandatoryParams()822 void Binder::AddMandatoryParams()
823 {
824     ASSERT(scope_ == topScope_);
825     ASSERT(!functionScopes_.empty());
826     auto iter = functionScopes_.begin();
827     [[maybe_unused]] auto *funcScope = *iter++;
828 
829     ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
830 
831     if (program_->Kind() == parser::ScriptKind::COMMONJS) {
832         AddMandatoryParams(CJS_MAINFUNC_MANDATORY_PARAMS);
833     } else {
834         AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
835     }
836 
837     for (; iter != functionScopes_.end(); iter++) {
838         funcScope = *iter;
839         const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
840 
841         auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
842 
843         if (!scriptFunc->IsArrow()) {
844             AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
845             continue;
846         }
847 
848         const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
849         bool lexicalFunctionObject {};
850 
851         if (ctor && util::Helpers::GetClassDefiniton(ctor)->Super() &&
852             funcScope->HasFlag(VariableScopeFlags::USE_SUPER)) {
853             ASSERT(ctor->Scope()->HasFlag(VariableScopeFlags::INNER_ARROW));
854             ctor->Scope()->AddFlag(VariableScopeFlags::SET_LEXICAL_FUNCTION);
855             lexicalFunctionObject = true;
856             AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
857         } else {
858             AddMandatoryParams(ARROW_MANDATORY_PARAMS);
859         }
860 
861         LookupReference(MANDATORY_PARAM_NEW_TARGET);
862         LookupReference(MANDATORY_PARAM_THIS);
863 
864         if (funcScope->HasFlag(VariableScopeFlags::USE_ARGS)) {
865             LookupReference(FUNCTION_ARGUMENTS);
866         }
867 
868         if (lexicalFunctionObject) {
869             LookupReference(MANDATORY_PARAM_FUNC);
870         }
871     }
872 }
873 
AddDeclarationName(const util::StringView & name,DeclType type)874 void Binder::AddDeclarationName(const util::StringView &name, DeclType type)
875 {
876     if (extension_ != ScriptExtension::TS) {
877         return;
878     }
879     variableNames_.insert(name);
880 
881     if (type == DeclType::ENUM) {
882         return;
883     }
884     auto *scope = GetScope();
885     while (scope != nullptr) {
886         if (scope->IsTSModuleScope()) {
887             scope->AsTSModuleScope()->AddDeclarationName(name);
888         }
889         if (scope->IsTSEnumScope()) {
890             scope->AsTSEnumScope()->AddDeclarationName(name);
891         }
892         scope = scope->Parent();
893     }
894 }
895 
HasVariableName(const util::StringView & name) const896 bool Binder::HasVariableName(const util::StringView &name) const
897 {
898     return variableNames_.find(name) != variableNames_.end();
899 }
900 
FindIdentifierTSVariables(const ir::Identifier * identifier,Scope * scope,ScopeFindResult & res)901 std::vector<Variable *> Binder::FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope,
902     ScopeFindResult &res)
903 {
904     const auto &name = identifier->Name();
905     std::vector<binder::Variable *> findRes;
906 
907     auto currentScope = scope;
908     while (currentScope != nullptr) {
909         // Find ts variables
910         auto fn = [&findRes](Variable *variable) {
911             if (variable != nullptr) {
912                 findRes.emplace_back(variable);
913             }
914         };
915 
916         fn(currentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name));
917         fn(currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
918         fn(currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
919         if (currentScope->IsTSModuleScope()) {
920             fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name));
921             fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
922             fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
923         }
924 
925         // Find js variable
926         if (currentScope->FindLocal(name, bindingOptions_) != nullptr) {
927             res = scope->Find(name, bindingOptions_);
928             break;
929         }
930 
931         if (!findRes.empty()) {
932             break;
933         }
934 
935         currentScope = currentScope->Parent();
936     }
937 
938     return findRes;
939 }
940 
ReplaceConstReferenceWithInitialization(const ir::Identifier * ident,const Decl * decl)941 void Binder::ReplaceConstReferenceWithInitialization(const ir::Identifier *ident, const Decl *decl)
942 {
943     bool isValidAssignmentExpr = ident->Parent()->IsAssignmentExpression() &&
944         ident->Parent()->AsAssignmentExpression()->Right() == ident;
945     bool isBinaryExpr = ident->Parent()->IsBinaryExpression();
946     bool isVariableDecl = ident->Parent()->IsVariableDeclarator() &&
947         ident->Parent()->AsVariableDeclarator()->Init() == ident;
948     if (!isValidAssignmentExpr && !isBinaryExpr && !isVariableDecl) {
949         return;
950     }
951 
952     if (decl->Node() == nullptr || decl->Node()->Parent() == nullptr ||
953         !decl->Node()->Parent()->IsVariableDeclarator()) {
954         return;
955     }
956 
957     const ir::AstNode *initialization = static_cast<const ir::AstNode *>(
958         decl->Node()->Parent()->AsVariableDeclarator()->Init());
959     if (initialization == nullptr || !initialization->IsNumberLiteral()) {
960         return;
961     }
962 
963     auto newNode = Allocator()->New<ir::NumberLiteral>(initialization->AsNumberLiteral()->Number());
964     if (newNode == nullptr) {
965         throw Error(ErrorType::GENERIC, "Unsuccessful allocation during replacing const reference node");
966     }
967     // Make sure the new node get the correct line number
968     // Column number may be incorrect, but it doesn't matter in release mode
969     newNode->SetRange(ident->Range());
970 
971     auto *parentNode = const_cast<panda::es2panda::ir::AstNode *>(ident->Parent());
972     // update the reference node with initialization node
973     parentNode->UpdateSelf([=](auto *childNode) {
974             if (childNode == ident) {
975                 return static_cast<ir::AstNode *>(newNode);
976             }
977             return childNode;
978         }, this);
979 }
980 
981 }  // namespace panda::es2panda::binder
982