• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "binder.h"
17 
18 #include "ir/base/annotation.h"
19 #include "ir/base/catchClause.h"
20 #include "ir/base/classDefinition.h"
21 #include "ir/base/property.h"
22 #include "ir/base/scriptFunction.h"
23 #include "ir/base/spreadElement.h"
24 #include "ir/expressions/arrayExpression.h"
25 #include "ir/expressions/assignmentExpression.h"
26 #include "ir/expressions/callExpression.h"
27 #include "ir/expressions/objectExpression.h"
28 #include "ir/expressions/literals/numberLiteral.h"
29 #include "ir/module/exportNamedDeclaration.h"
30 #include "ir/module/exportSpecifier.h"
31 #include "ir/statements/blockStatement.h"
32 #include "ir/statements/classDeclaration.h"
33 #include "ir/statements/doWhileStatement.h"
34 #include "ir/statements/forInStatement.h"
35 #include "ir/statements/forOfStatement.h"
36 #include "ir/statements/forUpdateStatement.h"
37 #include "ir/statements/switchCaseStatement.h"
38 #include "ir/statements/switchStatement.h"
39 #include "ir/statements/variableDeclaration.h"
40 #include "ir/statements/variableDeclarator.h"
41 #include "ir/statements/whileStatement.h"
42 #include "ir/ts/tsClassImplements.h"
43 #include "ir/ts/tsConstructorType.h"
44 #include "ir/ts/tsEnumDeclaration.h"
45 #include "ir/ts/tsFunctionType.h"
46 #include "ir/ts/tsIndexSignature.h"
47 #include "ir/ts/tsMethodSignature.h"
48 #include "ir/ts/tsModuleDeclaration.h"
49 #include "ir/ts/tsSignatureDeclaration.h"
50 #include "ir/ts/tsTypeParameterDeclaration.h"
51 #include "ir/ts/tsTypeParameterInstantiation.h"
52 #include "util/concurrent.h"
53 
54 namespace panda::es2panda::binder {
InitTopScope()55 void Binder::InitTopScope()
56 {
57     if (program_->Kind() == parser::ScriptKind::MODULE) {
58         topScope_ = Allocator()->New<ModuleScope>(Allocator(), program_);
59     } else {
60         topScope_ = Allocator()->New<GlobalScope>(Allocator());
61     }
62 
63     scope_ = topScope_;
64 }
65 
AddParamDecl(const ir::AstNode * param)66 ParameterDecl *Binder::AddParamDecl(const ir::AstNode *param)
67 {
68     ASSERT(scope_->IsFunctionParamScope() || scope_->IsCatchParamScope());
69     auto [decl, node] = static_cast<ParamScope *>(scope_)->AddParamDecl(Allocator(), param);
70 
71     if (!node) {
72         return decl;
73     }
74 
75     ThrowRedeclaration(node->Start(), decl->Name());
76 }
77 
ThrowRedeclaration(const lexer::SourcePosition & pos,const util::StringView & name)78 void Binder::ThrowRedeclaration(const lexer::SourcePosition &pos, const util::StringView &name)
79 {
80     lexer::LineIndex index(program_->SourceCode());
81     lexer::SourceLocation loc = index.GetLocation(pos);
82 
83     std::stringstream ss;
84     ss << "Variable '" << name << "' has already been declared.";
85     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
86 }
87 
ThrowUndeclaredExport(const lexer::SourcePosition & pos,const util::StringView & name)88 void Binder::ThrowUndeclaredExport(const lexer::SourcePosition &pos, const util::StringView &name)
89 {
90     lexer::LineIndex index(program_->SourceCode());
91     lexer::SourceLocation loc = index.GetLocation(pos);
92 
93     std::stringstream ss;
94     ss << "Export name '" << name << "' is not defined.";
95     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
96 }
97 
ThrowInvalidDstrTarget(const lexer::SourcePosition & pos,const util::StringView & name)98 void Binder::ThrowInvalidDstrTarget(const lexer::SourcePosition &pos, const util::StringView &name)
99 {
100     lexer::LineIndex index(program_->SourceCode());
101     lexer::SourceLocation loc = index.GetLocation(pos);
102 
103     std::stringstream ss;
104     ss << "Invalid destructuring assignment target: " << name;
105     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
106 }
107 
ThrowInvalidAnnotationDeclaration(const lexer::SourcePosition & pos,const util::StringView & name)108 void Binder::ThrowInvalidAnnotationDeclaration(const lexer::SourcePosition &pos, const util::StringView &name)
109 {
110     lexer::LineIndex index(program_->SourceCode());
111     lexer::SourceLocation loc = index.GetLocation(pos);
112 
113     std::stringstream ss;
114     ss << "Invalid annotation declaration: " << name;
115     throw Error(ErrorType::SYNTAX, ss.str(), loc.line, loc.col);
116 }
117 
CheckMandatoryArguments(const ir::Identifier * ident)118 void Binder::CheckMandatoryArguments(const ir::Identifier *ident)
119 {
120     const auto *iter = static_cast<const ir::AstNode *>(ident);
121     bool isPatternMember = false;
122     while (iter) {
123         if (iter->IsArrayExpression() || iter->IsArrayPattern()) {
124             isPatternMember = true;
125             break;
126         }
127 
128         if (iter->IsObjectExpression() || iter->IsObjectPattern()) {
129             auto &properties = iter->IsObjectExpression() ? iter->AsObjectExpression()->Properties() :
130                                                             iter->AsObjectPattern()->Properties();
131             isPatternMember = util::Helpers::IsObjectPropertyValue(properties, ident);
132             break;
133         }
134         iter = iter->Parent();
135     }
136 
137     if (!isPatternMember) {
138         return;
139     }
140 
141     auto *patternNode = iter;
142 
143     while (iter) {
144         if (iter->IsAssignmentExpression() || iter->IsVariableDeclarator() || iter->IsForInStatement() ||
145             iter->IsForOfStatement()) {
146             break;
147         }
148 
149         iter = iter->Parent();
150     }
151 
152     if (!iter) {
153         return;
154     }
155 
156     const ir::AstNode *potentialParent = iter;
157 
158     if (iter->IsAssignmentExpression()) {
159         potentialParent = iter->AsAssignmentExpression()->Left();
160     } else if (iter->IsVariableDeclarator()) {
161         potentialParent = iter->AsVariableDeclarator()->Id();
162     } else {
163         potentialParent = iter->IsForInStatement() ? iter->AsForInStatement()->Left() :
164                                                      iter->AsForOfStatement()->Left();
165     }
166 
167     if (!util::Helpers::IsChild(potentialParent, patternNode)) {
168         return;
169     }
170 
171     ThrowInvalidDstrTarget(ident->Start(), ident->Name());
172 }
173 
AssignIndexToModuleVariable()174 void Binder::AssignIndexToModuleVariable()
175 {
176     ASSERT(program_->ModuleRecord());
177     program_->ModuleRecord()->AssignIndexToModuleVariable(topScope_->AsModuleScope());
178 }
179 
IdentifierAnalysis(ResolveBindingFlags flags)180 void Binder::IdentifierAnalysis(ResolveBindingFlags flags)
181 {
182     ASSERT(program_->Ast());
183     ASSERT(scope_ == topScope_);
184 
185     bindingFlags_ = flags;
186     // Bind function main0 first to determine whether a lexical variable is in it or not under hot-reload mode
187     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
188         BuildFunction(topScope_, MAIN_FUNC_NAME);
189         ResolveReferences(program_->Ast());
190     } else if (bindingFlags_ & ResolveBindingFlags::TS_AFTER_TRANSFORM) {
191         // Basically same as js, except of function main0 will not be bound after transform
192         ResolveReferences(program_->Ast());
193         AddMandatoryParams();
194         if (topScope_->IsModuleScope()) {
195             AssignIndexToModuleVariable();
196         }
197     } else if (bindingFlags_ & ResolveBindingFlags::ALL) {
198         BuildFunction(topScope_, MAIN_FUNC_NAME);
199         ResolveReferences(program_->Ast());
200         AddMandatoryParams();
201         if (topScope_->IsModuleScope()) {
202             AssignIndexToModuleVariable();
203         }
204     }
205 }
206 
ValidateExportDecl(const ir::ExportNamedDeclaration * exportDecl)207 void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl)
208 {
209     if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr || exportDecl->IsType()) {
210         return;
211     }
212 
213     ASSERT(topScope_->IsModuleScope());
214     for (auto *it : exportDecl->Specifiers()) {
215         if (it->AsExportSpecifier()->IsType()) {
216             continue;
217         }
218 
219         auto localName = it->AsExportSpecifier()->Local()->Name();
220         if (scope_->IsTSModuleScope()) {
221             auto currentScope = scope_;
222             while (currentScope != nullptr) {
223                 if (currentScope->FindLocal(localName, ResolveBindingOptions::ALL) != nullptr ||
224                     (currentScope->IsTSModuleScope() && (currentScope->InLocalTSBindings(localName) ||
225                     currentScope->AsTSModuleScope()->InExportBindings(localName)))) {
226                     break;
227                 }
228                 currentScope = currentScope->Parent();
229             }
230             if (currentScope != nullptr) {
231                 continue;
232             }
233             ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
234         }
235         ASSERT(topScope_ == scope_);
236         if (scope_->FindLocal(localName) == nullptr) {
237             // The declaration of ts cannot correspond to the variables of ts before transform,
238             // After the transform, they are all js variables. So it can return directly here.
239             if (scope_->InLocalTSBindings(localName) ||
240                 scope_->FindLocal(localName, ResolveBindingOptions::INTERFACES)) {
241                 continue;
242             }
243             ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName);
244         }
245         scope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName);
246     }
247 }
248 
LookupReference(const util::StringView & name)249 void Binder::LookupReference(const util::StringView &name)
250 {
251     ScopeFindResult res = scope_->Find(name);
252     if (res.level == 0) {
253         return;
254     }
255 
256     ASSERT(res.variable);
257     res.variable->SetLexical(res.scope, program_->PatchFixHelper());
258 }
259 
InstantiateArguments()260 void Binder::InstantiateArguments()
261 {
262     auto *iter = scope_;
263     while (true) {
264         Scope *scope = iter->IsFunctionParamScope() ? iter : iter->EnclosingVariableScope();
265         CHECK_NOT_NULL(scope);
266 
267         const auto *node = scope->Node();
268 
269         if (scope->IsLoopScope()) {
270             iter = scope->Parent();
271             continue;
272         }
273 
274         if (!node->IsScriptFunction()) {
275             break;
276         }
277 
278         if (!node->AsScriptFunction()->IsArrow()) {
279             auto *argumentsVariable =
280                 scope->AddDecl<ConstDecl, LocalVariable>(Allocator(), FUNCTION_ARGUMENTS, VariableFlags::INITIALIZED);
281 
282             if (iter->IsFunctionParamScope()) {
283                 if (!argumentsVariable) {
284                     break;
285                 }
286 
287                 scope = iter->AsFunctionParamScope()->GetFunctionScope();
288                 scope->Bindings().insert({argumentsVariable->Name(), argumentsVariable});
289             }
290 
291             scope->AsVariableScope()->AddFlag(VariableScopeFlags::USE_ARGS);
292 
293             break;
294         }
295 
296         iter = scope->Parent();
297     }
298 }
299 
LookupIdentReference(ir::Identifier * ident)300 void Binder::LookupIdentReference(ir::Identifier *ident)
301 {
302     if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
303         InstantiateArguments();
304     }
305 
306     ScopeFindResult res;
307     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
308         ident->SetTSVariables(FindIdentifierTSVariables(ident, scope_, res));
309     } else {
310         if (ident->Parent()->IsTSTypeReference()) {
311             res = scope_->Find(ident->Name(), ResolveBindingOptions::ALL);
312         } else {
313             res = scope_->Find(ident->Name(), ResolveBindingOptions::BINDINGS);
314         }
315     }
316 
317     if (res.variable == nullptr) {
318         return;
319     }
320 
321     if (res.level != 0) {
322         if (!res.variable->Declaration()->IsDeclare() && !ident->Parent()->IsTSTypeReference() &&
323             !ident->Parent()->IsTSTypeQuery() && !(bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM)) {
324             util::Concurrent::ProcessConcurrent(Program()->GetLineIndex(), ident, res, program_);
325             res.variable->SetLexical(res.scope, program_->PatchFixHelper());
326         }
327     }
328 
329     auto decl = res.variable->Declaration();
330     if (decl->IsLetOrConstOrClassDecl() && !decl->HasFlag(DeclarationFlags::NAMESPACE_IMPORT) &&
331         !res.variable->HasFlag(VariableFlags::INITIALIZED)) {
332         ident->SetTdz();
333     }
334     // in release mode, replace const reference with its initialization
335     if (!this->Program()->IsDebug() && decl->IsConstDecl()) {
336         ReplaceConstReferenceWithInitialization(ident, decl);
337     }
338 
339     ident->SetVariable(res.variable);
340 }
341 
StoreAndCheckSpecialFunctionName(std::string & internalNameStr,std::string recordName)342 void Binder::StoreAndCheckSpecialFunctionName(std::string &internalNameStr, std::string recordName)
343 {
344     if (program_->PatchFixHelper()) {
345         if (program_->PatchFixHelper()->IsDumpSymbolTable()) {
346             // anonymous, special-name and duplicate function index started from 1
347             specialFuncNameIndexMap_.insert({internalNameStr, std::to_string(++globalIndexForSpecialFunc_)});
348             return;
349         }
350         if (program_->PatchFixHelper()->IsHotFix()) {
351             // Adding/removing anonymous, special or duplicate functions is supported for hotReload and coldFix mode,
352             // but forbidden in hotFix mode
353             program_->PatchFixHelper()->CheckAndRestoreSpecialFunctionName(++globalIndexForSpecialFunc_,
354                 internalNameStr, recordName);
355             return;
356         }
357         // else: must be coldfix or hotreload mode or coldreload mode
358         ASSERT(program_->PatchFixHelper()->IsColdFix() || program_->PatchFixHelper()->IsHotReload() ||
359                program_->PatchFixHelper()->IsColdReload());
360     }
361 }
362 
BuildFunction(FunctionScope * funcScope,util::StringView name,const ir::ScriptFunction * func)363 void Binder::BuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func)
364 {
365     if (funcScope->InFunctionScopes()) {
366         return;
367     }
368     functionScopes_.push_back(funcScope);
369     funcScope->SetInFunctionScopes();
370     if (!util::Helpers::IsDefaultApiVersion(Program()->TargetApiVersion(), Program()->GetTargetApiSubVersion())) {
371         funcScope->SetSelfScopeName(name);
372         auto recordName = program_->FormatedRecordName().Mutf8();
373         funcScope->BindNameWithScopeInfo(name, util::UString(recordName, Allocator()).View());
374         if (func && (name == ANONYMOUS_FUNC_NAME)) {
375             anonymousFunctionNames_[func] = util::UString(funcScope->InternalName().Mutf8(), Allocator()).View();
376         }
377     } else {
378         LegacyBuildFunction(funcScope, name, func);
379     }
380 }
381 
LegacyBuildFunction(FunctionScope * funcScope,util::StringView name,const ir::ScriptFunction * func)382 void Binder::LegacyBuildFunction(FunctionScope *funcScope, util::StringView name, const ir::ScriptFunction *func)
383 {
384     bool funcNameWithoutDot = (name.Find(".") == std::string::npos);
385     bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos);
386     if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot &&
387         funcNameWithoutBackslash && !functionNames_.count(name)) {
388         // function with normal name, and hasn't been recorded
389         auto internalName = std::string(program_->FormatedRecordName()) + std::string(name);
390         functionNames_.insert(name);
391         funcScope->BindName(name, util::UString(internalName, Allocator()).View());
392         return;
393     }
394 
395     std::stringstream ss;
396     ss << std::string(program_->FormatedRecordName());
397 
398     ASSERT(func != nullptr);
399 
400     // For anonymous, special-name and duplicate function, get its source and name, make hash code,
401     // and make #hash_duplicateHashTime#name as its name;
402     auto funcContentNameStr = func->SourceCode(this).Mutf8() + name.Mutf8();
403     ss << ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER << util::Helpers::GetHashString(funcContentNameStr);
404 
405     auto res = functionHashNames_.find(funcContentNameStr);
406     if (res != functionHashNames_.end()) {
407         ss << "_" << res->second++;
408     } else {
409         functionHashNames_.insert({funcContentNameStr, 1});
410     }
411     ss << ANONYMOUS_SPECIAL_DUPLICATE_FUNCTION_SPECIFIER;
412 
413     if (name == ANONYMOUS_FUNC_NAME) {
414         anonymousFunctionNames_[func] = util::UString(ss.str(), Allocator()).View();
415     }
416     if (funcNameWithoutDot && funcNameWithoutBackslash) {
417         ss << name;
418     }
419     std::string internalNameStr = ss.str();
420     StoreAndCheckSpecialFunctionName(internalNameStr, program_->RecordName().Mutf8());
421     funcScope->BindName(name, util::UString(internalNameStr, Allocator()).View());
422 }
423 
BuildScriptFunction(Scope * outerScope,const ir::ScriptFunction * scriptFunc)424 void Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *scriptFunc)
425 {
426     if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) {
427         return;
428     }
429 
430     auto *funcScope = scriptFunc->Scope();
431     funcScope->ParamScope()->SetParent(outerScope);
432 
433     if (scriptFunc->IsArrow()) {
434         const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
435         if (ctor) {
436             ctor->Scope()->AddFlag(VariableScopeFlags::INNER_ARROW);
437         }
438     }
439 
440     ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope() || scope_->IsTSEnumScope());
441     BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(Allocator(), scriptFunc), scriptFunc);
442 }
443 
BuildVarDeclaratorId(const ir::AstNode * parent,ir::AstNode * childNode)444 void Binder::BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode)
445 {
446     childNode->SetParent(parent);
447 
448     switch (childNode->Type()) {
449         case ir::AstNodeType::IDENTIFIER: {
450             auto *ident = childNode->AsIdentifier();
451             const auto &name = ident->Name();
452             if (name.Is(FUNCTION_ARGUMENTS)) {
453                 CheckMandatoryArguments(ident);
454             }
455 
456             if (util::Helpers::IsGlobalIdentifier(name)) {
457                 break;
458             }
459 
460             auto *variable = scope_->FindLocal(name, ResolveBindingOptions::BINDINGS);
461 
462             if (Program()->Extension() == ScriptExtension::TS) {
463                 ident->SetVariable(variable);
464                 BuildTSSignatureDeclarationBaseParamsWithParent(ident, ident->TypeAnnotation());
465             }
466 
467             CHECK_NOT_NULL(variable);
468             variable->AddFlag(VariableFlags::INITIALIZED);
469             break;
470         }
471         case ir::AstNodeType::OBJECT_PATTERN: {
472             auto *objPattern = childNode->AsObjectPattern();
473 
474             for (auto *prop : objPattern->Properties()) {
475                 BuildVarDeclaratorId(childNode, prop);
476             }
477 
478             BuildTSSignatureDeclarationBaseParamsWithParent(objPattern, objPattern->TypeAnnotation());
479             break;
480         }
481         case ir::AstNodeType::ARRAY_PATTERN: {
482             auto *arrayPattern = childNode->AsArrayPattern();
483 
484             for (auto *element : childNode->AsArrayPattern()->Elements()) {
485                 BuildVarDeclaratorId(childNode, element);
486             }
487 
488             BuildTSSignatureDeclarationBaseParamsWithParent(arrayPattern, arrayPattern->TypeAnnotation());
489             break;
490         }
491         case ir::AstNodeType::ASSIGNMENT_PATTERN: {
492             ResolveReference(childNode, childNode->AsAssignmentPattern()->Right());
493             BuildVarDeclaratorId(childNode, childNode->AsAssignmentPattern()->Left());
494             break;
495         }
496         case ir::AstNodeType::PROPERTY: {
497             ResolveReference(childNode, childNode->AsProperty()->Key());
498             BuildVarDeclaratorId(childNode, childNode->AsProperty()->Value());
499             break;
500         }
501         case ir::AstNodeType::REST_ELEMENT: {
502             BuildVarDeclaratorId(childNode, childNode->AsRestElement()->Argument());
503             break;
504         }
505         default:
506             break;
507     }
508 }
509 
BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode * parent,ir::AstNode * typeNode)510 void Binder::BuildTSSignatureDeclarationBaseParamsWithParent(const ir::AstNode *parent, ir::AstNode *typeNode)
511 {
512     if (!typeNode) {
513         return;
514     }
515     typeNode->SetParent(parent);
516     BuildTSSignatureDeclarationBaseParams(typeNode);
517 }
518 
BuildTSSignatureDeclarationBaseParams(const ir::AstNode * typeNode)519 void Binder::BuildTSSignatureDeclarationBaseParams(const ir::AstNode *typeNode)
520 {
521     ASSERT(typeNode != nullptr);
522 
523     Scope *scope = nullptr;
524 
525     switch (typeNode->Type()) {
526         case ir::AstNodeType::TS_FUNCTION_TYPE: {
527             scope = typeNode->AsTSFunctionType()->Scope();
528             break;
529         }
530         case ir::AstNodeType::TS_CONSTRUCTOR_TYPE: {
531             scope = typeNode->AsTSConstructorType()->Scope();
532             break;
533         }
534         case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
535             scope = typeNode->AsTSSignatureDeclaration()->Scope();
536             break;
537         }
538         case ir::AstNodeType::TS_METHOD_SIGNATURE: {
539             scope = typeNode->AsTSMethodSignature()->Scope();
540             break;
541         }
542         default: {
543             ResolveReferences(typeNode);
544             return;
545         }
546     }
547 
548     ASSERT(scope && scope->IsFunctionParamScope());
549 
550     auto scopeCtx = LexicalScope<FunctionParamScope>::Enter(this, scope->AsFunctionParamScope());
551     ResolveReferences(typeNode);
552 }
553 
BuildVarDeclarator(ir::VariableDeclarator * varDecl)554 void Binder::BuildVarDeclarator(ir::VariableDeclarator *varDecl)
555 {
556     if (varDecl->Parent()->AsVariableDeclaration()->Kind() == ir::VariableDeclaration::VariableDeclarationKind::VAR) {
557         ResolveReferences(varDecl);
558         return;
559     }
560 
561     if (varDecl->Init()) {
562         ResolveReference(varDecl, varDecl->Init());
563     }
564 
565     BuildVarDeclaratorId(varDecl, varDecl->Id());
566 }
567 
ProcessNodeInStaticInitializer(ir::ClassDefinition * classDef)568 void Binder::ProcessNodeInStaticInitializer(ir::ClassDefinition *classDef)
569 {
570     if (classDef->NeedStaticInitializer()) {
571         ResolveReference(classDef, classDef->StaticInitializer());
572     }
573 
574     for (auto *stmt : classDef->Body()) {
575         if (stmt->IsClassStaticBlock() || (stmt->IsClassProperty() && stmt->AsClassProperty()->IsStatic())) {
576             ResolveReference(classDef, stmt);
577         }
578     }
579 }
580 
BuildClassDefinition(ir::ClassDefinition * classDef)581 void Binder::BuildClassDefinition(ir::ClassDefinition *classDef)
582 {
583     if (classDef->Parent()->IsClassDeclaration()) {
584         util::StringView className = classDef->GetName();
585         ASSERT(!className.Empty());
586         ScopeFindResult res = scope_->Find(className);
587 
588         ASSERT(res.variable && (res.variable->Declaration()->IsClassDecl() ||
589                (res.variable->Declaration()->IsFunctionDecl() &&
590                res.variable->Declaration()->AsFunctionDecl()->GetDeclClass() != nullptr)));
591         res.variable->AddFlag(VariableFlags::INITIALIZED);
592     }
593 
594     auto scopeCtx = LexicalScope<ClassScope>::Enter(this, classDef->Scope());
595 
596     if (classDef->TypeParams()) {
597         ResolveReference(classDef, classDef->TypeParams());
598     }
599 
600     if (classDef->Super()) {
601         ResolveReference(classDef, classDef->Super());
602     }
603 
604     if (classDef->SuperTypeParams()) {
605         ResolveReference(classDef, classDef->SuperTypeParams());
606     }
607 
608     for (auto *iter : classDef->Implements()) {
609         ResolveReference(classDef, iter);
610     }
611 
612     // new class features in ecma2022 are only supported for api11 and above
613     if (Program()->TargetApiVersion() > 10 && !(bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM)) {
614         classDef->BuildClassEnvironment(program_->UseDefineSemantic());
615     }
616 
617     if (classDef->Ident()) {
618         ScopeFindResult res = scope_->Find(classDef->Ident()->Name());
619 
620         ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
621         res.variable->AddFlag(VariableFlags::INITIALIZED);
622 
623         classDef->Ident()->SetParent(classDef);
624     }
625     util::SaveValue<bool> saveInSendableClass {inSendableClass_};
626 
627     // Static initializer in sendable class should not be marked as sendable.
628     // By processing static initializer before constructor, in which class is marked sendable,
629     // the static initializer and functions inside it will not be marked as sendable.
630     ProcessNodeInStaticInitializer(classDef);
631 
632     if (!(classDef->Parent()->IsClassDeclaration() && classDef->Parent()->AsClassDeclaration()->IsAnnotationDecl())) {
633         ResolveReference(classDef, classDef->Ctor());
634     }
635 
636     if (classDef->NeedInstanceInitializer()) {
637         ResolveReference(classDef, classDef->InstanceInitializer());
638     }
639 
640     for (auto *stmt : classDef->Body()) {
641         if (!stmt->IsClassStaticBlock() && !(stmt->IsClassProperty() && stmt->AsClassProperty()->IsStatic())) {
642             ResolveReference(classDef, stmt);
643         }
644     }
645 
646     for (auto *iter : classDef->IndexSignatures()) {
647         ResolveReference(classDef, iter);
648     }
649 }
650 
BuildForUpdateLoop(ir::ForUpdateStatement * forUpdateStmt)651 void Binder::BuildForUpdateLoop(ir::ForUpdateStatement *forUpdateStmt)
652 {
653     auto *loopScope = forUpdateStmt->Scope();
654 
655     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
656 
657     if (forUpdateStmt->Init()) {
658         ResolveReference(forUpdateStmt, forUpdateStmt->Init());
659     }
660 
661     if (forUpdateStmt->Update()) {
662         ResolveReference(forUpdateStmt, forUpdateStmt->Update());
663     }
664 
665     if (forUpdateStmt->Test()) {
666         ResolveReference(forUpdateStmt, forUpdateStmt->Test());
667     }
668 
669     ResolveReference(forUpdateStmt, forUpdateStmt->Body());
670 
671     loopCtx.GetScope()->InitVariable();
672 }
673 
BuildForInOfLoop(const ir::Statement * parent,binder::LoopScope * loopScope,ir::AstNode * left,ir::Expression * right,ir::Statement * body)674 void Binder::BuildForInOfLoop(const ir::Statement *parent, binder::LoopScope *loopScope, ir::AstNode *left,
675                               ir::Expression *right, ir::Statement *body)
676 {
677     auto loopCtx = LexicalScope<LoopScope>::Enter(this, loopScope);
678 
679     ResolveReference(parent, right);
680     ResolveReference(parent, left);
681 
682     ResolveReference(parent, body);
683     loopCtx.GetScope()->InitVariable();
684 }
685 
BuildCatchClause(ir::CatchClause * catchClauseStmt)686 void Binder::BuildCatchClause(ir::CatchClause *catchClauseStmt)
687 {
688     if (catchClauseStmt->Param()) {
689         auto paramScopeCtx = LexicalScope<CatchParamScope>::Enter(this, catchClauseStmt->Scope()->ParamScope());
690         ResolveReference(catchClauseStmt, catchClauseStmt->Param());
691     }
692 
693     auto scopeCtx = LexicalScope<CatchScope>::Enter(this, catchClauseStmt->Scope());
694     ResolveReference(catchClauseStmt, catchClauseStmt->Body());
695 }
696 
ResolveReference(const ir::AstNode * parent,ir::AstNode * childNode)697 void Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode)
698 {
699     childNode->SetParent(parent);
700 
701     ClassTdz classTdz(parent, childNode, scope_);
702 
703     switch (childNode->Type()) {
704         case ir::AstNodeType::IDENTIFIER: {
705             auto *ident = childNode->AsIdentifier();
706 
707             if (ident->Name().Is(FUNCTION_ARGUMENTS)) {
708                 CheckMandatoryArguments(ident);
709             }
710 
711             if (ident->IsReference()) {
712                 LookupIdentReference(ident);
713             }
714 
715             /* During ts to js transformation, a non-empty namespace in ts file will be transformed
716                into a anonymous function while empty namespace will be removed. So the name for the
717                namespace need to be stored before the transformation.*/
718             if (scope_->Type() == ScopeType::TSMODULE) {
719                 scope_->SetSelfScopeName(ident->Name());
720             }
721 
722             ResolveReferences(childNode);
723             break;
724         }
725         case ir::AstNodeType::ANNOTATION: {
726             auto *annotation = childNode->AsAnnotation();
727             std::string annoName{annotation->Name()};
728             ScopeFindResult res = scope_->Find(annotation->Name(), bindingOptions_);
729             if (res.variable != nullptr) {
730                 if (res.variable->Declaration()->Node()->IsImportSpecifier()) {
731                     annotation->SetIsImported();
732                 } else if (!res.variable->Declaration()->Node()->IsClassDefinition()) {
733                     ThrowInvalidAnnotationDeclaration(annotation->Start(), annotation->Name());
734                 }
735             } else if (annoName.find_first_of(".") != std::string::npos) {
736                 auto importName = annoName.substr(0, annoName.find_first_of("."));
737                 ScopeFindResult res = scope_->Find(util::StringView(importName), bindingOptions_);
738                 if (res.variable != nullptr && res.variable->Declaration()->Node()->IsImportNamespaceSpecifier()) {
739                     annotation->SetIsImported();
740                 } else {
741                     ThrowInvalidAnnotationDeclaration(annotation->Start(), annotation->Name());
742                 }
743             } else {
744                 ThrowInvalidAnnotationDeclaration(annotation->Start(), annotation->Name());
745             }
746             ResolveReferences(childNode);
747             break;
748         }
749         case ir::AstNodeType::PRIVATE_IDENTIFIER: {
750             if (Program()->Extension() == ScriptExtension::JS) {
751                 CheckPrivateDeclaration(childNode->AsPrivateIdentifier());
752             } else if (Program()->Extension() == ScriptExtension::TS &&
753                        bindingFlags_ == ResolveBindingFlags::TS_AFTER_TRANSFORM) {
754                 CheckPrivateDeclaration(childNode->AsPrivateIdentifier());
755             }
756             break;
757         }
758         case ir::AstNodeType::SUPER_EXPRESSION: {
759             VariableScope *varScope = scope_->EnclosingVariableScope();
760             CHECK_NOT_NULL(varScope);
761             varScope->AddFlag(VariableScopeFlags::USE_SUPER);
762 
763             ResolveReferences(childNode);
764             break;
765         }
766         case ir::AstNodeType::SCRIPT_FUNCTION: {
767             util::SaveValue<bool> saveInSendableFunction {inSendableFunction_};
768             auto *scriptFunc = childNode->AsScriptFunction();
769             if (inSendableClass_ || inSendableFunction_) {
770                 scriptFunc->SetInSendable();
771             }
772             bool enableSendableClass = program_->TargetApiVersion() >=
773                 util::Helpers::SENDABLE_CLASS_MIN_SUPPORTED_API_VERSION;
774             util::Helpers::ScanDirectives(const_cast<ir::ScriptFunction *>(scriptFunc), Program()->GetLineIndex(),
775                 enableSendableClass,
776                 !util::Helpers::IsDefaultApiVersion(program_->TargetApiVersion(), program_->GetTargetApiSubVersion()));
777 
778             if (scriptFunc->IsConstructor() && util::Helpers::GetClassDefiniton(scriptFunc)->IsSendable()) {
779                 scriptFunc->SetInSendable();
780                 inSendableClass_ = true;
781             } else if (scriptFunc->IsSendable()) {
782                 scriptFunc->SetInSendable();
783                 inSendableFunction_ = true;
784             }
785 
786             auto *funcScope = scriptFunc->Scope();
787 
788             auto *outerScope = scope_;
789 
790             if (scriptFunc->Id() != nullptr) {
791                 scriptFunc->Id()->SetParent(scriptFunc);
792             }
793 
794             {
795                 auto paramScopeCtx = LexicalScope<FunctionParamScope>::Enter(this, funcScope->ParamScope());
796 
797                 if (Program()->Extension() == ScriptExtension::TS) {
798                     if (scriptFunc->TypeParams() != nullptr) {
799                         ResolveReference(scriptFunc, scriptFunc->TypeParams());
800                     }
801                     if (scriptFunc->ThisParams() != nullptr) {
802                         ResolveReference(scriptFunc, scriptFunc->ThisParams());
803                     }
804                 }
805 
806                 for (auto *param : scriptFunc->Params()) {
807                     ResolveReference(scriptFunc, param);
808                 }
809             }
810 
811             if (Program()->Extension() == ScriptExtension::TS) {
812                 if (scriptFunc->ReturnTypeAnnotation()) {
813                     ResolveReference(scriptFunc, scriptFunc->ReturnTypeAnnotation());
814                 }
815 
816                 if (scriptFunc->IsOverload() || scriptFunc->Declare()) {
817                     break;
818                 }
819             }
820 
821             auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
822 
823             BuildScriptFunction(outerScope, scriptFunc);
824 
825             ResolveReference(scriptFunc, scriptFunc->Body());
826             break;
827         }
828         case ir::AstNodeType::VARIABLE_DECLARATOR: {
829             BuildVarDeclarator(childNode->AsVariableDeclarator());
830 
831             break;
832         }
833         case ir::AstNodeType::CLASS_DEFINITION: {
834             auto *classScope = childNode->AsClassDefinition()->Scope();
835             classScope->SetParent(scope_);
836             BuildClassDefinition(childNode->AsClassDefinition());
837 
838             break;
839         }
840         case ir::AstNodeType::CLASS_PROPERTY: {
841             /* for ts tranformer cases, all class properties are implemented by transformer in api10 and
842              * only public instance class properties are implemented by transformer in api11*/
843             auto *prop = childNode->AsClassProperty();
844             if (Program()->Extension() == ScriptExtension::TS && (Program()->TargetApiVersion() < 11 ||
845                 (!prop->IsStatic() && !prop->IsPrivate()))) {
846                 const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(prop);
847                 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, ctor->Scope());
848                 ResolveReferences(childNode);
849                 break;
850             }
851 
852             ResolveReference(prop, prop->Key());
853             if (prop->TypeAnnotation() != nullptr) {
854                 ResolveReference(prop, prop->TypeAnnotation());
855             }
856             if (prop->Value() != nullptr) {
857                 ASSERT(parent->IsClassDefinition());
858                 const auto *classDef = parent->AsClassDefinition();
859                 const ir::MethodDefinition *method = prop->IsStatic() ? classDef->StaticInitializer() :
860                                                      classDef->InstanceInitializer();
861                 auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, method->Function()->Scope());
862                 ResolveReference(prop, prop->Value());
863             }
864             break;
865         }
866         case ir::AstNodeType::BLOCK_STATEMENT: {
867             auto scope = childNode->AsBlockStatement()->Scope();
868             auto scopeCtx = scope != nullptr ?
869                 LexicalScope<Scope>::Enter(this, scope) :
870                 LexicalScope<Scope>::Enter(this, GetScope());
871 
872             ResolveReferences(childNode);
873             break;
874         }
875         case ir::AstNodeType::SWITCH_STATEMENT: {
876             auto *switchStatement = childNode->AsSwitchStatement();
877             ResolveReference(switchStatement, switchStatement->Discriminant());
878 
879             auto scopeCtx = LexicalScope<LocalScope>::Enter(this, childNode->AsSwitchStatement()->Scope());
880             for (auto *it : switchStatement->Cases()) {
881                 ResolveReference(switchStatement, it);
882             }
883             break;
884         }
885         case ir::AstNodeType::DO_WHILE_STATEMENT: {
886             auto *doWhileStatement = childNode->AsDoWhileStatement();
887 
888             {
889                 auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, doWhileStatement->Scope());
890                 ResolveReference(doWhileStatement, doWhileStatement->Body());
891                 loopScopeCtx.GetScope()->InitVariable();
892             }
893 
894             ResolveReference(doWhileStatement, doWhileStatement->Test());
895             break;
896         }
897         case ir::AstNodeType::WHILE_STATEMENT: {
898             auto *whileStatement = childNode->AsWhileStatement();
899             ResolveReference(whileStatement, whileStatement->Test());
900 
901             auto loopScopeCtx = LexicalScope<LoopScope>::Enter(this, whileStatement->Scope());
902             ResolveReference(whileStatement, whileStatement->Body());
903             loopScopeCtx.GetScope()->InitVariable();
904             break;
905         }
906         case ir::AstNodeType::FOR_UPDATE_STATEMENT: {
907             BuildForUpdateLoop(childNode->AsForUpdateStatement());
908             break;
909         }
910         case ir::AstNodeType::FOR_IN_STATEMENT: {
911             auto *forInStmt = childNode->AsForInStatement();
912             BuildForInOfLoop(forInStmt, forInStmt->Scope(), forInStmt->Left(), forInStmt->Right(), forInStmt->Body());
913 
914             break;
915         }
916         case ir::AstNodeType::FOR_OF_STATEMENT: {
917             auto *forOfStmt = childNode->AsForOfStatement();
918             BuildForInOfLoop(forOfStmt, forOfStmt->Scope(), forOfStmt->Left(), forOfStmt->Right(), forOfStmt->Body());
919             break;
920         }
921         case ir::AstNodeType::CATCH_CLAUSE: {
922             BuildCatchClause(childNode->AsCatchClause());
923             break;
924         }
925         case ir::AstNodeType::EXPORT_NAMED_DECLARATION: {
926             ValidateExportDecl(childNode->AsExportNamedDeclaration());
927 
928             ResolveReferences(childNode);
929             break;
930         }
931         // TypeScript specific part
932         case ir::AstNodeType::TS_FUNCTION_TYPE:
933         case ir::AstNodeType::TS_CONSTRUCTOR_TYPE:
934         case ir::AstNodeType::TS_METHOD_SIGNATURE:
935         case ir::AstNodeType::TS_SIGNATURE_DECLARATION: {
936             BuildTSSignatureDeclarationBaseParams(childNode);
937             break;
938         }
939         case ir::AstNodeType::TS_MODULE_DECLARATION: {
940             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSModuleDeclaration()->Scope());
941             ResolveReferences(childNode);
942             break;
943         }
944         case ir::AstNodeType::TS_ENUM_DECLARATION: {
945             auto scopeCtx = LexicalScope<Scope>::Enter(this, childNode->AsTSEnumDeclaration()->Scope());
946             ResolveReferences(childNode);
947             break;
948         }
949         default: {
950             ResolveReferences(childNode);
951             break;
952         }
953     }
954 }
ResolveReferences(const ir::AstNode * parent)955 void Binder::ResolveReferences(const ir::AstNode *parent)
956 {
957     parent->Iterate([this, parent](auto *childNode) { ResolveReference(parent, childNode); });
958 }
959 
AddMandatoryParam(const std::string_view & name)960 void Binder::AddMandatoryParam(const std::string_view &name)
961 {
962     ASSERT(scope_->IsFunctionVariableScope());
963 
964     auto *decl = Allocator()->New<ParameterDecl>(name);
965     CHECK_NOT_NULL(decl);
966     auto *param = Allocator()->New<LocalVariable>(decl, VariableFlags::VAR);
967     CHECK_NOT_NULL(param);
968 
969     auto *paramScope = scope_->AsFunctionVariableScope()->ParamScope();
970     CHECK_NOT_NULL(paramScope);
971 
972     auto &funcParams = paramScope->Params();
973     funcParams.insert(funcParams.begin(), param);
974     scope_->AsFunctionVariableScope()->ParamScope()->Bindings().insert({decl->Name(), param});
975     scope_->AsFunctionVariableScope()->Bindings().insert({decl->Name(), param});
976 }
977 
AddMandatoryParams()978 void Binder::AddMandatoryParams()
979 {
980     ASSERT(scope_ == topScope_);
981     ASSERT(!functionScopes_.empty());
982     auto iter = functionScopes_.begin();
983     [[maybe_unused]] auto *funcScope = *iter++;
984 
985     ASSERT(funcScope->IsGlobalScope() || funcScope->IsModuleScope());
986 
987     if (program_->Kind() == parser::ScriptKind::COMMONJS) {
988         AddMandatoryParams(CJS_MAINFUNC_MANDATORY_PARAMS);
989     } else {
990         AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
991     }
992 
993     for (; iter != functionScopes_.end(); iter++) {
994         funcScope = *iter;
995         const auto *scriptFunc = funcScope->Node()->AsScriptFunction();
996 
997         auto scopeCtx = LexicalScope<FunctionScope>::Enter(this, funcScope);
998 
999         if (!scriptFunc->IsArrow()) {
1000             AddMandatoryParams(FUNCTION_MANDATORY_PARAMS);
1001             continue;
1002         }
1003 
1004         const ir::ScriptFunction *ctor = util::Helpers::GetContainingConstructor(scriptFunc);
1005         bool lexicalFunctionObject {};
1006 
1007         if (ctor && util::Helpers::GetClassDefiniton(ctor)->Super() &&
1008             funcScope->HasFlag(VariableScopeFlags::USE_SUPER)) {
1009             ASSERT(ctor->Scope()->HasFlag(VariableScopeFlags::INNER_ARROW));
1010             ctor->Scope()->AddFlag(VariableScopeFlags::SET_LEXICAL_FUNCTION);
1011             lexicalFunctionObject = true;
1012             AddMandatoryParams(CTOR_ARROW_MANDATORY_PARAMS);
1013         } else {
1014             AddMandatoryParams(ARROW_MANDATORY_PARAMS);
1015         }
1016 
1017         LookupReference(MANDATORY_PARAM_NEW_TARGET);
1018         LookupReference(MANDATORY_PARAM_THIS);
1019 
1020         if (funcScope->HasFlag(VariableScopeFlags::USE_ARGS)) {
1021             LookupReference(FUNCTION_ARGUMENTS);
1022         }
1023 
1024         if (lexicalFunctionObject) {
1025             LookupReference(MANDATORY_PARAM_FUNC);
1026         }
1027     }
1028 }
1029 
AddDeclarationName(const util::StringView & name,DeclType type)1030 void Binder::AddDeclarationName(const util::StringView &name, DeclType type)
1031 {
1032     if (extension_ != ScriptExtension::TS) {
1033         return;
1034     }
1035     variableNames_.insert(name);
1036 
1037     if (type == DeclType::ENUM) {
1038         return;
1039     }
1040     auto *scope = GetScope();
1041     while (scope != nullptr) {
1042         if (scope->IsTSModuleScope()) {
1043             scope->AsTSModuleScope()->AddDeclarationName(name);
1044         }
1045         if (scope->IsTSEnumScope()) {
1046             scope->AsTSEnumScope()->AddDeclarationName(name);
1047         }
1048         scope = scope->Parent();
1049     }
1050 }
1051 
HasVariableName(const util::StringView & name) const1052 bool Binder::HasVariableName(const util::StringView &name) const
1053 {
1054     return variableNames_.find(name) != variableNames_.end();
1055 }
1056 
FindIdentifierTSVariables(const ir::Identifier * identifier,Scope * scope,ScopeFindResult & res)1057 std::vector<Variable *> Binder::FindIdentifierTSVariables(const ir::Identifier *identifier, Scope *scope,
1058     ScopeFindResult &res)
1059 {
1060     const auto &name = identifier->Name();
1061     std::vector<binder::Variable *> findRes;
1062 
1063     auto currentScope = scope;
1064     while (currentScope != nullptr) {
1065         // Find ts variables
1066         auto fn = [&findRes](Variable *variable) {
1067             if (variable != nullptr) {
1068                 findRes.emplace_back(variable);
1069             }
1070         };
1071 
1072         fn(currentScope->FindLocalTSVariable<binder::TSBindingType::NAMESPACE>(name));
1073         fn(currentScope->FindLocalTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
1074         fn(currentScope->FindLocalTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
1075         if (currentScope->IsTSModuleScope()) {
1076             fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::NAMESPACE>(name));
1077             fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::ENUMLITERAL>(name));
1078             fn(currentScope->AsTSModuleScope()->FindExportTSVariable<binder::TSBindingType::IMPORT_EQUALS>(name));
1079         }
1080 
1081         // Find js variable
1082         if (currentScope->FindLocal(name, bindingOptions_) != nullptr) {
1083             res = scope->Find(name, bindingOptions_);
1084             break;
1085         }
1086 
1087         if (!findRes.empty()) {
1088             break;
1089         }
1090 
1091         currentScope = currentScope->Parent();
1092     }
1093 
1094     return findRes;
1095 }
1096 
ReplaceConstReferenceWithInitialization(const ir::Identifier * ident,const Decl * decl)1097 void Binder::ReplaceConstReferenceWithInitialization(const ir::Identifier *ident, const Decl *decl)
1098 {
1099     bool isValidAssignmentExpr = ident->Parent()->IsAssignmentExpression() &&
1100         ident->Parent()->AsAssignmentExpression()->Right() == ident;
1101     bool isBinaryExpr = ident->Parent()->IsBinaryExpression();
1102     bool isVariableDecl = ident->Parent()->IsVariableDeclarator() &&
1103         ident->Parent()->AsVariableDeclarator()->Init() == ident;
1104     if (!isValidAssignmentExpr && !isBinaryExpr && !isVariableDecl) {
1105         return;
1106     }
1107 
1108     if (decl->Node() == nullptr || decl->Node()->Parent() == nullptr ||
1109         !decl->Node()->Parent()->IsVariableDeclarator()) {
1110         return;
1111     }
1112 
1113     const ir::AstNode *initialization = static_cast<const ir::AstNode *>(
1114         decl->Node()->Parent()->AsVariableDeclarator()->Init());
1115     if (initialization == nullptr || !initialization->IsNumberLiteral()) {
1116         return;
1117     }
1118 
1119     auto newNode = Allocator()->New<ir::NumberLiteral>(initialization->AsNumberLiteral()->Number());
1120     if (newNode == nullptr) {
1121         throw Error(ErrorType::GENERIC, "Unsuccessful allocation during replacing const reference node");
1122     }
1123     // Make sure the new node get the correct line number
1124     // Column number may be incorrect, but it doesn't matter in release mode
1125     newNode->SetRange(ident->Range());
1126 
1127     auto *parentNode = const_cast<panda::es2panda::ir::AstNode *>(ident->Parent());
1128     // update the reference node with initialization node
1129     parentNode->UpdateSelf([=](auto *childNode) {
1130             if (childNode == ident) {
1131                 return static_cast<ir::AstNode *>(newNode);
1132             }
1133             return childNode;
1134         }, this);
1135 }
1136 
CheckPrivateDeclaration(const ir::PrivateIdentifier * privateIdent)1137 void Binder::CheckPrivateDeclaration(const ir::PrivateIdentifier *privateIdent)
1138 {
1139     auto name = privateIdent->Name();
1140     auto scope = scope_;
1141     while (scope != nullptr) {
1142         if (scope->Type() == ScopeType::CLASS) {
1143             const auto *classScope = scope->AsClassScope();
1144             if (classScope->HasPrivateName(name)) {
1145                 return;
1146             }
1147         }
1148         scope = scope->Parent();
1149     }
1150 
1151     auto pos = privateIdent->Start();
1152     lexer::LineIndex index(program_->SourceCode());
1153     lexer::SourceLocation loc = index.GetLocation(pos);
1154 
1155     throw Error{ErrorType::SYNTAX, "Use private property before declaration", loc.line, loc.col};
1156 }
1157 
ClassTdz(const ir::AstNode * parent,const ir::AstNode * childNode,Scope * scope)1158 ClassTdz::ClassTdz(const ir::AstNode *parent, const ir::AstNode *childNode, Scope *scope)
1159 {
1160     /* In ES2022, class element name's evaluation is before class's initialization.
1161      * So a computed property name can not access class object which leads to a reference error.
1162      * For example:
1163      * class A {
1164      *   [A]
1165      * }
1166      */
1167     bool isClassTdz = (parent->IsClassProperty() && childNode == parent->AsClassProperty()->Key()) ||
1168         (parent->IsMethodDefinition() && childNode == parent->AsMethodDefinition()->Key());
1169     if (!isClassTdz) {
1170         return;
1171     }
1172 
1173     ASSERT(parent->Parent()->IsClassDefinition());
1174     auto classDef = parent->Parent()->AsClassDefinition();
1175     if (!classDef->Ident()) {
1176         return;
1177     }
1178 
1179     ScopeFindResult res = scope->Find(classDef->Ident()->Name());
1180     ASSERT(res.variable && res.variable->Declaration()->IsConstDecl());
1181     variable_ = res.variable;
1182     variable_->RemoveFlag(VariableFlags::INITIALIZED);
1183 }
1184 
1185 }  // namespace panda::es2panda::binder
1186