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