diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 784a32cb7145286e5dfb79528e4f70753bede95d..5fe48fd9f97a32c8aa1f80e8615adc5a589d207d 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -179,8 +179,17 @@ void Binder::IdentifierAnalysis(ResolveBindingFlags flags) ASSERT(scope_ == topScope_); bindingFlags_ = flags; + // Bind function main0 first to determine whether a lexical variable is in it or not under hot-reload mode if (bindingFlags_ & ResolveBindingFlags::TS_BEFORE_TRANSFORM) { + BuildFunction(topScope_, MAIN_FUNC_NAME); + ResolveReferences(program_->Ast()); + } else if (bindingFlags_ & ResolveBindingFlags::TS_AFTER_TRANSFORM) { + // Basically same as js, except of function main0 will not be bound after transform ResolveReferences(program_->Ast()); + AddMandatoryParams(); + if (topScope_->IsModuleScope()) { + AssignIndexToModuleVariable(); + } } else if (bindingFlags_ & ResolveBindingFlags::ALL) { BuildFunction(topScope_, MAIN_FUNC_NAME); ResolveReferences(program_->Ast()); diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 7b0099739072775d0523a031239d300d5d2fbee1..a8ef3f48fc840ba454bb0f136da7990e6fc0e23a 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -394,6 +394,11 @@ public: return (flags_ & flag) != 0; } + void RestoreFuncMain0LexEnv(uint32_t slotSize) + { + slotIndex_ = slotSize; + } + uint32_t NextSlot() { return slotIndex_++; diff --git a/es2panda/binder/variable.cpp b/es2panda/binder/variable.cpp index 23c37db31a4d05398063ddb1584abe6eb80b6e19..42d1d45b26c1a9dbde67f614d0d4acc8ce395569 100644 --- a/es2panda/binder/variable.cpp +++ b/es2panda/binder/variable.cpp @@ -50,10 +50,15 @@ void LocalVariable::SetLexical(Scope *scope, util::PatchFix *patchFixHelper) uint32_t slot = 0; auto name = Declaration()->Name(); - if (patchFixHelper && !patchFixHelper->IsHotReload() && patchFixHelper->IsScopeValidToPatchLexical(varScope)) { + if (patchFixHelper && patchFixHelper->IsScopeValidToPatchLexical(varScope)) { + // get slot from symbol table for lexical variable, if not found, slot is set to UINT32_MAX slot = patchFixHelper->GetSlotIdFromSymbolTable(std::string(name)); - if (patchFixHelper->IsPatchVar(slot)) { + // Store the additional lexical variable into PatchEnv + if (patchFixHelper->IsAdditionalVarInPatch(slot)) { patchFixHelper->AllocSlotfromPatchEnv(std::string(name)); + } else { + // Just for restore 'newlexenv' instruction for func_main_0 in patch + varScope->RestoreFuncMain0LexEnv(patchFixHelper->GetEnvSizeOfFuncMain0()); } } else { slot = varScope->NextSlot(); diff --git a/es2panda/binder/variableFlags.h b/es2panda/binder/variableFlags.h index d870bca045a6af04201abb9707f6f0966b94b042..3bdb668a0a5f92eeaa96cb421a97016492e789c0 100644 --- a/es2panda/binder/variableFlags.h +++ b/es2panda/binder/variableFlags.h @@ -79,6 +79,7 @@ DEFINE_BITOPS(ResolveBindingOptions) enum class ResolveBindingFlags { ALL = 1U << 0U, TS_BEFORE_TRANSFORM = 1U << 1U, + TS_AFTER_TRANSFORM = 1U << 2U, }; DEFINE_BITOPS(ResolveBindingFlags) diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index c138f1c32361313775621666baabf702eb947f53..53786cbdf5aa2e352d461f5a667220381776d7be 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1809,7 +1809,7 @@ void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name) { - if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsPatchVar(slot)) { + if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsAdditionalVarInPatch(slot)) { uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(name)); ra_.Emit(node, patchSlot); return; @@ -1847,7 +1847,7 @@ void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const binder::LocalVariable *local) { - if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsPatchVar(slot)) { + if (context_->PatchFixHelper() && context_->PatchFixHelper()->IsAdditionalVarInPatch(slot)) { uint32_t patchSlot = context_->PatchFixHelper()->GetPatchLexicalIdx(std::string(local->Name())); ra_.Emit(node, patchSlot); return; diff --git a/es2panda/es2panda.cpp b/es2panda/es2panda.cpp index 6038195d6a04d9b0a02a6bd253ae9ca825a3eb70..38ec4c58a37c7e1deba735a1f6e366955c9fbcc8 100644 --- a/es2panda/es2panda.cpp +++ b/es2panda/es2panda.cpp @@ -90,7 +90,7 @@ panda::pandasm::Program *Compiler::Compile(const SourceFile &input, const Compil if (ast.Extension() == ScriptExtension::TS) { transformer_->Transform(&ast); - ast.Binder()->IdentifierAnalysis(binder::ResolveBindingFlags::ALL); + ast.Binder()->IdentifierAnalysis(binder::ResolveBindingFlags::TS_AFTER_TRANSFORM); if (options.dumpTransformedAst) { std::cout << ast.Dump() << std::endl; } diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt b/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt index 5d8ca0489d4fbff9566e8e36432536b3d4e81082..b8064d65e52d2f9538ec6886d942bdfc2f0f67a8 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-increase/expected.txt @@ -24,7 +24,7 @@ label_0: lda v1 add2 0x0, v0 sta v0 - ldlexvar 0x0, 0x2 + wide.ldpatchvar 0x0 sta v1 throw.undefinedifholewithname c lda v1 @@ -33,7 +33,7 @@ label_0: ldai 0x3 add2 0x2, v0 sta v0 - ldlexvar 0x0, 0x3 + wide.ldpatchvar 0x1 sta v1 throw.undefinedifholewithname n lda v1 @@ -45,7 +45,7 @@ label_2: .function any .func_main_0(any a0, any a1, any a2) { label_1: label_0: - newlexenv 0x4 + newlexenv 0x2 definefunc 0x0, .A, 0x0 ldai 0x1 sta v0 @@ -54,9 +54,9 @@ label_0: lda v0 stlexvar 0x0, 0x1 lda v0 - stlexvar 0x0, 0x2 + wide.stpatchvar 0x0 ldai 0x2 - stlexvar 0x0, 0x3 + wide.stpatchvar 0x1 ldundefined returnundefined label_2: diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js index b377a08164dffb24d314854e1fa897e8fda03946..f5717a46eb64baae37ef8deb26dd0136e5b456d7 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base.js @@ -2,7 +2,7 @@ let a = 1; let b = 1; let c = 1; function A() { - let d = a + b; + let d = a + b + c; let e = 3; let m = d + e; return m; diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js index 3f9da8bb7be1c5ff93229a5efd319cdac53be17c..01276424147cf2ff2cb46e541d2ed750ca1ba08a 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/base_mod.js @@ -2,7 +2,7 @@ let a = 1; let b = 1; let c = 1; function A() { - let d = a; + let d = a + c; let e = 3; let m = d + e; return m; diff --git a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt index d94e48e6757495807626b83e50b6b984325a56ae..33ac3f73ec76261bf58e9396920f4222a02f1e82 100644 --- a/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt +++ b/es2panda/test/hotreload/hotreload-noerror/lexenv-reduce/expected.txt @@ -18,8 +18,14 @@ label_0: ldlexvar 0x0, 0x0 sta v0 throw.undefinedifholewithname a - ldai 0x3 + ldlexvar 0x0, 0x2 + sta v1 + throw.undefinedifholewithname c + lda v1 add2 0x0, v0 + sta v0 + ldai 0x3 + add2 0x1, v0 return label_2: } @@ -27,10 +33,14 @@ label_2: .function any .func_main_0(any a0, any a1, any a2) { label_1: label_0: - newlexenv 0x1 + newlexenv 0x3 definefunc 0x0, .A, 0x0 ldai 0x1 + sta v0 + lda v0 stlexvar 0x0, 0x0 + lda v0 + stlexvar 0x0, 0x2 ldundefined returnundefined label_2: diff --git a/es2panda/util/patchFix.cpp b/es2panda/util/patchFix.cpp index e5a8a8ad55b151f7a9a6063fe186bf1e58b6658d..867ad9da221702faf00489ee678f25e7433f6fb2 100644 --- a/es2panda/util/patchFix.cpp +++ b/es2panda/util/patchFix.cpp @@ -293,6 +293,13 @@ uint32_t PatchFix::GetSlotIdFromSymbolTable(const std::string &variableName) return UINT32_MAX; } +uint32_t PatchFix::GetEnvSizeOfFuncMain0() +{ + auto functionIter = originFunctionInfo_->find(funcMain0_); + ASSERT(functionIter != originFunctionInfo_->end()); + return functionIter->second.lexenv.size(); +} + uint32_t PatchFix::GetPatchLexicalIdx(const std::string &variableName) { ASSERT(topScopeLexEnvs_.count(variableName)); @@ -618,7 +625,7 @@ void PatchFix::DumpFunctionInfo(const compiler::PandaGen *pg, panda::pandasm::Fu symbolTable_->WriteSymbolTable(ss.str()); } -bool PatchFix::IsPatchVar(uint32_t slot) +bool PatchFix::IsAdditionalVarInPatch(uint32_t slot) { return slot == UINT32_MAX; } diff --git a/es2panda/util/patchFix.h b/es2panda/util/patchFix.h index 3b255b2328902fd024f2c699f42a33584f147811..0c99c71d0773a1c9e7e2d35f6a035f2d19b185af 100644 --- a/es2panda/util/patchFix.h +++ b/es2panda/util/patchFix.h @@ -66,9 +66,10 @@ public: void Finalize(panda::pandasm::Program **prog); bool IsScopeValidToPatchLexical(binder::VariableScope *scope) const; uint32_t GetSlotIdFromSymbolTable(const std::string &variableName); + uint32_t GetEnvSizeOfFuncMain0(); void AllocSlotfromPatchEnv(const std::string &variableName); uint32_t GetPatchLexicalIdx(const std::string &variableName); - bool IsPatchVar(uint32_t slot); + bool IsAdditionalVarInPatch(uint32_t slot); void ProcessFunction(const compiler::PandaGen *pg, panda::pandasm::Function *func, LiteralBuffers &literalBuffers); void ProcessModule(const std::string &recordName, std::vector &moduleBuffer); void ProcessJsonContentRecord(const std::string &recordName, const std::string &jsonFileContent);