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
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 "es2panda.h"
24 #include "ir/astNode.h"
25 #include "ir/base/catchClause.h"
26 #include "ir/base/classDefinition.h"
27 #include "ir/base/classProperty.h"
28 #include "ir/base/classStaticBlock.h"
29 #include "ir/base/methodDefinition.h"
30 #include "ir/base/property.h"
31 #include "ir/base/scriptFunction.h"
32 #include "ir/base/spreadElement.h"
33 #include "ir/expressions/arrayExpression.h"
34 #include "ir/expressions/assignmentExpression.h"
35 #include "ir/expressions/blockExpression.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 #include "public/public.h"
62
63 namespace ark::es2panda::varbinder {
InitTopScope()64 void VarBinder::InitTopScope()
65 {
66 if (program_->Kind() == parser::ScriptKind::MODULE) {
67 topScope_ = Allocator()->New<ModuleScope>(Allocator());
68 } else {
69 topScope_ = Allocator()->New<GlobalScope>(Allocator());
70 }
71
72 scope_ = topScope_;
73 varScope_ = topScope_;
74 }
75
AddParamDecl(ir::AstNode * param)76 std::tuple<ParameterDecl *, Variable *> VarBinder::AddParamDecl(ir::AstNode *param)
77 {
78 ASSERT(scope_->IsFunctionParamScope() || scope_->IsCatchParamScope());
79 auto [decl, node, var] = static_cast<ParamScope *>(scope_)->AddParamDecl(Allocator(), param);
80
81 if (node == nullptr) {
82 return {decl, var};
83 }
84
85 ThrowRedeclaration(node->Start(), decl->Name());
86 }
87
ThrowRedeclaration(const lexer::SourcePosition & pos,const util::StringView & name) const88 void VarBinder::ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name) const
89 {
90 std::stringstream ss;
91 ss << "Variable '" << name << "' has already been declared.";
92 ThrowError(pos, ss.str());
93 }
94
ThrowUnresolvableVariable(const lexer::SourcePosition & pos,const util::StringView & name) const95 void VarBinder::ThrowUnresolvableVariable(const lexer::SourcePosition &pos, const util::StringView &name) const
96 {
97 std::stringstream ss;
98 ss << "Cannot find variable '" << name << "'.";
99 ThrowError(pos, ss.str());
100 }
101
ThrowUnresolvableType(const lexer::SourcePosition & pos,const util::StringView & name) const102 void VarBinder::ThrowUnresolvableType(const lexer::SourcePosition &pos, const util::StringView &name) const
103 {
104 std::stringstream ss;
105 ss << "Cannot find type '" << name << "'.";
106 ThrowError(pos, ss.str());
107 }
108
ThrowTDZ(const lexer::SourcePosition & pos,const util::StringView & name) const109 void VarBinder::ThrowTDZ(const lexer::SourcePosition &pos, const util::StringView &name) const
110 {
111 std::stringstream ss;
112 ss << "Variable '" << name << "' is accessed before it's initialization.";
113 ThrowError(pos, ss.str());
114 }
115
ThrowInvalidCapture(const lexer::SourcePosition & pos,const util::StringView & name) const116 void VarBinder::ThrowInvalidCapture(const lexer::SourcePosition &pos, const util::StringView &name) const
117 {
118 std::stringstream ss;
119 ss << "Cannot capture variable'" << name << "'.";
120 ThrowError(pos, ss.str());
121 }
122
ThrowPrivateFieldMismatch(const lexer::SourcePosition & pos,const util::StringView & name) const123 void VarBinder::ThrowPrivateFieldMismatch(const lexer::SourcePosition &pos, const util::StringView &name) const
124 {
125 std::stringstream ss;
126 ss << "Private field '" << name << "' must be declared in an enclosing class";
127
128 ThrowError(pos, ss.str());
129 }
130
ThrowError(const lexer::SourcePosition & pos,const std::string_view & msg) const131 void VarBinder::ThrowError(const lexer::SourcePosition &pos, const std::string_view &msg) const
132 {
133 lexer::LineIndex index(program_->SourceCode());
134 lexer::SourceLocation loc = index.GetLocation(pos);
135
136 throw Error(ErrorType::SYNTAX, program_->SourceFilePath().Utf8(), msg, loc.line, loc.col);
137 }
138
IdentifierAnalysis()139 void VarBinder::IdentifierAnalysis()
140 {
141 ASSERT(program_->Ast());
142 ASSERT(scope_ == topScope_);
143 ASSERT(varScope_ == topScope_);
144
145 functionScopes_.push_back(topScope_);
146 topScope_->BindName(MAIN);
147 topScope_->BindInternalName(BuildFunctionName(MAIN, 0));
148
149 topScope_->CheckDirectEval(context_);
150
151 ResolveReferences(program_->Ast());
152 AddMandatoryParams();
153 }
154
LookupReference(const util::StringView & name)155 void VarBinder::LookupReference(const util::StringView &name)
156 {
157 auto res = scope_->Find(name);
158 if (res.level == 0) {
159 return;
160 }
161
162 ASSERT(res.variable);
163 res.variable->SetLexical(res.scope);
164 }
165
InstantiateArgumentsImpl(Scope ** scope,Scope * iter,const ir::AstNode * node)166 bool VarBinder::InstantiateArgumentsImpl(Scope **scope, Scope *iter, const ir::AstNode *node)
167 {
168 if (node->AsScriptFunction()->IsArrow()) {
169 return false;
170 }
171 auto *argumentsVariable =
172 (*scope)->AddDecl<ConstDecl, LocalVariable>(Allocator(), FUNCTION_ARGUMENTS, VariableFlags::INITIALIZED);
173 if (iter->IsFunctionParamScope()) {
174 if (argumentsVariable == nullptr) {
175 return true;
176 }
177
178 *scope = iter->AsFunctionParamScope()->GetFunctionScope();
179 (*scope)->InsertBinding(argumentsVariable->Name(), argumentsVariable);
180 }
181
182 (*scope)->AddFlag(ScopeFlags::USE_ARGS);
183 return true;
184 }
185
InstantiateArguments()186 void VarBinder::InstantiateArguments()
187 {
188 auto *iter = scope_;
189 while (true) {
190 Scope *scope = iter->IsFunctionParamScope() ? iter : iter->EnclosingVariableScope();
191
192 const auto *node = scope->Node();
193
194 if (scope->IsLoopScope()) {
195 iter = scope->Parent();
196 continue;
197 }
198
199 if (!node->IsScriptFunction()) {
200 break;
201 }
202
203 if (InstantiateArgumentsImpl(&scope, iter, node)) {
204 break;
205 }
206
207 iter = scope->Parent();
208 }
209 }
210
PropagateDirectEval() const211 void VarBinder::PropagateDirectEval() const
212 {
213 auto *iter = scope_;
214
215 do {
216 VariableScope *scope = iter->IsFunctionParamScope() ? iter->AsFunctionParamScope()->GetFunctionScope()
217 : iter->EnclosingVariableScope();
218
219 scope->AddFlag(ScopeFlags::NO_REG_STORE);
220 iter = iter->Parent();
221 } while (iter != nullptr);
222 }
223
InstantiatePrivateContext(const ir::Identifier * ident) const224 void VarBinder::InstantiatePrivateContext(const ir::Identifier *ident) const
225 {
226 auto *classDef = util::Helpers::GetContainingClassDefinition(ident);
227
228 while (classDef != nullptr) {
229 auto *scope = classDef->Scope();
230 Variable *variable = scope->FindLocal(classDef->PrivateId(), varbinder::ResolveBindingOptions::BINDINGS);
231
232 if (!variable->HasFlag(VariableFlags::INITIALIZED)) {
233 break;
234 }
235
236 if (classDef->HasMatchingPrivateKey(ident->Name())) {
237 variable->SetLexical(scope);
238 return;
239 }
240
241 classDef = util::Helpers::GetContainingClassDefinition(classDef->Parent());
242 }
243
244 ThrowPrivateFieldMismatch(ident->Start(), ident->Name());
245 }
246
LookupIdentReference(ir::Identifier * ident)247 void VarBinder::LookupIdentReference(ir::Identifier *ident)
248 {
249 if (!ident->IsReference()) {
250 return;
251 }
252
253 if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
254 InstantiateArguments();
255 }
256
257 if (ident->IsPrivateIdent()) {
258 InstantiatePrivateContext(ident);
259 return;
260 }
261
262 auto res = scope_->Find(ident->Name(), BindingOptions());
263 if (res.level != 0) {
264 ASSERT(res.variable);
265 res.variable->SetLexical(res.scope);
266 }
267
268 if (res.variable == nullptr) {
269 return;
270 }
271
272 if (res.variable->Declaration()->IsLetOrConstDecl() && !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
273 ident->SetTdz();
274 }
275
276 ident->SetVariable(res.variable);
277 }
278
BuildFunctionName(util::StringView name,uint32_t idx)279 util::StringView VarBinder::BuildFunctionName(util::StringView name, uint32_t idx)
280 {
281 std::stringstream ss;
282 ss << "func_" << name << "_" << std::to_string(idx);
283 util::UString internalName(ss.str(), Allocator());
284
285 return internalName.View();
286 }
287
BuildInternalName(ir::ScriptFunction * scriptFunc)288 bool VarBinder::BuildInternalName(ir::ScriptFunction *scriptFunc)
289 {
290 auto *funcScope = scriptFunc->Scope();
291 auto name = util::Helpers::FunctionName(Allocator(), scriptFunc);
292
293 uint32_t idx = functionScopes_.size();
294 funcScope->BindName(name);
295 funcScope->BindInternalName(BuildFunctionName(name, idx));
296
297 return !scriptFunc->IsOverload();
298 }
299
BuildVarDeclaratorId(ir::AstNode * childNode)300 void VarBinder::BuildVarDeclaratorId(ir::AstNode *childNode)
301 {
302 switch (childNode->Type()) {
303 case ir::AstNodeType::IDENTIFIER: {
304 auto *ident = childNode->AsIdentifier();
305 const auto &name = ident->Name();
306
307 if (util::Helpers::IsGlobalIdentifier(name)) {
308 break;
309 }
310
311 auto *variable = scope_->FindLocal(name, varbinder::ResolveBindingOptions::BINDINGS);
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 AddCompilableFunction(func);
519
520 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
521
522 if (func->Body() != nullptr) {
523 ResolveReference(func->Body());
524 }
525 }
526
VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction * func)527 void VarBinder::VisitScriptFunctionWithPotentialTypeParams(ir::ScriptFunction *func)
528 {
529 if (func->TypeParams() != nullptr) {
530 auto typeParamScopeCtx = LexicalScope<Scope>::Enter(this, func->TypeParams()->Scope());
531 VisitScriptFunction(func);
532 return;
533 }
534
535 VisitScriptFunction(func);
536 }
537
ResolveReference(ir::AstNode * childNode)538 void VarBinder::ResolveReference(ir::AstNode *childNode)
539 {
540 switch (childNode->Type()) {
541 case ir::AstNodeType::IDENTIFIER: {
542 auto *ident = childNode->AsIdentifier();
543
544 LookupIdentReference(ident);
545 ResolveReferences(childNode);
546 break;
547 }
548 case ir::AstNodeType::SUPER_EXPRESSION: {
549 VariableScope *varScope = scope_->EnclosingVariableScope();
550 varScope->AddFlag(ScopeFlags::USE_SUPER);
551 ResolveReferences(childNode);
552 break;
553 }
554 case ir::AstNodeType::SCRIPT_FUNCTION: {
555 VisitScriptFunctionWithPotentialTypeParams(childNode->AsScriptFunction());
556 break;
557 }
558 case ir::AstNodeType::VARIABLE_DECLARATOR: {
559 BuildVarDeclarator(childNode->AsVariableDeclarator());
560 break;
561 }
562 case ir::AstNodeType::CLASS_DEFINITION: {
563 BuildClassDefinition(childNode->AsClassDefinition());
564 break;
565 }
566 case ir::AstNodeType::CLASS_PROPERTY: {
567 BuildClassProperty(childNode->AsClassProperty());
568 break;
569 }
570 case ir::AstNodeType::BLOCK_STATEMENT: {
571 auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsBlockStatement()->Scope());
572
573 ResolveReferences(childNode);
574 break;
575 }
576 case ir::AstNodeType::BLOCK_EXPRESSION: {
577 auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsBlockExpression()->Scope());
578
579 ResolveReferences(childNode);
580 break;
581 }
582 case ir::AstNodeType::SWITCH_STATEMENT: {
583 auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
584
585 ResolveReferences(childNode);
586 break;
587 }
588 case ir::AstNodeType::DO_WHILE_STATEMENT: {
589 auto *doWhileStatement = childNode->AsDoWhileStatement();
590
591 {
592 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
593 ResolveReference(doWhileStatement->Body());
594 }
595
596 ResolveReference(doWhileStatement->Test());
597 break;
598 }
599 case ir::AstNodeType::WHILE_STATEMENT: {
600 auto *whileStatement = childNode->AsWhileStatement();
601 ResolveReference(whileStatement->Test());
602
603 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
604 ResolveReference(whileStatement->Body());
605
606 break;
607 }
608 case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
609 BuildForUpdateLoop(childNode->AsForUpdateStatement());
610 break;
611 }
612 case ir::AstNodeType::FOR_IN_STATEMENT: {
613 auto *forInStmt = childNode->AsForInStatement();
614 BuildForInOfLoop(forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
615
616 break;
617 }
618 case ir::AstNodeType::FOR_OF_STATEMENT: {
619 auto *forOfStmt = childNode->AsForOfStatement();
620 BuildForInOfLoop(forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
621 break;
622 }
623 case ir::AstNodeType::CATCH_CLAUSE: {
624 BuildCatchClause(childNode->AsCatchClause());
625 break;
626 }
627 case ir::AstNodeType::TS_TYPE_ALIAS_DECLARATION: {
628 BuildTypeAliasDeclaration(childNode->AsTSTypeAliasDeclaration());
629 break;
630 }
631 default: {
632 HandleCustomNodes(childNode);
633 break;
634 }
635 }
636 }
637
ResolveReferences(const ir::AstNode * parent)638 void VarBinder::ResolveReferences(const ir::AstNode *parent)
639 {
640 parent->Iterate([this](auto *childNode) { ResolveReference(childNode); });
641 }
642
AddMandatoryParam(const std::string_view & name)643 LocalVariable *VarBinder::AddMandatoryParam(const std::string_view &name)
644 {
645 ASSERT(scope_->IsFunctionParamScope());
646
647 auto *decl = Allocator()->New<ParameterDecl>(name);
648 auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
649
650 auto &funcParams = scope_->AsFunctionParamScope()->Params();
651
652 funcParams.insert(funcParams.begin(), param);
653 scope_->AsFunctionParamScope()->GetFunctionScope()->InsertBinding(decl->Name(), param);
654 scope_->InsertBinding(decl->Name(), param);
655
656 return param;
657 }
658
LookUpMandatoryReferences(const FunctionScope * funcScope,bool needLexicalFuncObj)659 void VarBinder::LookUpMandatoryReferences(const FunctionScope *funcScope, bool needLexicalFuncObj)
660 {
661 LookupReference(MANDATORY_PARAM_NEW_TARGET);
662 LookupReference(MANDATORY_PARAM_THIS);
663
664 if (funcScope->HasFlag(ScopeFlags::USE_ARGS)) {
665 LookupReference(FUNCTION_ARGUMENTS);
666 }
667
668 if (needLexicalFuncObj) {
669 LookupReference(MANDATORY_PARAM_FUNC);
670 }
671 }
672
AddMandatoryParams()673 void VarBinder::AddMandatoryParams()
674 {
675 ASSERT(scope_ == topScope_);
676 ASSERT(!functionScopes_.empty());
677 auto iter = functionScopes_.begin();
678 [[maybe_unused]] auto *funcScope = *iter++;
679
680 ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
681
682 const auto &options = context_->config->options->CompilerOptions();
683 if (options.isDirectEval) {
684 AddMandatoryParams(EVAL_SCRIPT_MANDATORY_PARAMS);
685 topScope_->ParamScope()->Params().back()->SetLexical(topScope_);
686 } else {
687 AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
688 }
689
690 if (options.isFunctionEval) {
691 ASSERT(iter != functionScopes_.end());
692 funcScope = *iter++;
693 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
694 AddMandatoryParams(ARROW_MANDATORY_PARAMS);
695 LookUpMandatoryReferences(funcScope, false);
696 }
697
698 for (; iter != functionScopes_.end(); iter++) {
699 funcScope = *iter;
700 const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
701
702 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
703
704 if (!scriptFunc->IsArrow()) {
705 AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
706 continue;
707 }
708
709 const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
710 bool lexicalFunctionObject {};
711
712 if (ctor != nullptr && util::Helpers::GetClassDefiniton(ctor)->Super() != nullptr &&
713 funcScope->HasFlag(ScopeFlags::USE_SUPER)) {
714 ASSERT(ctor->Scope()->HasFlag(ScopeFlags::INNER_ARROW));
715 ctor->Scope()->AddFlag(ScopeFlags::SET_LEXICAL_FUNCTION);
716 lexicalFunctionObject = true;
717 AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
718 } else {
719 AddMandatoryParams(ARROW_MANDATORY_PARAMS);
720 }
721
722 LookUpMandatoryReferences(funcScope, lexicalFunctionObject);
723 }
724 }
725 } // namespace ark::es2panda::varbinder
726