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