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