1 /**
2 * Copyright (c) 2021-2024 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 #include "varbinder/privateBinding.h"
18 #include "parser/program/program.h"
19 #include "util/helpers.h"
20 #include "varbinder/scope.h"
21 #include "varbinder/tsBinding.h"
22 #include "es2panda.h"
23 #include "ir/astNode.h"
24 #include "ir/base/catchClause.h"
25 #include "ir/base/classDefinition.h"
26 #include "ir/base/classProperty.h"
27 #include "ir/base/classStaticBlock.h"
28 #include "ir/base/methodDefinition.h"
29 #include "ir/base/property.h"
30 #include "ir/base/scriptFunction.h"
31 #include "ir/base/spreadElement.h"
32 #include "ir/expressions/arrayExpression.h"
33 #include "ir/expressions/assignmentExpression.h"
34 #include "ir/expressions/blockExpression.h"
35 #include "ir/expressions/memberExpression.h"
36 #include "ir/expressions/identifier.h"
37 #include "ir/expressions/objectExpression.h"
38 #include "ir/statements/blockStatement.h"
39 #include "ir/statements/doWhileStatement.h"
40 #include "ir/statements/forInStatement.h"
41 #include "ir/statements/forOfStatement.h"
42 #include "ir/statements/forUpdateStatement.h"
43 #include "ir/statements/ifStatement.h"
44 #include "ir/statements/switchStatement.h"
45 #include "ir/statements/variableDeclaration.h"
46 #include "ir/statements/variableDeclarator.h"
47 #include "ir/statements/whileStatement.h"
48 #include "ir/module/exportNamedDeclaration.h"
49 #include "ir/module/importDeclaration.h"
50 #include "ir/ts/tsFunctionType.h"
51 #include "ir/ts/tsConstructorType.h"
52 #include "ir/ts/tsTypeParameterDeclaration.h"
53 #include "ir/ts/tsTypeAliasDeclaration.h"
54 #include "ir/ts/tsTypeReference.h"
55 #include "ir/ts/tsInterfaceDeclaration.h"
56 #include "ir/ets/etsNewClassInstanceExpression.h"
57 #include "ir/ets/etsTypeReference.h"
58 #include "ir/base/tsSignatureDeclaration.h"
59 #include "ir/base/tsMethodSignature.h"
60 #include "public/public.h"
61
62 namespace ark::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(context_);
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(Extension())) {
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 ASSERT(variable);
312 ident->SetVariable(variable);
313 BuildSignatureDeclarationBaseParams(ident->TypeAnnotation());
314 variable->AddFlag(VariableFlags::INITIALIZED);
315 break;
316 }
317 case ir::AstNodeType::OBJECT_PATTERN: {
318 auto *objPattern = childNode->AsObjectPattern();
319
320 for (auto *prop : objPattern->Properties()) {
321 BuildVarDeclaratorId(prop);
322 }
323
324 BuildSignatureDeclarationBaseParams(objPattern->TypeAnnotation());
325 break;
326 }
327 case ir::AstNodeType::ARRAY_PATTERN: {
328 auto *arrayPattern = childNode->AsArrayPattern();
329
330 for (auto *element : childNode->AsArrayPattern()->Elements()) {
331 BuildVarDeclaratorId(element);
332 }
333
334 BuildSignatureDeclarationBaseParams(arrayPattern->TypeAnnotation());
335 break;
336 }
337 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
338 ResolveReference(childNode->AsAssignmentPattern()->Right());
339 BuildVarDeclaratorId(childNode->AsAssignmentPattern()->Left());
340 break;
341 }
342 case ir::AstNodeType::PROPERTY: {
343 ResolveReference(childNode->AsProperty()->Key());
344 BuildVarDeclaratorId(childNode->AsProperty()->Value());
345 break;
346 }
347 case ir::AstNodeType::REST_ELEMENT: {
348 BuildVarDeclaratorId(childNode->AsRestElement()->Argument());
349 break;
350 }
351 default:
352 break;
353 }
354 }
355
BuildVarDeclarator(ir::VariableDeclarator * varDecl)356 void VarBinder::BuildVarDeclarator(ir::VariableDeclarator *varDecl)
357 {
358 if (varDecl->Parent()->AsVariableDeclaration()->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) {
359 ResolveReferences(varDecl);
360 return;
361 }
362
363 if (varDecl->Init() != nullptr) {
364 ResolveReference(varDecl->Init());
365 }
366
367 BuildVarDeclaratorId(varDecl->Id());
368 }
369
BuildClassProperty(const ir::ClassProperty * prop)370 void VarBinder::BuildClassProperty(const ir::ClassProperty *prop)
371 {
372 const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(prop);
373 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, ctor->Scope());
374
375 ResolveReferences(prop);
376 }
377
InitializeClassBinding(ir::ClassDefinition * classDef)378 void VarBinder::InitializeClassBinding(ir::ClassDefinition *classDef)
379 {
380 auto res = scope_->Find(classDef->Ident()->Name());
381
382 ASSERT(res.variable && res.variable->Declaration()->IsLetDecl());
383 res.variable->AddFlag(VariableFlags::INITIALIZED);
384 }
385
InitializeClassIdent(ir::ClassDefinition * classDef)386 void VarBinder::InitializeClassIdent(ir::ClassDefinition *classDef)
387 {
388 auto res = scope_->Find(classDef->Ident()->Name());
389
390 ASSERT(res.variable &&
391 (res.variable->Declaration()->IsConstDecl() || res.variable->Declaration()->IsReadonlyDecl()));
392 res.variable->AddFlag(VariableFlags::INITIALIZED);
393 }
394
BuildClassDefinition(ir::ClassDefinition * classDef)395 void VarBinder::BuildClassDefinition(ir::ClassDefinition *classDef)
396 {
397 if (classDef->Parent()->IsClassDeclaration() || classDef->Parent()->IsETSStructDeclaration()) {
398 InitializeClassBinding(classDef);
399 }
400
401 auto scopeCtx = LexicalScope<LocalScope>::Enter(this, classDef->Scope());
402
403 if (classDef->Super() != nullptr) {
404 ResolveReference(classDef->Super());
405 }
406
407 Variable *variable = scope_->FindLocal(classDef->PrivateId(), varbinder::ResolveBindingOptions::BINDINGS);
408 variable->AddFlag(VariableFlags::INITIALIZED);
409
410 if (classDef->Ident() != nullptr) {
411 InitializeClassIdent(classDef);
412 }
413
414 ResolveReference(classDef->Ctor());
415
416 for (auto *stmt : classDef->Body()) {
417 ResolveReference(stmt);
418 }
419 }
420
BuildForUpdateLoop(ir::ForUpdateStatement * forUpdateStmt)421 void VarBinder::BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt)
422 {
423 auto *loopScope = forUpdateStmt->Scope();
424
425 auto declScopeCtx = LexicalScope<LoopDeclarationScope>::Enter(this, loopScope->DeclScope());
426
427 if (forUpdateStmt->Init() != nullptr) {
428 ResolveReference(forUpdateStmt->Init());
429 }
430
431 if (forUpdateStmt->Update() != nullptr) {
432 ResolveReference(forUpdateStmt->Update());
433 }
434
435 auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
436
437 if (forUpdateStmt->Test() != nullptr) {
438 ResolveReference(forUpdateStmt->Test());
439 }
440
441 ResolveReference(forUpdateStmt->Body());
442
443 loopCtx.GetScope()->ConvertToVariableScope(Allocator());
444 }
445
BuildForInOfLoop(varbinder::LoopScope * loopScope,ir::AstNode * left,ir::Expression * right,ir::Statement * body)446 void VarBinder::BuildForInOfLoop(varbinder::LoopScope *loopScope, ir::AstNode *left, ir::Expression *right,
447 ir::Statement *body)
448 {
449 auto declScopeCtx = LexicalScope<LoopDeclarationScope>::Enter(this, loopScope->DeclScope());
450
451 ResolveReference(right);
452 ResolveReference(left);
453
454 auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
455
456 ResolveReference(body);
457 loopCtx.GetScope()->ConvertToVariableScope(Allocator());
458 }
459
BuildCatchClause(ir::CatchClause * catchClauseStmt)460 void VarBinder::BuildCatchClause(ir::CatchClause *catchClauseStmt)
461 {
462 if (catchClauseStmt->Param() != nullptr) {
463 auto paramScopeCtx = LexicalScope<CatchParamScope>::Enter(this, catchClauseStmt->Scope()->ParamScope());
464 ResolveReference(catchClauseStmt->Param());
465 }
466
467 auto scopeCtx = LexicalScope<CatchScope>::Enter(this, catchClauseStmt->Scope());
468 ResolveReference(catchClauseStmt->Body());
469 }
470
BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration * const typeAliasDecl)471 void VarBinder::BuildTypeAliasDeclaration(ir::TSTypeAliasDeclaration *const typeAliasDecl)
472 {
473 if (typeAliasDecl->TypeParams() != nullptr) {
474 const auto typeAliasScope = LexicalScope<LocalScope>::Enter(this, typeAliasDecl->TypeParams()->Scope());
475 ResolveReferences(typeAliasDecl);
476 return;
477 }
478
479 ResolveReferences(typeAliasDecl);
480 }
481
AddCompilableFunction(ir::ScriptFunction * func)482 void VarBinder::AddCompilableFunction(ir::ScriptFunction *func)
483 {
484 if (func->IsArrow()) {
485 VariableScope *outerVarScope = scope_->EnclosingVariableScope();
486 ASSERT(outerVarScope != nullptr);
487 outerVarScope->AddFlag(ScopeFlags::INNER_ARROW);
488 }
489
490 AddCompilableFunctionScope(func->Scope());
491 }
492
AddCompilableFunctionScope(varbinder::FunctionScope * funcScope)493 void VarBinder::AddCompilableFunctionScope(varbinder::FunctionScope *funcScope)
494 {
495 functionScopes_.push_back(funcScope);
496 }
497
VisitScriptFunction(ir::ScriptFunction * func)498 void VarBinder::VisitScriptFunction(ir::ScriptFunction *func)
499 {
500 auto *funcScope = func->Scope();
501 {
502 ASSERT(funcScope != nullptr);
503 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, funcScope->ParamScope());
504
505 for (auto *param : func->Params()) {
506 ResolveReference(param);
507 }
508 }
509
510 if (func->ReturnTypeAnnotation() != nullptr) {
511 ResolveReference(func->ReturnTypeAnnotation());
512 }
513
514 if (!BuildInternalName(func)) {
515 return;
516 }
517
518 if (!func->IsDeclare()) {
519 AddCompilableFunction(func);
520 }
521
522 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
523
524 if (func->Body() != nullptr) {
525 ResolveReference(func->Body());
526 }
527 }
528
VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction * func)529 void VarBinder::VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func)
530 {
531 if (func->TypeParams() != nullptr) {
532 auto typeParamScopeCtx = LexicalScope<Scope>::Enter(this, func->TypeParams()->Scope());
533 VisitScriptFunction(func);
534 return;
535 }
536
537 VisitScriptFunction(func);
538 }
539
ResolveReferenceDoWhileHelper(ir::AstNode * childNode)540 void VarBinder::ResolveReferenceDoWhileHelper(ir::AstNode *childNode)
541 {
542 auto *doWhileStatement = childNode->AsDoWhileStatement();
543
544 {
545 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
546 ResolveReference(doWhileStatement->Body());
547 }
548 return ResolveReference(doWhileStatement->Test());
549 }
550
ResolveReferenceWhileHelper(ir::AstNode * childNode)551 void VarBinder::ResolveReferenceWhileHelper(ir::AstNode *childNode)
552 {
553 auto *whileStatement = childNode->AsWhileStatement();
554 ResolveReference(whileStatement->Test());
555
556 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
557 return ResolveReference(whileStatement->Body());
558 }
559
ResolveReference(ir::AstNode * childNode)560 void VarBinder::ResolveReference(ir::AstNode *childNode)
561 {
562 switch (childNode->Type()) {
563 case ir::AstNodeType::IDENTIFIER:
564 LookupIdentReference(childNode->AsIdentifier());
565 return ResolveReferences(childNode);
566 case ir::AstNodeType::SUPER_EXPRESSION:
567 scope_->EnclosingVariableScope()->AddFlag(ScopeFlags::USE_SUPER);
568 return ResolveReferences(childNode);
569 case ir::AstNodeType::SCRIPT_FUNCTION:
570 return VisitScriptFunctionWithPotentialTypeParams(childNode->AsScriptFunction());
571 case ir::AstNodeType::VARIABLE_DECLARATOR:
572 return BuildVarDeclarator(childNode->AsVariableDeclarator());
573 case ir::AstNodeType::CLASS_DEFINITION:
574 return BuildClassDefinition(childNode->AsClassDefinition());
575 case ir::AstNodeType::CLASS_PROPERTY:
576 return BuildClassProperty(childNode->AsClassProperty());
577 case ir::AstNodeType::BLOCK_STATEMENT: {
578 auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsBlockStatement()->Scope());
579
580 return ResolveReferences(childNode);
581 }
582 case ir::AstNodeType::BLOCK_EXPRESSION: {
583 auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsBlockExpression()->Scope());
584
585 return ResolveReferences(childNode);
586 }
587 case ir::AstNodeType::SWITCH_STATEMENT: {
588 auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
589
590 return ResolveReferences(childNode);
591 }
592 case ir::AstNodeType::DO_WHILE_STATEMENT:
593 return ResolveReferenceDoWhileHelper(childNode);
594 case ir::AstNodeType::WHILE_STATEMENT:
595 return ResolveReferenceWhileHelper(childNode);
596 case ir::AstNodeType::FOR_UPDATE_STATEMENT:
597 return BuildForUpdateLoop(childNode->AsForUpdateStatement());
598 case ir::AstNodeType::FOR_IN_STATEMENT: {
599 auto *forInStmt = childNode->AsForInStatement();
600 return BuildForInOfLoop(forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
601 }
602 case ir::AstNodeType::FOR_OF_STATEMENT: {
603 auto *forOfStmt = childNode->AsForOfStatement();
604 return BuildForInOfLoop(forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
605 }
606 case ir::AstNodeType::CATCH_CLAUSE:
607 return BuildCatchClause(childNode->AsCatchClause());
608 case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION:
609 return BuildTypeAliasDeclaration(childNode->AsTSTypeAliasDeclaration());
610 default:
611 return HandleCustomNodes(childNode);
612 }
613 }
614
ResolveReferences(const ir::AstNode * parent)615 void VarBinder::ResolveReferences(const ir::AstNode *parent)
616 {
617 parent->Iterate([this](auto *childNode) { ResolveReference(childNode); });
618 }
619
AddMandatoryParam(const std::string_view & name)620 LocalVariable *VarBinder::AddMandatoryParam(const std::string_view &name)
621 {
622 ASSERT(scope_->IsFunctionParamScope());
623
624 auto *decl = Allocator()->New<ParameterDecl>(name);
625 auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
626
627 auto &funcParams = scope_->AsFunctionParamScope()->Params();
628
629 funcParams.insert(funcParams.begin(), param);
630 scope_->AsFunctionParamScope()->GetFunctionScope()->InsertBinding(decl->Name(), param);
631 scope_->InsertBinding(decl->Name(), param);
632
633 return param;
634 }
635
LookUpMandatoryReferences(const FunctionScope * funcScope,bool needLexicalFuncObj)636 void VarBinder::LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj)
637 {
638 LookupReference(MANDATORY_PARAM_NEW_TARGET);
639 LookupReference(MANDATORY_PARAM_THIS);
640
641 if (funcScope->HasFlag(ScopeFlags::USE_ARGS)) {
642 LookupReference(FUNCTION_ARGUMENTS);
643 }
644
645 if (needLexicalFuncObj) {
646 LookupReference(MANDATORY_PARAM_FUNC);
647 }
648 }
649
AddMandatoryParams()650 void VarBinder::AddMandatoryParams()
651 {
652 ASSERT(scope_ == topScope_);
653 ASSERT(!functionScopes_.empty());
654 auto iter = functionScopes_.begin();
655 [[maybe_unused]] auto *funcScope = *iter++;
656
657 ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
658
659 const auto &options = context_->config->options->CompilerOptions();
660 if (options.isDirectEval) {
661 AddMandatoryParams(EVAL_SCRIPT_MANDATORY_PARAMS);
662 topScope_->ParamScope()->Params().back()->SetLexical(topScope_);
663 } else {
664 AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
665 }
666
667 if (options.isFunctionEval) {
668 ASSERT(iter != functionScopes_.end());
669 funcScope = *iter++;
670 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
671 AddMandatoryParams(ARROW_MANDATORY_PARAMS);
672 LookUpMandatoryReferences(funcScope, false);
673 }
674
675 for (; iter != functionScopes_.end(); iter++) {
676 funcScope = *iter;
677 const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
678
679 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
680
681 if (!scriptFunc->IsArrow()) {
682 AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
683 continue;
684 }
685
686 const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
687 bool lexicalFunctionObject {};
688
689 if (ctor != nullptr && util::Helpers::GetClassDefiniton(ctor)->Super() != nullptr &&
690 funcScope->HasFlag(ScopeFlags::USE_SUPER)) {
691 ASSERT(ctor->Scope()->HasFlag(ScopeFlags::INNER_ARROW));
692 ctor->Scope()->AddFlag(ScopeFlags::SET_LEXICAL_FUNCTION);
693 lexicalFunctionObject = true;
694 AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
695 } else {
696 AddMandatoryParams(ARROW_MANDATORY_PARAMS);
697 }
698
699 LookUpMandatoryReferences(funcScope, lexicalFunctionObject);
700 }
701 }
702 } // namespace ark::es2panda::varbinder
703