From 28325725ac2f760481ecea8fb09786325f15e5b7 Mon Sep 17 00:00:00 2001 From: yaochaonan Date: Wed, 10 Jul 2024 00:41:17 +0800 Subject: [PATCH] Support Lazy Import Issue: https://e.gitee.com/open_harmony/dashboard?issue=IAARFN Signed-off-by: yaochaonan Change-Id: I8ccd39ba22d71827eb93699d560165beb9d12ba9 --- .../compiler/baseline/baseline_compiler.cpp | 20 +++++ ecmascript/compiler/bc_call_signature.h | 6 +- ecmascript/compiler/bytecodes.cpp | 24 ++++++ ecmascript/compiler/bytecodes.h | 2 +- ecmascript/compiler/ecma_opcode_des.h | 4 + ecmascript/compiler/interpreter_stub.cpp | 79 ++++++++++++++++++ ecmascript/compiler/slowpath_lowering.cpp | 27 ++++++ ecmascript/compiler/slowpath_lowering.h | 2 + ecmascript/ecma_vm.cpp | 2 + ecmascript/interpreter/interpreter-inl.cpp | 42 +++++++++- .../interpreter/interpreter_assembly.cpp | 56 +++++++++++++ ecmascript/interpreter/slow_runtime_stub.cpp | 15 ++++ ecmascript/interpreter/slow_runtime_stub.h | 2 + .../call_runtime_instruction_dispatch.inl | 4 + ecmascript/jspandafile/js_pandafile.cpp | 2 + ecmascript/jspandafile/js_pandafile.h | 2 + ecmascript/module/js_module_manager.cpp | 82 ++++++++++++++++++- ecmascript/module/js_module_manager.h | 16 ++++ ecmascript/module/js_module_source_text.cpp | 24 +++--- ecmascript/module/js_module_source_text.h | 21 ++++- ecmascript/module/js_shared_module.cpp | 5 +- ecmascript/module/js_shared_module.h | 3 +- .../module/js_shared_module_manager.cpp | 42 +++++++++- ecmascript/module/js_shared_module_manager.h | 4 + ecmascript/module/module_data_extractor.cpp | 37 +++++++-- ecmascript/module/module_data_extractor.h | 8 +- ecmascript/module/module_manager_helper.cpp | 63 ++++++++++++++ ecmascript/module/module_manager_helper.h | 8 ++ ecmascript/object_factory.cpp | 2 + ecmascript/shared_object_factory.cpp | 2 + ecmascript/stubs/runtime_stubs-inl.h | 11 +++ ecmascript/stubs/runtime_stubs.cpp | 16 ++++ ecmascript/stubs/runtime_stubs.h | 6 ++ ecmascript/tests/dump_test.cpp | 2 +- test/moduletest/BUILD.gn | 1 + test/moduletest/moduleLazyImport/A.js | 34 ++++++++ test/moduletest/moduleLazyImport/B.js | 27 ++++++ test/moduletest/moduleLazyImport/BUILD.gn | 22 +++++ test/moduletest/moduleLazyImport/C_Cjs.js | 26 ++++++ test/moduletest/moduleLazyImport/D_Cjs.js | 25 ++++++ test/moduletest/moduleLazyImport/E.js | 25 ++++++ test/moduletest/moduleLazyImport/F.js | 25 ++++++ .../moduleLazyImport/expect_output.txt | 25 ++++++ .../moduleLazyImport/moduleLazyImport.js | 30 +++++++ .../moduleLazyImport/moduleLazyImport.txt | 7 ++ .../sendableclassuseimport.ts | 2 +- 46 files changed, 858 insertions(+), 32 deletions(-) create mode 100644 test/moduletest/moduleLazyImport/A.js create mode 100644 test/moduletest/moduleLazyImport/B.js create mode 100644 test/moduletest/moduleLazyImport/BUILD.gn create mode 100644 test/moduletest/moduleLazyImport/C_Cjs.js create mode 100644 test/moduletest/moduleLazyImport/D_Cjs.js create mode 100644 test/moduletest/moduleLazyImport/E.js create mode 100644 test/moduletest/moduleLazyImport/F.js create mode 100644 test/moduletest/moduleLazyImport/expect_output.txt create mode 100644 test/moduletest/moduleLazyImport/moduleLazyImport.js create mode 100644 test/moduletest/moduleLazyImport/moduleLazyImport.txt diff --git a/ecmascript/compiler/baseline/baseline_compiler.cpp b/ecmascript/compiler/baseline/baseline_compiler.cpp index d61162ab3e..efdb06c88f 100644 --- a/ecmascript/compiler/baseline/baseline_compiler.cpp +++ b/ecmascript/compiler/baseline/baseline_compiler.cpp @@ -5619,5 +5619,25 @@ BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM { (void)bytecodeArray; } + +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8) +{ + (void)bytecodeArray; +} + +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16) +{ + (void)bytecodeArray; +} + +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8) +{ + (void)bytecodeArray; +} + +BYTECODE_BASELINE_HANDLER_IMPLEMENT(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16) +{ + (void)bytecodeArray; +} #undef LOG_INST } // namespace panda::ecmascript::kungfu \ No newline at end of file diff --git a/ecmascript/compiler/bc_call_signature.h b/ecmascript/compiler/bc_call_signature.h index 23d970d0d2..429140eb16 100644 --- a/ecmascript/compiler/bc_call_signature.h +++ b/ecmascript/compiler/bc_call_signature.h @@ -392,7 +392,11 @@ namespace panda::ecmascript::kungfu { T(HandleCallRuntimeLdSendableVarImm8Imm8) \ T(HandleCallRuntimeLdSendableVarImm16Imm16) \ T(HandleCallRuntimeIstruePrefImm8) \ - T(HandleCallRuntimeIsfalsePrefImm8) + T(HandleCallRuntimeIsfalsePrefImm8) \ + T(HandleCallRuntimeLdLazyModuleVarPrefImm8) \ + T(HandleCallRuntimeWideLdLazyModuleVarPrefImm16) \ + T(HandleCallRuntimeLdLazySendableModuleVarPrefImm8) \ + T(HandleCallRuntimeWideLdLazySendableModuleVarPrefImm16) #define ASM_INTERPRETER_BC_HELPER_STUB_LIST(V) \ V(SingleStepDebugging) \ diff --git a/ecmascript/compiler/bytecodes.cpp b/ecmascript/compiler/bytecodes.cpp index f6bafbad3a..91889eb6a9 100644 --- a/ecmascript/compiler/bytecodes.cpp +++ b/ecmascript/compiler/bytecodes.cpp @@ -478,6 +478,10 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc) case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: case EcmaOpcode::CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8: case EcmaOpcode::CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16: + case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16: + case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16: flags |= BytecodeFlags::READ_FUNC; break; case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8: @@ -1236,6 +1240,26 @@ void BytecodeInfo::InitBytecodeInfo(BytecodeCircuitBuilder *builder, info.inputs.emplace_back(Immediate(index)); break; } + case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8: { + int32_t index = READ_INST_8_1(); + info.inputs.emplace_back(Immediate(index)); + break; + } + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16: { + int32_t index = READ_INST_16_1(); + info.inputs.emplace_back(Immediate(index)); + break; + } + case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8: { + int32_t index = READ_INST_8_1(); + info.inputs.emplace_back(Immediate(index)); + break; + } + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16: { + int32_t index = READ_INST_16_1(); + info.inputs.emplace_back(Immediate(index)); + break; + } case EcmaOpcode::STCONSTTOGLOBALRECORD_IMM16_ID16: { uint16_t stringId = READ_INST_16_2(); info.inputs.emplace_back(ConstDataId(ConstDataIDType::StringIDType, stringId)); diff --git a/ecmascript/compiler/bytecodes.h b/ecmascript/compiler/bytecodes.h index dec0ebfaa6..61d342683e 100644 --- a/ecmascript/compiler/bytecodes.h +++ b/ecmascript/compiler/bytecodes.h @@ -291,7 +291,7 @@ public: static constexpr uint32_t LAST_THROW_OPCODE = static_cast(EcmaOpcode::THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16); static constexpr uint32_t LAST_CALLRUNTIME_OPCODE = - static_cast(EcmaOpcode::CALLRUNTIME_ISFALSE_PREF_IMM8); + static_cast(EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16); static_assert(CALLRUNTIME_PREFIX_OPCODE_INDEX == static_cast(EcmaOpcode::CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE)); diff --git a/ecmascript/compiler/ecma_opcode_des.h b/ecmascript/compiler/ecma_opcode_des.h index aa6b4cf1ec..a286dafb6b 100644 --- a/ecmascript/compiler/ecma_opcode_des.h +++ b/ecmascript/compiler/ecma_opcode_des.h @@ -340,6 +340,10 @@ namespace panda::ecmascript::kungfu { V(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16) \ V(CALLRUNTIME_ISTRUE_PREF_IMM8) \ V(CALLRUNTIME_ISFALSE_PREF_IMM8) \ + V(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8) \ + V(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16) \ + V(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8) \ + V(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16) \ inline std::string GetEcmaOpcodeStr(EcmaOpcode opcode) { diff --git a/ecmascript/compiler/interpreter_stub.cpp b/ecmascript/compiler/interpreter_stub.cpp index 99a6502d58..f9581d4bb9 100644 --- a/ecmascript/compiler/interpreter_stub.cpp +++ b/ecmascript/compiler/interpreter_stub.cpp @@ -5881,6 +5881,85 @@ DECLARE_ASM_HANDLER(HandleCallRuntimeLdSendableVarImm16Imm16) DISPATCH_WITH_ACC(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16); } +DECLARE_ASM_HANDLER(HandleCallRuntimeLdLazyModuleVarPrefImm8) +{ + DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); + DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined()); + GateRef index = ReadInst8_1(pc); + + GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); + moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazyExternalModuleVarByIndex), { Int8ToTaggedInt(index), currentFunc }); + + auto env = GetEnvironment(); + Label notException(env); + CHECK_EXCEPTION_WITH_JUMP(*moduleRef, ¬Exception); + Bind(¬Exception); + { + varAcc = *moduleRef; + DISPATCH_WITH_ACC(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8); + } +} + +DECLARE_ASM_HANDLER(HandleCallRuntimeWideLdLazyModuleVarPrefImm16) +{ + DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); + DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined()); + + GateRef index = ReadInst16_1(pc); + + GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); + moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazyExternalModuleVarByIndex), { Int16ToTaggedInt(index), currentFunc }); + + auto env = GetEnvironment(); + Label notException(env); + CHECK_EXCEPTION_WITH_JUMP(*moduleRef, ¬Exception); + Bind(¬Exception); + { + varAcc = *moduleRef; + DISPATCH_WITH_ACC(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16); + } +} + +DECLARE_ASM_HANDLER(HandleCallRuntimeLdLazySendableModuleVarPrefImm8) +{ + DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); + DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined()); + GateRef index = ReadInst8_1(pc); + + GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); + moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazySendableExternalModuleVarByIndex), + { Int8ToTaggedInt(index), currentFunc }); + + auto env = GetEnvironment(); + Label notException(env); + CHECK_EXCEPTION_WITH_JUMP(*moduleRef, ¬Exception); + Bind(¬Exception); + { + varAcc = *moduleRef; + DISPATCH_WITH_ACC(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8); + } +} + +DECLARE_ASM_HANDLER(HandleCallRuntimeWideLdLazySendableModuleVarPrefImm16) +{ + DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc); + DEFVARIABLE(moduleRef, VariableType::JS_ANY(), Undefined()); + + GateRef index = ReadInst16_1(pc); + + GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp)); + moduleRef = CallRuntime(glue, RTSTUB_ID(LdLazySendableExternalModuleVarByIndex), + { Int16ToTaggedInt(index), currentFunc }); + + auto env = GetEnvironment(); + Label notException(env); + CHECK_EXCEPTION_WITH_JUMP(*moduleRef, ¬Exception); + Bind(¬Exception); + { + varAcc = *moduleRef; + DISPATCH_WITH_ACC(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16); + } +} ASM_INTERPRETER_BC_TYPE_PROFILER_STUB_LIST(DECLARE_ASM_HANDLER_PROFILE) ASM_INTERPRETER_BC_LAYOUT_PROFILER_STUB_LIST(DECLARE_ASM_HANDLER_PROFILE) diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index d4ad58f9cf..83dd5a7b5a 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -784,6 +784,14 @@ void SlowPathLowering::Lower(GateRef gate) case EcmaOpcode::CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16: LowerLdSendableVar(gate); break; + case EcmaOpcode::CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16: + LowerLdLazyExternalModuleVar(gate); + break; + case EcmaOpcode::CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8: + case EcmaOpcode::CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16: + LowerLdLazySendableExternalModuleVar(gate); + break; case EcmaOpcode::LDA_STR_ID16: LowerLdStr(gate); break; @@ -3864,4 +3872,23 @@ void SlowPathLowering::LowerGetUnsharedConstPool(GateRef gate) acc_.DeleteGate(gate); } +void SlowPathLowering::LowerLdLazyExternalModuleVar(GateRef gate) +{ + ASSERT(acc_.GetNumValueIn(gate) == 1); + GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); + GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0)); + GateRef result = LowerCallRuntime(gate, + RTSTUB_ID(LdLazyExternalModuleVarByIndex), {index, jsFunc}, true); + ReplaceHirWithValue(gate, result); +} + +void SlowPathLowering::LowerLdLazySendableExternalModuleVar(GateRef gate) +{ + ASSERT(acc_.GetNumValueIn(gate) == 1); + GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC); + GateRef index = builder_.ToTaggedInt(acc_.GetValueIn(gate, 0)); + GateRef result = LowerCallRuntime(gate, + RTSTUB_ID(LdLazySendableExternalModuleVarByIndex), {index, jsFunc}, true); + ReplaceHirWithValue(gate, result); +} } // namespace panda::ecmascript diff --git a/ecmascript/compiler/slowpath_lowering.h b/ecmascript/compiler/slowpath_lowering.h index fba562aa43..6f952a0221 100644 --- a/ecmascript/compiler/slowpath_lowering.h +++ b/ecmascript/compiler/slowpath_lowering.h @@ -335,6 +335,8 @@ private: void LowerLdStr(GateRef gate); void LowerGetSharedConstPool(GateRef gate); void LowerGetUnsharedConstPool(GateRef gate); + void LowerLdLazyExternalModuleVar(GateRef gate); + void LowerLdLazySendableExternalModuleVar(GateRef gate); CompilationEnv *compilationEnv_; const MethodLiteral *methodLiteral_ {nullptr}; diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index 511aadf5c4..51625c54b6 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -418,6 +418,8 @@ EcmaVM::~EcmaVM() } #endif + thread_->GetCurrentEcmaContext()->GetModuleManager()->NativeObjDestory(); + if (!isBundlePack_) { std::shared_ptr jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(assetPath_); if (jsPandaFile != nullptr) { diff --git a/ecmascript/interpreter/interpreter-inl.cpp b/ecmascript/interpreter/interpreter-inl.cpp index 7bf79cddc1..e43cea7ccc 100644 --- a/ecmascript/interpreter/interpreter-inl.cpp +++ b/ecmascript/interpreter/interpreter-inl.cpp @@ -1039,7 +1039,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t constexpr size_t numOps = 0x100; constexpr size_t numThrowOps = 10; constexpr size_t numWideOps = 20; - constexpr size_t numCallRuntimeOps = 21; + constexpr size_t numCallRuntimeOps = 25; constexpr size_t numDeprecatedOps = 47; static std::array instDispatchTable { @@ -7803,6 +7803,46 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t SET_ACC(SendableEnv::Cast(env.GetTaggedObject())->GetProperties(slot)); DISPATCH(CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16); } + HANDLE_OPCODE(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8) { + int32_t index = READ_INST_8_1(); + JSTaggedValue funcObj = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, funcObj); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8); + } + HANDLE_OPCODE(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16) { + int32_t index = READ_INST_16_1(); + JSTaggedValue funcObj = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, funcObj); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16); + } + HANDLE_OPCODE(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8) { + int32_t index = READ_INST_8_1(); + JSTaggedValue funcObj = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, funcObj); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8); + } + HANDLE_OPCODE(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16) { + int32_t index = READ_INST_16_1(); + JSTaggedValue funcObj = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, funcObj); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16); + } #include "templates/debugger_instruction_handler.inl" } #endif diff --git a/ecmascript/interpreter/interpreter_assembly.cpp b/ecmascript/interpreter/interpreter_assembly.cpp index 6600a8ee2c..2b43006f8d 100644 --- a/ecmascript/interpreter/interpreter_assembly.cpp +++ b/ecmascript/interpreter/interpreter_assembly.cpp @@ -7796,6 +7796,62 @@ void InterpreterAssembly::ExceptionHandler( DISPATCH_OFFSET(0); } +void InterpreterAssembly::HandleCallRuntimeLdLazyModuleVarPrefImm8( + JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, + JSTaggedValue acc, int16_t hotnessCounter) +{ + int32_t index = READ_INST_8_1(); + JSTaggedValue thisFunc = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, thisFunc); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8); +} + +void InterpreterAssembly::HandleCallRuntimeWideLdLazyModuleVarPrefImm16( + JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, + JSTaggedValue acc, int16_t hotnessCounter) +{ + int32_t index = READ_INST_16_1(); + JSTaggedValue thisFunc = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazyexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazyExternalModuleVar(thread, index, thisFunc); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16); +} + +void InterpreterAssembly::HandleCallRuntimeLdLazySendableModuleVarPrefImm8( + JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, + JSTaggedValue acc, int16_t hotnessCounter) +{ + int32_t index = READ_INST_8_1(); + JSTaggedValue thisFunc = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, thisFunc); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8); +} + +void InterpreterAssembly::HandleCallRuntimeWideLdLazySendableModuleVarPrefImm16( + JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo, + JSTaggedValue acc, int16_t hotnessCounter) +{ + int32_t index = READ_INST_16_1(); + JSTaggedValue thisFunc = GetFunction(sp); + LOG_INST() << "intrinsics::ldlazysendableexternalmodulevar index:" << index; + + JSTaggedValue moduleVar = SlowRuntimeStub::LdLazySendableExternalModuleVar(thread, index, thisFunc); + INTERPRETER_RETURN_IF_ABRUPT(moduleVar); + SET_ACC(moduleVar); + DISPATCH(CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16); +} + #define DECLARE_UNUSED_ASM_HANDLE(name) \ void InterpreterAssembly::name( \ JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, \ diff --git a/ecmascript/interpreter/slow_runtime_stub.cpp b/ecmascript/interpreter/slow_runtime_stub.cpp index 5e74f354ae..e3cd2ca443 100644 --- a/ecmascript/interpreter/slow_runtime_stub.cpp +++ b/ecmascript/interpreter/slow_runtime_stub.cpp @@ -1057,6 +1057,21 @@ JSTaggedValue SlowRuntimeStub::LdSendableExternalModuleVar(JSThread *thread, int return RuntimeStubs::RuntimeLdSendableExternalModuleVar(thread, index, thisFunc); } +JSTaggedValue SlowRuntimeStub::LdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc) +{ + RUNTIME_TRACE(thread, LdLazyExternalModuleVarByIndex); + [[maybe_unused]] EcmaHandleScope scope(thread); + return RuntimeStubs::RuntimeLdLazyExternalModuleVar(thread, index, thisFunc); +} + +JSTaggedValue SlowRuntimeStub::LdLazySendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc) +{ + RUNTIME_TRACE(thread, LdLazySendableExternalModuleVarByIndex); + [[maybe_unused]] EcmaHandleScope scope(thread); + + return RuntimeStubs::RuntimeLdLazySendableExternalModuleVar(thread, index, thisFunc); +} + JSTaggedValue SlowRuntimeStub::LdSuperByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key, JSTaggedValue thisFunc) { diff --git a/ecmascript/interpreter/slow_runtime_stub.h b/ecmascript/interpreter/slow_runtime_stub.h index 2142d1150a..66a8625f33 100644 --- a/ecmascript/interpreter/slow_runtime_stub.h +++ b/ecmascript/interpreter/slow_runtime_stub.h @@ -120,6 +120,8 @@ public: static JSTaggedValue LdLocalModuleVar(JSThread *thread, int32_t index); static JSTaggedValue LdExternalModuleVar(JSThread *thread, int32_t index); static JSTaggedValue LdSendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc); + static JSTaggedValue LdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc); + static JSTaggedValue LdLazySendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue thisFunc); static JSTaggedValue CreateRegExpWithLiteral(JSThread *thread, JSTaggedValue pattern, uint8_t flags); static JSTaggedValue GetIteratorNext(JSThread *thread, JSTaggedValue obj, JSTaggedValue method); diff --git a/ecmascript/interpreter/templates/call_runtime_instruction_dispatch.inl b/ecmascript/interpreter/templates/call_runtime_instruction_dispatch.inl index 2bbec51a2e..58296e51e0 100755 --- a/ecmascript/interpreter/templates/call_runtime_instruction_dispatch.inl +++ b/ecmascript/interpreter/templates/call_runtime_instruction_dispatch.inl @@ -34,3 +34,7 @@ &&HANDLE_CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16, &&HANDLE_CALLRUNTIME_ISTRUE_PREF_IMM8, &&HANDLE_CALLRUNTIME_ISFALSE_PREF_IMM8, + &&HANDLE_CALLRUNTIME_LDLAZYMODULEVAR_PREF_IMM8, + &&HANDLE_CALLRUNTIME_WIDELDLAZYMODULEVAR_PREF_IMM16, + &&HANDLE_CALLRUNTIME_LDLAZYSENDABLEMODULEVAR_PREF_IMM8, + &&HANDLE_CALLRUNTIME_WIDELDLAZYSENDABLEMODULEVAR_PREF_IMM16, diff --git a/ecmascript/jspandafile/js_pandafile.cpp b/ecmascript/jspandafile/js_pandafile.cpp index c75467cd7b..f49b927a1c 100644 --- a/ecmascript/jspandafile/js_pandafile.cpp +++ b/ecmascript/jspandafile/js_pandafile.cpp @@ -207,6 +207,8 @@ void JSPandaFile::InitializeMergedPF() info->isSharedModule = fieldAccessor.GetValue().value(); } else if (std::strcmp(HAS_TOP_LEVEL_AWAIT, fieldName) == 0) { info->hasTopLevelAwait = fieldAccessor.GetValue().value(); + } else if (std::strcmp(LAZY_IMPORT, fieldName) == 0) { + info->lazyImportIdx = fieldAccessor.GetValue().value(); } else if (std::strcmp(TYPE_FLAG, fieldName) == 0) { info->hasTSTypes = fieldAccessor.GetValue().value() != 0; } else if (std::strcmp(TYPE_SUMMARY_OFFSET, fieldName) == 0) { diff --git a/ecmascript/jspandafile/js_pandafile.h b/ecmascript/jspandafile/js_pandafile.h index 5494daebce..b788e9686f 100644 --- a/ecmascript/jspandafile/js_pandafile.h +++ b/ecmascript/jspandafile/js_pandafile.h @@ -42,6 +42,7 @@ public: bool hasTopLevelAwait {false}; CUnorderedMap constpoolMap; bool hasTSTypes {false}; + uint32_t lazyImportIdx {0}; uint32_t typeSummaryOffset {0}; uint32_t classId {CLASSID_OFFSET_NOT_FOUND}; CString npmPackageName; @@ -77,6 +78,7 @@ public: static constexpr char MODULE_RECORD_IDX[] = "moduleRecordIdx"; static constexpr char IS_SHARED_MODULE[] = "isSharedModule"; static constexpr char HAS_TOP_LEVEL_AWAIT[] = "hasTopLevelAwait"; + static constexpr char LAZY_IMPORT[] = "moduleRequestPhaseIdx"; static constexpr char PACKAGE_NAME[] = "pkgName@"; static constexpr char MERGE_ABC_NAME[] = "modules.abc"; static constexpr char NPM_PATH_SEGMENT[] = "node_modules"; diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index 5c7c597d70..315a1be6b0 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -164,6 +164,80 @@ JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTagge UNREACHABLE(); } +JSTaggedValue ModuleManager::GetLazyModuleValueOutter(int32_t index, JSTaggedValue jsFunc) +{ + JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(); + return GetLazyModuleValueOutterInternal(index, currentModule); +} + +JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule) +{ + JSThread *thread = vm_->GetJSThread(); + if (currentModule.IsUndefined()) { + LOG_FULL(FATAL) << "GetLazyModuleValueOutter currentModule failed"; + UNREACHABLE(); + } + JSHandle currentModuleHdl(thread, currentModule); + JSTaggedValue moduleEnvironment = currentModuleHdl->GetEnvironment(); + if (moduleEnvironment.IsUndefined()) { + return thread->GlobalConstants()->GetUndefined(); + } + ASSERT(moduleEnvironment.IsTaggedArray()); + JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index); + if (resolvedBinding.IsResolvedIndexBinding()) { + JSHandle binding(thread, resolvedBinding); + JSTaggedValue resolvedModule = binding->GetModule(); + JSHandle module(thread, resolvedModule); + ASSERT(resolvedModule.IsSourceTextModule()); + SourceTextModule::Evaluate(thread, module, nullptr); + if (thread->HasPendingException()) { + return JSTaggedValue::Undefined(); + } + // Support for only modifying var value of HotReload. + // Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord. + EcmaContext *context = thread->GetCurrentEcmaContext(); + if (context->GetStageOfHotReload() == StageOfHotReload::LOAD_END_EXECUTE_PATCHMAIN) { + const JSHandle resolvedModuleOfHotReload = + context->FindPatchModule(ConvertToString(module->GetEcmaModuleRecordName())); + if (!resolvedModuleOfHotReload->IsHole()) { + resolvedModule = resolvedModuleOfHotReload.GetTaggedValue(); + JSHandle moduleOfHotReload(thread, resolvedModule); + return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex()); + } + } + return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex()); + } + if (resolvedBinding.IsResolvedBinding()) { + JSHandle binding(thread, resolvedBinding); + JSTaggedValue resolvedModule = binding->GetModule(); + JSHandle module(thread, resolvedModule); + ModuleStatus status = module->GetStatus(); + ModuleTypes moduleType = module->GetTypes(); + if (SourceTextModule::IsNativeModule(moduleType)) { + SourceTextModule::InstantiateNativeModule(thread, currentModuleHdl, module, moduleType); + module->SetStatus(ModuleStatus::EVALUATED); + return ModuleManagerHelper::GetNativeModuleValue(thread, resolvedModule, binding->GetBindingName()); + } + if (moduleType == ModuleTypes::CJS_MODULE) { + if (status != ModuleStatus::EVALUATED) { + SourceTextModule::ModuleExecution(thread, module, nullptr, 0); + module->SetStatus(ModuleStatus::EVALUATED); + } + SourceTextModule::InstantiateCJS(thread, currentModuleHdl, module); + JSHandle cjsModuleName(thread, SourceTextModule::GetModuleName(module.GetTaggedValue())); + return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue(); + } + } + if (resolvedBinding.IsResolvedRecordIndexBinding()) { + return ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(thread, currentModuleHdl, resolvedBinding); + } + if (resolvedBinding.IsResolvedRecordBinding()) { + return ModuleManagerHelper::GetLazyModuleValueFromRecordBinding(thread, currentModuleHdl, resolvedBinding); + } + LOG_ECMA(FATAL) << "Get module value failed, mistaken ResolvedBinding"; + UNREACHABLE(); +} + void ModuleManager::StoreModuleValue(int32_t index, JSTaggedValue value) { JSThread *thread = vm_->GetJSThread(); @@ -465,7 +539,8 @@ JSHandle ModuleManager::ResolveModule(JSThread *thread, const JSP JSHandle moduleRecord = thread->GlobalConstants()->GetHandledUndefined(); JSRecordInfo recordInfo = const_cast(jsPandaFile)->FindRecordInfo(JSPandaFile::ENTRY_FUNCTION_NAME); if (jsPandaFile->IsModule(&recordInfo)) { - moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, moduleFileName, moduleFileName); + moduleRecord = ModuleDataExtractor::ParseModule( + thread, jsPandaFile, moduleFileName, moduleFileName, &recordInfo); } else { ASSERT(jsPandaFile->IsCjs(&recordInfo)); moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile); @@ -508,7 +583,7 @@ JSHandle ModuleManager::ResolveModuleWithMerge( } if (jsPandaFile->IsModule(recordInfo)) { RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); - moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordNameStr, moduleFileName); + moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordNameStr, moduleFileName, recordInfo); } else if (jsPandaFile->IsJson(recordInfo)) { moduleRecord = ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, moduleFileName, recordNameStr); } else { @@ -852,7 +927,8 @@ void ModuleManager::RemoveModuleFromCache(JSTaggedValue recordName) int entry = dict->FindEntry(recordName); LOG_ECMA_IF(entry == -1, FATAL) << "Can not get module: " << ConvertToString(recordName) << ", when try to remove the module"; - + JSTaggedValue result = dict->GetValue(entry); + SourceTextModule::Cast(result)->DestoryLazyImportArray(); resolvedModules_ = NameDictionary::Remove(thread, dict, entry).GetTaggedValue(); } } // namespace panda::ecmascript diff --git a/ecmascript/module/js_module_manager.h b/ecmascript/module/js_module_manager.h index e009a1cb60..c4bd565397 100644 --- a/ecmascript/module/js_module_manager.h +++ b/ecmascript/module/js_module_manager.h @@ -37,6 +37,7 @@ public: JSTaggedValue GetModuleValueOutter(int32_t index); JSTaggedValue GetModuleValueOutter(int32_t index, JSTaggedValue jsFunc); JSTaggedValue GetModuleValueOutter(int32_t index, JSHandle currentModule); + JSTaggedValue GetLazyModuleValueOutter(int32_t index, JSTaggedValue jsFunc); void StoreModuleValue(int32_t index, JSTaggedValue value); void StoreModuleValue(int32_t index, JSTaggedValue value, JSTaggedValue jsFunc); JSTaggedValue GetModuleNamespace(int32_t index); @@ -115,6 +116,19 @@ public: return ordinal; } + void NativeObjDestory() + { + NameDictionary* dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject()); + int size = dict->Size(); + for (int hashIndex = 0; hashIndex < size; hashIndex++) { + JSTaggedValue key(dict->GetKey(hashIndex)); + if (!key.IsUndefined() && !key.IsHole() && !key.IsNull()) { + JSTaggedValue val(dict->GetValue(hashIndex)); + SourceTextModule::Cast(val)->DestoryLazyImportArray(); + } + } + } + private: NO_COPY_SEMANTIC(ModuleManager); NO_MOVE_SEMANTIC(ModuleManager); @@ -123,6 +137,8 @@ private: void StoreModuleValueInternal(JSHandle ¤tModule, int32_t index, JSTaggedValue value); + JSTaggedValue GetLazyModuleValueOutterInternal(int32_t index, JSTaggedValue currentModule); + // deprecated begin JSTaggedValue GetModuleValueOutterInternal(JSTaggedValue key, JSTaggedValue currentModule); void StoreModuleValueInternal(JSHandle ¤tModule, diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 710293d897..42b10e11bd 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -488,13 +488,12 @@ bool SourceTextModule::LoadNativeModule(JSThread *thread, const JSHandle ¤tModule, - JSHandle &requiredModule, const JSHandle &moduleRequest, - ModuleTypes moduleType) + JSHandle &requiredModule, ModuleTypes moduleType) { if (requiredModule->GetStatus() != ModuleStatus::EVALUATED) { if (!SourceTextModule::LoadNativeModule(thread, requiredModule, moduleType)) { LOG_FULL(WARN) << "LoadNativeModule " << - ModulePathHelper::Utf8ConvertToString(moduleRequest.GetTaggedValue()) << " failed"; + ModulePathHelper::Utf8ConvertToString(requiredModule->GetEcmaModuleRecordName()) << " failed"; return; } } @@ -1114,21 +1113,26 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand JSHandle requestedModules(thread, module->GetRequestedModules()); size_t requestedModulesLen = requestedModules->GetLength(); JSMutableHandle required(thread, thread->GlobalConstants()->GetUndefined()); + JSHandle requiredModule; + bool *lazyFlag = module->GetLazyImportStatusArray(); for (size_t idx = 0; idx < requestedModulesLen; idx++) { + if (lazyFlag[idx]) { + continue; + } required.Update(requestedModules->Get(idx)); - JSMutableHandle requiredModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - requiredModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, required)); + requiredModule = JSHandle::Cast( + SourceTextModule::HostResolveImportedModule(thread, module, required)); } else { ASSERT(moduleRecordName.IsString()); - requiredModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required)); + requiredModule = JSHandle::Cast( + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index); } - ModuleTypes moduleType = requiredModule->GetTypes(); if (SourceTextModule::IsNativeModule(moduleType)) { - InstantiateNativeModule(thread, module, requiredModule, required, moduleType); + InstantiateNativeModule(thread, module, requiredModule, moduleType); requiredModule->SetStatus(ModuleStatus::EVALUATED); continue; } @@ -1156,7 +1160,7 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand int dfsAncIdx = std::min(module->GetDFSAncestorIndex(), requiredModule->GetDFSAncestorIndex()); module->SetDFSAncestorIndex(dfsAncIdx); } else { - requiredModule.Update(requiredModule->GetCycleRoot()); + requiredModule = JSHandle(thread, requiredModule->GetCycleRoot()); requiredModuleStatus = requiredModule->GetStatus(); ASSERT(requiredModuleStatus == ModuleStatus::EVALUATING_ASYNC || requiredModuleStatus == ModuleStatus::EVALUATED); @@ -1355,7 +1359,7 @@ int SourceTextModule::ModuleEvaluation(JSThread *thread, const JSHandleGetTypes(); if (SourceTextModule::IsNativeModule(moduleType)) { - InstantiateNativeModule(thread, module, requiredModule, required, moduleType); + InstantiateNativeModule(thread, module, requiredModule, moduleType); requiredModule->SetStatus(ModuleStatus::EVALUATED); continue; } diff --git a/ecmascript/module/js_module_source_text.h b/ecmascript/module/js_module_source_text.h index 118e408e69..e5e1eda3ad 100644 --- a/ecmascript/module/js_module_source_text.h +++ b/ecmascript/module/js_module_source_text.h @@ -232,6 +232,22 @@ public: SharedTypes::SENDABLE_FUNCTION_MODULE; } + inline void SetLazyImportArray(bool *lazyImportArray) + { + DestoryLazyImportArray(); + SetLazyImportStatus(ToUintPtr(lazyImportArray)); + } + + inline void DestoryLazyImportArray() + { + delete[] GetLazyImportStatusArray(); + } + + inline bool *GetLazyImportStatusArray() + { + return reinterpret_cast(GetLazyImportStatus()); + } + static constexpr size_t SOURCE_TEXT_MODULE_OFFSET = ModuleRecord::SIZE; ACCESSORS(Environment, SOURCE_TEXT_MODULE_OFFSET, NAMESPACE_OFFSET); ACCESSORS(Namespace, NAMESPACE_OFFSET, ECMA_MODULE_FILENAME); @@ -251,7 +267,9 @@ public: ACCESSORS_PRIMITIVE_FIELD(DFSAncestorIndex, int32_t, DFS_ANCESTOR_INDEX_OFFSET, DFS_INDEX_OFFSET); ACCESSORS_PRIMITIVE_FIELD(DFSIndex, int32_t, DFS_INDEX_OFFSET, ASYNC_EVALUATION_OFFSET); ACCESSORS_PRIMITIVE_FIELD(AsyncEvaluatingOrdinal, uint32_t, ASYNC_EVALUATION_OFFSET, PENDING_DEPENDENCIES_OFFSET); - ACCESSORS_PRIMITIVE_FIELD(PendingAsyncDependencies, int32_t, PENDING_DEPENDENCIES_OFFSET, BIT_FIELD_OFFSET); + ACCESSORS_PRIMITIVE_FIELD(PendingAsyncDependencies, + int32_t, PENDING_DEPENDENCIES_OFFSET, LAYZ_IMPORT_STATUS_OFFSET); + ACCESSORS_PRIMITIVE_FIELD(LazyImportStatus, uintptr_t, LAYZ_IMPORT_STATUS_OFFSET, BIT_FIELD_OFFSET); ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) DEFINE_ALIGN_SIZE(LAST_OFFSET); @@ -289,7 +307,6 @@ public: const JSHandle &requiredModule); static void InstantiateNativeModule(JSThread *thread, JSHandle ¤tModule, JSHandle &requiredModule, - const JSHandle &moduleRequest, ModuleTypes moduleType); JSTaggedValue GetModuleValue(JSThread *thread, int32_t index, bool isThrow); diff --git a/ecmascript/module/js_shared_module.cpp b/ecmascript/module/js_shared_module.cpp index c7e68429db..7919454559 100644 --- a/ecmascript/module/js_shared_module.cpp +++ b/ecmascript/module/js_shared_module.cpp @@ -127,7 +127,8 @@ JSHandle JSSharedModule::CloneEnvForSModule(JSThread *thread, const } JSHandle SharedModuleHelper::ParseSharedModule(JSThread *thread, const JSPandaFile *jsPandaFile, - const CString &descriptor, const CString &moduleFilename) + const CString &descriptor, const CString &moduleFilename, + JSRecordInfo *recordInfo) { int moduleIdx = jsPandaFile->GetModuleRecordIdx(descriptor); ASSERT(jsPandaFile->IsNewVersion() && (moduleIdx != -1)); // new pandafile version use new literal offset mechanism @@ -136,7 +137,7 @@ JSHandle SharedModuleHelper::ParseSharedModule(JSThread *thread, ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle moduleRecord = factory->NewSSourceTextModule(); moduleRecord->SetSharedType(SharedTypes::SHARED_MODULE); - ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord); + ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord, recordInfo); bool hasTLA = jsPandaFile->GetHasTopLevelAwait(descriptor); moduleRecord->SetHasTLA(hasTLA); diff --git a/ecmascript/module/js_shared_module.h b/ecmascript/module/js_shared_module.h index 9beb773750..ed604561bd 100644 --- a/ecmascript/module/js_shared_module.h +++ b/ecmascript/module/js_shared_module.h @@ -75,7 +75,8 @@ public: class SharedModuleHelper { public: static JSHandle ParseSharedModule(JSThread *thread, const JSPandaFile *jsPandaFile, - const CString &descriptor, const CString &moduleFilename); + const CString &descriptor, const CString &moduleFilename, + JSRecordInfo *recordInfo); }; } // namespace panda::ecmascript diff --git a/ecmascript/module/js_shared_module_manager.cpp b/ecmascript/module/js_shared_module_manager.cpp index d019c482dd..5c073f2d59 100644 --- a/ecmascript/module/js_shared_module_manager.cpp +++ b/ecmascript/module/js_shared_module_manager.cpp @@ -79,6 +79,44 @@ JSTaggedValue SharedModuleManager::GetSendableModuleValueImpl( UNREACHABLE(); } +JSTaggedValue SharedModuleManager::GetLazySendableModuleValue(JSThread *thread, int32_t index, JSTaggedValue jsFunc) +{ + JSTaggedValue currentModule = JSFunction::Cast(jsFunc.GetTaggedObject())->GetModule(); + return GetLazySendableModuleValueImpl(thread, index, currentModule); +} + +JSTaggedValue SharedModuleManager::GetLazySendableModuleValueImpl( + JSThread *thread, int32_t index, JSTaggedValue currentModule) const +{ + if (currentModule.IsUndefined()) { + LOG_FULL(FATAL) << "GetModuleValueOutter currentModule failed"; + UNREACHABLE(); + } + + JSHandle module(thread, currentModule.GetTaggedObject()); + JSTaggedValue moduleEnvironment = module->GetEnvironment(); + if (moduleEnvironment.IsUndefined()) { + return thread->GlobalConstants()->GetUndefined(); + } + ASSERT(moduleEnvironment.IsTaggedArray()); + JSTaggedValue resolvedBinding = TaggedArray::Cast(moduleEnvironment.GetTaggedObject())->Get(index); + if (resolvedBinding.IsResolvedRecordIndexBinding()) { + return ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(thread, module, resolvedBinding); + } else if (resolvedBinding.IsResolvedIndexBinding()) { + ResolvedIndexBinding *binding = ResolvedIndexBinding::Cast(resolvedBinding.GetTaggedObject()); + JSHandle resolvedModule(thread, binding->GetModule().GetTaggedObject()); + SourceTextModule::Evaluate(thread, resolvedModule, nullptr); + if (thread->HasPendingException()) { + return JSTaggedValue::Undefined(); + } + return ModuleManagerHelper::GetModuleValue(thread, resolvedModule, binding->GetIndex()); + } else if (resolvedBinding.IsResolvedRecordBinding()) { + return ModuleManagerHelper::GetLazyModuleValueFromRecordBinding(thread, module, resolvedBinding); + } + LOG_ECMA(FATAL) << "Unexpect binding"; + UNREACHABLE(); +} + JSHandle SharedModuleManager::ResolveImportedModule(JSThread *thread, const CString &fileName, bool executeFromJob) { @@ -122,7 +160,7 @@ JSHandle SharedModuleManager::ResolveSharedImportedModule(JSThrea ASSERT(jsPandaFile->IsModule(recordInfo)); JSHandle moduleRecord = SharedModuleHelper::ParseSharedModule(thread, - jsPandaFile, fileName, fileName); + jsPandaFile, fileName, fileName, recordInfo); moduleManager->AddResolveImportedModule(requireModule, moduleRecord); moduleManager->AddToInstantiatingSModuleList(fileName); return moduleRecord; @@ -173,7 +211,7 @@ JSHandle SharedModuleManager::ResolveSharedImportedModuleWithMerg ASSERT(jsPandaFile->IsModule(recordInfo)); JSHandle moduleRecord = SharedModuleHelper::ParseSharedModule(thread, jsPandaFile, recordName, - fileName); + fileName, recordInfo); JSHandle::Cast(moduleRecord)->SetEcmaModuleRecordName(thread, requireModule); moduleManager->AddResolveImportedModule(requireModule, moduleRecord); moduleManager->AddToInstantiatingSModuleList(recordName); diff --git a/ecmascript/module/js_shared_module_manager.h b/ecmascript/module/js_shared_module_manager.h index f180911bc9..79b9558613 100644 --- a/ecmascript/module/js_shared_module_manager.h +++ b/ecmascript/module/js_shared_module_manager.h @@ -50,6 +50,10 @@ public: JSTaggedValue GetSendableModuleValueImpl(JSThread *thread, int32_t index, JSTaggedValue currentModule) const; + JSTaggedValue GetLazySendableModuleValue(JSThread *thread, int32_t index, JSTaggedValue jsFunc); + + JSTaggedValue GetLazySendableModuleValueImpl(JSThread *thread, int32_t index, JSTaggedValue currentModule) const; + void Iterate(const RootVisitor &v); JSHandle ResolveImportedModule(JSThread *thread, const CString &referencingModule, diff --git a/ecmascript/module/module_data_extractor.cpp b/ecmascript/module/module_data_extractor.cpp index 22bac04098..fab6ebe3ad 100644 --- a/ecmascript/module/module_data_extractor.cpp +++ b/ecmascript/module/module_data_extractor.cpp @@ -31,11 +31,11 @@ using BuiltinsJson = builtins::BuiltinsJson; using JSRecordInfo = ecmascript::JSPandaFile::JSRecordInfo; JSHandle ModuleDataExtractor::ParseModule(JSThread *thread, const JSPandaFile *jsPandaFile, - const CString &descriptor, const CString &moduleFilename) + const CString &descriptor, const CString &moduleFilename, + JSRecordInfo *recordInfo) { int moduleIdx = jsPandaFile->GetModuleRecordIdx(descriptor); ASSERT(moduleIdx != -1); - panda_file::File::EntityId moduleId; if (jsPandaFile->IsNewVersion()) { // new pandafile version use new literal offset mechanism moduleId = panda_file::File::EntityId(static_cast(moduleIdx)); @@ -46,9 +46,9 @@ JSHandle ModuleDataExtractor::ParseModule(JSThread *thread, const ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle moduleRecord = factory->NewSourceTextModule(); - ModuleDataExtractor::ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord); + ExtractModuleDatas(thread, jsPandaFile, moduleId, moduleRecord, recordInfo); - bool hasTLA = jsPandaFile->GetHasTopLevelAwait(descriptor); + bool hasTLA = recordInfo->hasTopLevelAwait; moduleRecord->SetHasTLA(hasTLA); JSHandle ecmaModuleFilename = factory->NewFromUtf8(moduleFilename); @@ -63,7 +63,8 @@ JSHandle ModuleDataExtractor::ParseModule(JSThread *thread, const void ModuleDataExtractor::ExtractModuleDatas(JSThread *thread, const JSPandaFile *jsPandaFile, panda_file::File::EntityId moduleId, - JSHandle &moduleRecord) + JSHandle &moduleRecord, + [[maybe_unused]]JSRecordInfo *recordInfo) { [[maybe_unused]] EcmaHandleScope scope(thread); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); @@ -86,6 +87,17 @@ void ModuleDataExtractor::ExtractModuleDatas(JSThread *thread, const JSPandaFile moduleRecord->SetRequestedModules(thread, requestModuleArray); } + if (recordInfo->lazyImportIdx != 0) { + bool *lazyImportFlags = ModuleLazyImportFlagAccessor(jsPandaFile, + panda_file::File::EntityId(static_cast(recordInfo->lazyImportIdx))); + moduleRecord->SetLazyImportArray(lazyImportFlags); // set module Lazy Import flag + } else { + bool *lazyImportArray = new bool[len](); + for (size_t idx = 0; idx < len; idx++) { + lazyImportArray[idx] = 0; + } + moduleRecord->SetLazyImportArray(lazyImportArray); // set module Lazy Import 0 + } // note the order can't change mda.EnumerateImportEntry(thread, requestModuleArray, moduleRecord); mda.EnumerateLocalExportEntry(thread, moduleRecord); @@ -174,4 +186,19 @@ JSTaggedValue ModuleDataExtractor::JsonParse(JSThread *thread, const JSPandaFile info->SetCallArg(value); return BuiltinsJson::Parse(info); } + +bool* ModuleDataExtractor::ModuleLazyImportFlagAccessor(const JSPandaFile *pandaFile, + panda_file::File::EntityId module_lazy_import_flag_id) +{ + auto &pf = *pandaFile->GetPandaFile(); + auto sp = pf.GetSpanFromId(module_lazy_import_flag_id); + + uint32_t numLazyImportFlags = panda_file::helpers::Read(&sp); + bool *lazyImportArray = new bool[numLazyImportFlags](); + for (size_t idx = 0; idx < numLazyImportFlags; idx++) { + uint32_t value = static_cast(panda_file::helpers::Read(&sp)); + lazyImportArray[idx] = value > 0 ? 1 : 0; + } + return lazyImportArray; +} } // namespace panda::ecmascript diff --git a/ecmascript/module/module_data_extractor.h b/ecmascript/module/module_data_extractor.h index 101c0a4d26..7d69768fe8 100644 --- a/ecmascript/module/module_data_extractor.h +++ b/ecmascript/module/module_data_extractor.h @@ -34,15 +34,19 @@ public: static void ExtractModuleDatas(JSThread *thread, const JSPandaFile *jsPandaFile, panda_file::File::EntityId moduleId, - JSHandle &moduleRecord); + JSHandle &moduleRecord, + [[maybe_unused]]JSRecordInfo *recordInfo); static JSHandle ParseModule(JSThread *thread, const JSPandaFile *jsPandaFile, - const CString &descriptor, const CString &moduleFilename); + const CString &descriptor, const CString &moduleFilename, + JSRecordInfo *recordInfo); static JSHandle ParseCjsModule(JSThread *thread, const JSPandaFile *jsPandaFile); static JSHandle ParseJsonModule(JSThread *thread, const JSPandaFile *jsPandaFile, const CString &moduleFilename, const CString &recordName); static JSHandle ParseNativeModule(JSThread *thread, const CString &moduleRequestName, const CString &baseFileName, ModuleTypes moduleType); static JSTaggedValue JsonParse(JSThread *thread, const JSPandaFile *jsPandaFile, CString entryPoint); + static bool *ModuleLazyImportFlagAccessor(const JSPandaFile *pandaFile, + panda_file::File::EntityId module_lazy_import_flag_id); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_MODULE_MODULE_DATA_EXTRACTOR_H diff --git a/ecmascript/module/module_manager_helper.cpp b/ecmascript/module/module_manager_helper.cpp index c2b46ddf0f..9446b2e2ea 100644 --- a/ecmascript/module/module_manager_helper.cpp +++ b/ecmascript/module/module_manager_helper.cpp @@ -204,4 +204,67 @@ JSTaggedValue ModuleManagerHelper::GetModuleValueFromRecordBinding(JSThread *thr } return GetModuleValue(thread, resolvedModule, binding->GetBindingName()); } + +JSTaggedValue ModuleManagerHelper::GetLazyModuleValueFromIndexBinding(JSThread *thread, + JSHandle module, + JSTaggedValue resolvedBinding) +{ + JSHandle binding(thread, resolvedBinding); + JSHandle moduleRecord(thread, binding->GetModuleRecord()); + ASSERT(moduleRecord->IsString()); + // moduleRecord is string, find at current vm + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle resolvedModule; + if (moduleManager->IsLocalModuleLoaded(moduleRecord.GetTaggedValue())) { + if (moduleManager->IsEvaluatedModule(moduleRecord.GetTaggedValue())) { + resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue()); + } else { + resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue()); + SourceTextModule::Evaluate(thread, resolvedModule, nullptr); + if (thread->HasPendingException()) { + return JSTaggedValue::Undefined(); + } + } + } else { + auto isMergedAbc = !module->GetEcmaModuleRecordName().IsUndefined(); + CString record = ConvertToString(moduleRecord.GetTaggedValue()); + CString fileName = ConvertToString(binding->GetAbcFileName()); + if (!JSPandaFileExecutor::LazyExecuteModule(thread, record, fileName, isMergedAbc)) { + LOG_ECMA(FATAL) << "LazyExecuteModule failed"; + } + resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue()); + } + return GetModuleValue(thread, resolvedModule, binding->GetIndex()); +} + +JSTaggedValue ModuleManagerHelper::GetLazyModuleValueFromRecordBinding( + JSThread *thread, JSHandle module, JSTaggedValue resolvedBinding) +{ + JSHandle binding(thread, resolvedBinding); + JSHandle moduleRecord(thread, binding->GetModuleRecord()); + ASSERT(moduleRecord->IsString()); + // moduleRecord is string, find at current vm + ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); + JSHandle resolvedModule; + if (moduleManager->IsLocalModuleLoaded(moduleRecord.GetTaggedValue())) { + if (moduleManager->IsEvaluatedModule(moduleRecord.GetTaggedValue())) { + resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue()); + } else { + resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue()); + SourceTextModule::Evaluate(thread, resolvedModule, nullptr); + if (thread->HasPendingException()) { + return JSTaggedValue::Undefined(); + } + } + } else { + auto isMergedAbc = !module->GetEcmaModuleRecordName().IsUndefined(); + CString record = ConvertToString(moduleRecord.GetTaggedValue()); + CString fileName = ConvertToString(module->GetEcmaModuleFilename()); + if (!JSPandaFileExecutor::LazyExecuteModule(thread, record, fileName, isMergedAbc)) { + LOG_ECMA(FATAL) << "LazyExecuteModule failed"; + } + resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue()); + } + return GetModuleValue(thread, resolvedModule, binding->GetBindingName()); +} } // namespace panda::ecmascript diff --git a/ecmascript/module/module_manager_helper.h b/ecmascript/module/module_manager_helper.h index 4daf4882d6..15f4f5312b 100644 --- a/ecmascript/module/module_manager_helper.h +++ b/ecmascript/module/module_manager_helper.h @@ -45,6 +45,14 @@ public: static JSTaggedValue PUBLIC_API GetModuleValueFromRecordBinding(JSThread *thread, JSHandle module, JSTaggedValue resolvedBinding); + + static JSTaggedValue GetLazyModuleValueFromIndexBinding(JSThread *thread, + JSHandle module, + JSTaggedValue resolvedBinding); + + static JSTaggedValue GetLazyModuleValueFromRecordBinding(JSThread *thread, + JSHandle module, + JSTaggedValue resolvedBinding); }; } // namespace panda::ecmascript #endif // ECMASCRIPT_MODULE_JS_SHARED_MODULE_H diff --git a/ecmascript/object_factory.cpp b/ecmascript/object_factory.cpp index 5eb9911c3f..1768748c1f 100644 --- a/ecmascript/object_factory.cpp +++ b/ecmascript/object_factory.cpp @@ -4718,6 +4718,8 @@ JSHandle ObjectFactory::NewSourceTextModule() obj->SetTypes(ModuleTypes::UNKNOWN); obj->SetIsNewBcVersion(false); obj->SetRegisterCounts(UINT16_MAX); + bool *tmp = new bool[0]; + obj->SetLazyImportStatus(ToUintPtr(tmp)); obj->SetSharedType(SharedTypes::UNSENDABLE_MODULE); obj->SetSendableEnv(thread_, undefinedValue); return obj; diff --git a/ecmascript/shared_object_factory.cpp b/ecmascript/shared_object_factory.cpp index 7615e89129..73d9083cc6 100644 --- a/ecmascript/shared_object_factory.cpp +++ b/ecmascript/shared_object_factory.cpp @@ -689,6 +689,8 @@ JSHandle ObjectFactory::NewSSourceTextModule() obj->SetTypes(ModuleTypes::UNKNOWN); obj->SetIsNewBcVersion(false); obj->SetRegisterCounts(UINT16_MAX); + bool *tmp = new bool[0]; + obj->SetLazyImportStatus(ToUintPtr(tmp)); obj->SetSharedType(SharedTypes::UNSENDABLE_MODULE); obj->SetSendableEnv(thread_, undefinedValue); return obj; diff --git a/ecmascript/stubs/runtime_stubs-inl.h b/ecmascript/stubs/runtime_stubs-inl.h index 7e9477d3fd..44e48e65ad 100644 --- a/ecmascript/stubs/runtime_stubs-inl.h +++ b/ecmascript/stubs/runtime_stubs-inl.h @@ -1347,6 +1347,17 @@ JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVar(JSThread *thread, int32_t return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(index, jsFunc); } +JSTaggedValue RuntimeStubs::RuntimeLdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc) +{ + return thread->GetCurrentEcmaContext()->GetModuleManager()->GetLazyModuleValueOutter(index, jsFunc); +} + +JSTaggedValue RuntimeStubs::RuntimeLdLazySendableExternalModuleVar( + JSThread *thread, int32_t index, JSTaggedValue jsFunc) +{ + return SharedModuleManager::GetInstance()->GetLazySendableModuleValue(thread, index, jsFunc); +} + JSTaggedValue RuntimeStubs::RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner) { if (inner) { diff --git a/ecmascript/stubs/runtime_stubs.cpp b/ecmascript/stubs/runtime_stubs.cpp index fa49a4263b..56d6474518 100644 --- a/ecmascript/stubs/runtime_stubs.cpp +++ b/ecmascript/stubs/runtime_stubs.cpp @@ -1936,6 +1936,22 @@ DEF_RUNTIME_STUBS(LdSendableExternalModuleVarByIndex) return RuntimeLdSendableExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); } +DEF_RUNTIME_STUBS(LdLazyExternalModuleVarByIndex) +{ + RUNTIME_STUBS_HEADER(LdLazyExternalModuleVarByIndex); + JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter + JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter + return RuntimeLdLazyExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); +} + +DEF_RUNTIME_STUBS(LdLazySendableExternalModuleVarByIndex) +{ + RUNTIME_STUBS_HEADER(LdLazySendableExternalModuleVarByIndex); + JSTaggedValue index = GetArg(argv, argc, 0); // 0: means the zeroth parameter + JSTaggedValue jsFunc = GetArg(argv, argc, 1); // 1: means the first parameter + return RuntimeLdLazySendableExternalModuleVar(thread, index.GetInt(), jsFunc).GetRawData(); +} + DEF_RUNTIME_STUBS(LdLocalModuleVarByIndexOnJSFunc) { RUNTIME_STUBS_HEADER(LdLocalModuleVarByIndexOnJSFunc); diff --git a/ecmascript/stubs/runtime_stubs.h b/ecmascript/stubs/runtime_stubs.h index b1b16938eb..9709e2e8d6 100644 --- a/ecmascript/stubs/runtime_stubs.h +++ b/ecmascript/stubs/runtime_stubs.h @@ -347,6 +347,8 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co V(LdLocalModuleVarByIndex) \ V(LdExternalModuleVarByIndex) \ V(LdSendableExternalModuleVarByIndex) \ + V(LdLazyExternalModuleVarByIndex) \ + V(LdLazySendableExternalModuleVarByIndex) \ V(LdLocalModuleVarByIndexOnJSFunc) \ V(LdExternalModuleVarByIndexOnJSFunc) \ V(LdModuleVar) \ @@ -753,6 +755,10 @@ private: JSTaggedValue jsFunc); static inline JSTaggedValue RuntimeLdExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc); + static inline JSTaggedValue RuntimeLdLazySendableExternalModuleVar(JSThread *thread, int32_t index, + JSTaggedValue jsFunc); + static inline JSTaggedValue RuntimeLdLazyExternalModuleVar(JSThread *thread, int32_t index, + JSTaggedValue jsFunc); static inline JSTaggedValue RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner); static inline JSTaggedValue RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner, JSTaggedValue jsFunc); diff --git a/ecmascript/tests/dump_test.cpp b/ecmascript/tests/dump_test.cpp index 3e38a0c1df..8044fe6483 100644 --- a/ecmascript/tests/dump_test.cpp +++ b/ecmascript/tests/dump_test.cpp @@ -1370,7 +1370,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump) break; } case JSType::SOURCE_TEXT_MODULE_RECORD: { - CHECK_DUMP_FIELDS(ModuleRecord::SIZE, SourceTextModule::SIZE, 17U); + CHECK_DUMP_FIELDS(ModuleRecord::SIZE, SourceTextModule::SIZE, 18U); JSHandle moduleSourceRecord = factory->NewSourceTextModule(); DUMP_FOR_HANDLE(moduleSourceRecord); break; diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 5b61ef9355..9dc2bfe409 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -105,6 +105,7 @@ group("ark_js_moduletest") { "merge", "module", "moduleImportJson", + "moduleLazyImport", "moduleUseCjs", "multiargs", "multiprotoic", diff --git a/test/moduletest/moduleLazyImport/A.js b/test/moduletest/moduleLazyImport/A.js new file mode 100644 index 0000000000..e1b6aedc39 --- /dev/null +++ b/test/moduletest/moduleLazyImport/A.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:moduleCircularCheck + * @tc.desc:check module circular import + * @tc.type: FUNC + * @tc.require: issueI5RC2C + */ + +import ss from './D_Cjs' +import lazy {b} from './B' +print("this is A"); +print(JSON.stringify(ss)); +export class A { + static myMethod() { + print('static'); + } + myMethod() { + print('instance', b); + } +} diff --git a/test/moduletest/moduleLazyImport/B.js b/test/moduletest/moduleLazyImport/B.js new file mode 100644 index 0000000000..b9a7882d4e --- /dev/null +++ b/test/moduletest/moduleLazyImport/B.js @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:moduleCircularCheck + * @tc.desc:check module circular import + * @tc.type: FUNC + * @tc.require: issueI5RC2C + */ + +import {fun} from './C_Cjs' +import foo from './D_Cjs' +export let b = "3"; +print("this is B", JSON.stringify(foo)); +fun(); \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/BUILD.gn b/test/moduletest/moduleLazyImport/BUILD.gn new file mode 100644 index 0000000000..85ef46c8a1 --- /dev/null +++ b/test/moduletest/moduleLazyImport/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("../../test_helper.gni") + +host_moduletest_action("moduleLazyImport") { + deps = [] + entry_point = "--entry-point=moduleLazyImport" + is_module = true + is_merge = true + is_merge_abc = true +} diff --git a/test/moduletest/moduleLazyImport/C_Cjs.js b/test/moduletest/moduleLazyImport/C_Cjs.js new file mode 100644 index 0000000000..0c3df306b3 --- /dev/null +++ b/test/moduletest/moduleLazyImport/C_Cjs.js @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:cjsImportJson + * @tc.desc:test import Json + * @tc.type: FUNC + * @tc.require: issueI5NO8G + */ + +module.exports.fun = function foo5 () { + print("foo5"); +}; +print("this is C_Cjs") \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/D_Cjs.js b/test/moduletest/moduleLazyImport/D_Cjs.js new file mode 100644 index 0000000000..d96b268d08 --- /dev/null +++ b/test/moduletest/moduleLazyImport/D_Cjs.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:moduleCircularCheck + * @tc.desc:check module circular import + * @tc.type: FUNC + * @tc.require: issueI5RC2C + */ +print("this is D_Cjs"); +module.exports = { + foo: "module use cjsModule" +} \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/E.js b/test/moduletest/moduleLazyImport/E.js new file mode 100644 index 0000000000..8e9c479594 --- /dev/null +++ b/test/moduletest/moduleLazyImport/E.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:moduleCircularCheck + * @tc.desc:check module circular import + * @tc.type: FUNC + * @tc.require: issueI5RC2C + */ +export function aaa() { + print("E func"); +} +print("this is E"); \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/F.js b/test/moduletest/moduleLazyImport/F.js new file mode 100644 index 0000000000..81767cd3a3 --- /dev/null +++ b/test/moduletest/moduleLazyImport/F.js @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:moduleCircularCheck + * @tc.desc:check module circular import + * @tc.type: FUNC + * @tc.require: issueI5RC2C + */ +export function func1() { + print("F func"); +} +print("this is F"); \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/expect_output.txt b/test/moduletest/moduleLazyImport/expect_output.txt new file mode 100644 index 0000000000..105a098cc1 --- /dev/null +++ b/test/moduletest/moduleLazyImport/expect_output.txt @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +this is E +this is entry +this is F +F func +this is D_Cjs +this is A +{"foo":"module use cjsModule"} +this is C_Cjs +this is B {"foo":"module use cjsModule"} +foo5 +instance 3 +E func diff --git a/test/moduletest/moduleLazyImport/moduleLazyImport.js b/test/moduletest/moduleLazyImport/moduleLazyImport.js new file mode 100644 index 0000000000..c3a42d8b04 --- /dev/null +++ b/test/moduletest/moduleLazyImport/moduleLazyImport.js @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @tc.name:importJson + * @tc.desc:test import Json + * @tc.type: FUNC + * @tc.require: issueI5NO8G + */ +import lazy {A} from "./A" +import { aaa } from "./E"; +import lazy {func1} from './F'; + +print("this is entry"); +func1(); +let myClass = new A(); +myClass.myMethod(); +aaa(); \ No newline at end of file diff --git a/test/moduletest/moduleLazyImport/moduleLazyImport.txt b/test/moduletest/moduleLazyImport/moduleLazyImport.txt new file mode 100644 index 0000000000..f1c06c78c0 --- /dev/null +++ b/test/moduletest/moduleLazyImport/moduleLazyImport.txt @@ -0,0 +1,7 @@ +A.js;A;esm;A.js;xxAxx +B.js;B;esm;B.js;xxBxx +C_Cjs.js;C_Cjs;commonjs;C_Cjs.js;xxC_Cjsxx +D_Cjs.js;D_Cjs;commonjs;D_Cjs.js;xxD_Cjsxx +E.js;E;esm;E.js;xxExx +F.js;F;esm;F.js;xxFxx +moduleLazyImport.js;moduleLazyImport;esm;moduleLazyImport.js;xxmoduleLazyImportxx \ No newline at end of file diff --git a/test/moduletest/sendableclassuseimport/sendableclassuseimport.ts b/test/moduletest/sendableclassuseimport/sendableclassuseimport.ts index f087461cac..1615032d0d 100644 --- a/test/moduletest/sendableclassuseimport/sendableclassuseimport.ts +++ b/test/moduletest/sendableclassuseimport/sendableclassuseimport.ts @@ -23,7 +23,7 @@ // @ts-nocheck declare function print(str: any): string; -import {Test1, foo2} from "./func" +import lazy {Test1, foo2} from "./func" import {strA, strB} from "./string" class SendableClassA {