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