diff --git a/ecmascript/base/path_helper.h b/ecmascript/base/path_helper.h new file mode 100644 index 0000000000..bafb28d121 --- /dev/null +++ b/ecmascript/base/path_helper.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 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. + */ +#ifndef ECMASCRIPT_BASE_PATH_HELPER_H +#define ECMASCRIPT_BASE_PATH_HELPER_H + +#include "ecmascript/aot_file_manager.h" +#include "ecmascript/ecma_macros.h" +#include "ecmascript/ecma_string.h" +#include "ecmascript/ecma_vm.h" +#include "ecmascript/global_env.h" +#include "ecmascript/js_tagged_value-inl.h" +#include "ecmascript/jspandafile/js_pandafile.h" + +namespace panda::ecmascript::base { +class PathHelper { +public: + static void ResolveCurrentPath(JSThread *thread, + JSMutableHandle &dirPath, + JSMutableHandle &fileName, + const JSPandaFile *jsPandaFile) + { + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + CString fullName = jsPandaFile->GetJSPandaFileDesc(); + // find last '/' + int foundPos = static_cast(fullName.find_last_of("/\\")); + if (foundPos == -1) { + RETURN_IF_ABRUPT_COMPLETION(thread); + } + CString dirPathStr = fullName.substr(0, foundPos + 1); + JSHandle dirPathName = factory->NewFromUtf8(dirPathStr); + dirPath.Update(dirPathName.GetTaggedValue()); + + // Get filename from JSPandaFile + JSHandle cbFileName = factory->NewFromUtf8(fullName); + fileName.Update(cbFileName.GetTaggedValue()); + } + + static JSHandle ResolveDirPath(JSThread *thread, + JSHandle fileName) + { + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + CString fullName = ConvertToString(fileName.GetTaggedValue()); + // find last '/' + int foundPos = static_cast(fullName.find_last_of("/\\")); + if (foundPos == -1) { + RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); + } + CString dirPathStr = fullName.substr(0, foundPos + 1); + return factory->NewFromUtf8(dirPathStr); + } +}; +} // namespace panda::ecmascript::base +#endif // ECMASCRIPT_BASE_PATH_HELPER_H \ No newline at end of file diff --git a/ecmascript/builtins/builtins_cjs_module.cpp b/ecmascript/builtins/builtins_cjs_module.cpp index 84d821679a..312f582252 100644 --- a/ecmascript/builtins/builtins_cjs_module.cpp +++ b/ecmascript/builtins/builtins_cjs_module.cpp @@ -16,11 +16,14 @@ #include "ecmascript/builtins/builtins_cjs_module.h" #include "ecmascript/base/builtins_base.h" +#include "ecmascript/base/path_helper.h" #include "ecmascript/interpreter/interpreter-inl.h" +#include "ecmascript/platform/file.h" #include "ecmascript/require/js_cjs_module.h" #include "ecmascript/require/js_require_manager.h" namespace panda::ecmascript::builtins { +using PathHelper = base::PathHelper; JSTaggedValue BuiltinsCjsModule::CjsModuleConstructor(EcmaRuntimeCallInfo *argv) { JSThread *thread = argv->GetThread(); @@ -56,15 +59,15 @@ JSTaggedValue BuiltinsCjsModule::ResolveFilename(EcmaRuntimeCallInfo *argv) JSMutableHandle parent(thread, JSTaggedValue::Undefined()); JSMutableHandle dirname(thread, JSTaggedValue::Undefined()); const JSPandaFile *jsPandaFile = EcmaInterpreter::GetNativeCallPandafile(thread); - RequireManager::ResolveCurrentPath(thread, parent, dirname, jsPandaFile); + PathHelper::ResolveCurrentPath(thread, parent, dirname, jsPandaFile); if (length != 1) { // strange arg's number LOG_ECMA(FATAL) << "BuiltinsCjsModule::Load : can only accept one argument"; UNREACHABLE(); } JSHandle requestName = JSHandle::Cast(GetCallArg(argv, 0)); - JSHandle filename = CjsModule::ResolveFilename(thread, dirname.GetTaggedValue(), - requestName.GetTaggedValue()); + JSHandle filename = ResolveFilenameFromNative(thread, dirname.GetTaggedValue(), + requestName.GetTaggedValue()); return filename.GetTaggedValue(); } diff --git a/ecmascript/builtins/builtins_promise_job.cpp b/ecmascript/builtins/builtins_promise_job.cpp index 5a1288ff64..bb6faab02f 100644 --- a/ecmascript/builtins/builtins_promise_job.cpp +++ b/ecmascript/builtins/builtins_promise_job.cpp @@ -15,6 +15,7 @@ #include "ecmascript/builtins/builtins_promise_job.h" +#include "ecmascript/base/path_helper.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/global_env.h" #include "ecmascript/interpreter/interpreter.h" @@ -25,10 +26,12 @@ #include "ecmascript/js_promise.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/module/js_module_manager.h" +#include "ecmascript/platform/file.h" #include "ecmascript/require/js_cjs_module.h" #include "libpandabase/macros.h" namespace panda::ecmascript::builtins { +using PathHelper = base::PathHelper; JSTaggedValue BuiltinsPromiseJob::PromiseReactionJob(EcmaRuntimeCallInfo *argv) { ASSERT(argv); @@ -128,6 +131,7 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv) ASSERT(argv); BUILTINS_API_TRACE(argv->GetThread(), PromiseJob, DynamicImportJob); JSThread *thread = argv->GetThread(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); EcmaVM *vm = thread->GetEcmaVM(); [[maybe_unused]] EcmaHandleScope handleScope(thread); @@ -148,14 +152,22 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv) CString baseFilename = ConvertToString(dirPath.GetTaggedValue()); CString fileNameStr = ""; if (recordName->IsUndefined()) { - moduleName = CjsModule::ResolveFilenameFromNative(thread, dirPath.GetTaggedValue(), - specifierString.GetTaggedValue()); + moduleName = ResolveFilenameFromNative(thread, dirPath.GetTaggedValue(), + specifierString.GetTaggedValue()); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); fileNameStr = ConvertToString(moduleName.GetTaggedValue()); } else { CString recordNameStr = ConvertToString(recordName.GetTaggedValue()); CString requestModule = ConvertToString(specifierString.GetTaggedValue()); const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, baseFilename, recordNameStr.c_str()); + if (jsPandaFile == nullptr) { + LOG_ECMA(ERROR) << "Try to load record " << recordNameStr << " in abc : " << baseFilename; + CString msg = "Faild to load file '" + recordNameStr + "', please check the request path."; + JSTaggedValue error = factory->GetJSError(ErrorType::REFERENCE_ERROR, msg.c_str()).GetTaggedValue(); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + } + entryPoint = ModuleManager::ConcatFileNameWithMerge(jsPandaFile, baseFilename, recordNameStr, requestModule); @@ -164,12 +176,20 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv) } const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, fileNameStr, entryPoint); - bool isModule = jsPandaFile->IsModule(entryPoint); + if (jsPandaFile == nullptr) { + LOG_ECMA(ERROR) << "Try to load record " << entryPoint << " in abc : " << fileNameStr; + CString msg = "Faild to load file '" + entryPoint + "', please check the request path."; + JSTaggedValue error = factory->GetJSError(ErrorType::REFERENCE_ERROR, msg.c_str()).GetTaggedValue(); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); + } + bool isModule = jsPandaFile->IsModule(thread, entryPoint); JSMutableHandle moduleNamespace(thread, JSTaggedValue::Undefined()); if (!vm->GetModuleManager()->IsImportedModuleLoaded(moduleName.GetTaggedValue())) { if (!JSPandaFileExecutor::ExecuteFromFile(thread, fileNameStr.c_str(), entryPoint.c_str(), false, true)) { - LOG_FULL(FATAL) << "Cannot execute dynamic-imported panda file : "<< fileNameStr.c_str() - << entryPoint.c_str(); + LOG_ECMA(ERROR) << "Try to load record " << entryPoint << " in abc : " << fileNameStr; + CString msg = "Cannot execute request dynamic-imported module : " + entryPoint; + JSTaggedValue error = factory->GetJSError(ErrorType::REFERENCE_ERROR, msg.c_str()).GetTaggedValue(); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, JSTaggedValue::Exception()); } } if (thread->HasPendingException()) { diff --git a/ecmascript/compiler/pass_manager.cpp b/ecmascript/compiler/pass_manager.cpp index f7c9fbe458..b5c984c214 100644 --- a/ecmascript/compiler/pass_manager.cpp +++ b/ecmascript/compiler/pass_manager.cpp @@ -135,9 +135,11 @@ void PassManager::ResolveModule(const JSPandaFile *jsPandaFile, const std::strin { const auto &recordInfo = jsPandaFile->GetJSRecordInfo(); ModuleManager *moduleManager = vm_->GetModuleManager(); + JSThread *thread = vm_->GetJSThread(); for (auto info: recordInfo) { auto recordName = info.first; - if (jsPandaFile->IsModule(recordName)) { + if (jsPandaFile->IsModule(thread, recordName)) { + ASSERT(!thread->HasPendingException()); moduleManager->HostResolveImportedModuleWithMerge(fileName.c_str(), recordName); } } diff --git a/ecmascript/ecma_macros.h b/ecmascript/ecma_macros.h index 3ed976f3be..dc7ddc65f0 100644 --- a/ecmascript/ecma_macros.h +++ b/ecmascript/ecma_macros.h @@ -310,6 +310,21 @@ return (value); \ } while (false) +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, errorType, type, message) \ + do { \ + if ((thread)->HasPendingException()) { \ + return JSHandle(thread, JSTaggedValue::Exception()); \ + } \ + ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory(); \ + JSHandle _error = _factory->GetJSError(errorType, message); \ + (thread)->SetException(_error.GetTaggedValue()); \ + if ((thread)->IsPrintBCOffset()) { \ + (thread)->CollectBCOffsetInfo(); \ + } \ + return JSHandle(thread, JSTaggedValue::Exception()); \ + } while (false) + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, errorType, message, value) \ do { \ diff --git a/ecmascript/ecma_vm.cpp b/ecmascript/ecma_vm.cpp index af12ca06e5..80b685de47 100644 --- a/ecmascript/ecma_vm.cpp +++ b/ecmascript/ecma_vm.cpp @@ -15,6 +15,7 @@ #include "ecmascript/ecma_vm.h" +#include "ecmascript/base/path_helper.h" #include "ecmascript/base/string_helper.h" #include "ecmascript/builtins/builtins.h" #include "ecmascript/builtins/builtins_collator.h" @@ -92,6 +93,7 @@ #endif namespace panda::ecmascript { +using PathHelper = base::PathHelper; /* static */ EcmaVM *EcmaVM::Create(const JSRuntimeOptions &options, EcmaParamConfiguration &config) { @@ -455,7 +457,7 @@ Expected EcmaVM::InvokeEcmaEntrypoint(const JSPandaFile *js JSHandle func(thread_, program->GetMainFunction()); JSHandle global = GlobalEnv::Cast(globalEnv_.GetTaggedObject())->GetJSGlobalObject(); JSHandle undefined = thread_->GlobalConstants()->GetHandledUndefined(); - if (jsPandaFile->IsModule(entryPoint.data())) { + if (jsPandaFile->IsModule(thread_, entryPoint.data())) { global = undefined; CString moduleName = jsPandaFile->GetJSPandaFileDesc(); if (!jsPandaFile->IsBundlePack()) { @@ -476,8 +478,10 @@ Expected EcmaVM::InvokeEcmaEntrypoint(const JSPandaFile *js EcmaRuntimeStatScope runtimeStatScope(this); result = InvokeEcmaAotEntrypoint(func, global, jsPandaFile, entryPoint); } else { - if (jsPandaFile->IsCjs(entryPoint.data())) { - CJSExecution(func, global, jsPandaFile); + if (jsPandaFile->IsCjs(thread_, entryPoint.data())) { + if (!thread_->HasPendingException()) { + CJSExecution(func, global, jsPandaFile); + } } else { EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread_, JSHandle(func), global, undefined, 0); @@ -557,11 +561,11 @@ void EcmaVM::CJSExecution(JSHandle &func, JSHandle &t JSMutableHandle filename(thread_, JSTaggedValue::Undefined()); JSMutableHandle dirname(thread_, JSTaggedValue::Undefined()); if (jsPandaFile->IsBundlePack()) { - RequireManager::ResolveCurrentPath(thread_, dirname, filename, jsPandaFile); + PathHelper::ResolveCurrentPath(thread_, dirname, filename, jsPandaFile); } else { filename.Update(func->GetModule()); ASSERT(filename->IsString()); - RequireManager::ResolveDirPath(thread_, dirname, filename); + dirname.Update(PathHelper::ResolveDirPath(thread_, filename)); } CJSInfo cjsInfo(module, require, exports, filename, dirname); RequireManager::InitializeCommonJS(thread_, cjsInfo); diff --git a/ecmascript/ecma_vm.h b/ecmascript/ecma_vm.h index ec6ea9381b..069529be34 100644 --- a/ecmascript/ecma_vm.h +++ b/ecmascript/ecma_vm.h @@ -382,17 +382,6 @@ public: } } - // CJS callbacks - void SetResolvePathCallback(ResolvePathCallback cb) - { - resolvePathCallback_ = cb; - } - - ResolvePathCallback GetResolvePathCallback() const - { - return resolvePathCallback_; - } - void SetResolveBufferCallback(ResolveBufferCallback cb) { resolveBufferCallback_ = cb; @@ -474,6 +463,11 @@ public: return false; } + bool IsWorkerThread() + { + return options_.IsWorker(); + } + bool IsBundlePack() const { return isBundlePack_; @@ -589,10 +583,10 @@ public: return optCodeProfiler_; } -protected: - void HandleUncaughtException(JSTaggedValue exception); +protected: + void PrintJSErrorInfo(const JSHandle &exceptionInfo); private: diff --git a/ecmascript/jspandafile/js_pandafile.cpp b/ecmascript/jspandafile/js_pandafile.cpp index ef8ac82d48..5ed8fd8340 100644 --- a/ecmascript/jspandafile/js_pandafile.cpp +++ b/ecmascript/jspandafile/js_pandafile.cpp @@ -204,7 +204,7 @@ MethodLiteral *JSPandaFile::FindMethodLiteral(uint32_t offset) const return iter->second; } -bool JSPandaFile::IsModule(const CString &recordName) const +bool JSPandaFile::IsModule(JSThread *thread, const CString &recordName) const { if (IsBundlePack()) { return jsRecordInfo_.begin()->second.moduleRecordIdx != -1; @@ -213,11 +213,11 @@ bool JSPandaFile::IsModule(const CString &recordName) const if (info != jsRecordInfo_.end()) { return info->second.moduleRecordIdx != -1; } - LOG_FULL(FATAL) << "find entryPoint failed: " << recordName; - UNREACHABLE(); + CString msg = "Faild to load file '" + recordName + "', please check the request path."; + THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), false); } -bool JSPandaFile::IsCjs(const CString &recordName) const +bool JSPandaFile::IsCjs(JSThread *thread, const CString &recordName) const { if (IsBundlePack()) { return jsRecordInfo_.begin()->second.isCjs; @@ -226,8 +226,8 @@ bool JSPandaFile::IsCjs(const CString &recordName) const if (info != jsRecordInfo_.end()) { return info->second.isCjs; } - LOG_FULL(FATAL) << "find entryPoint failed: " << recordName; - UNREACHABLE(); + CString msg = "Faild to load file '" + recordName + "', please check the request path."; + THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), false); } bool JSPandaFile::IsJson(JSThread *thread, const CString &recordName) const @@ -239,8 +239,8 @@ bool JSPandaFile::IsJson(JSThread *thread, const CString &recordName) const if (info != jsRecordInfo_.end()) { return info->second.isJson; } - CString message = "find entryPoint failed: " + recordName; - THROW_REFERENCE_ERROR_AND_RETURN(thread, message.c_str(), false); + CString msg = "Faild to load file '" + recordName + "', please check the request path."; + THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), false); } CString JSPandaFile::GetJsonStringId(JSThread *thread, const CString &recordName) const @@ -255,11 +255,11 @@ CString JSPandaFile::GetJsonStringId(JSThread *thread, const CString &recordName StringData sd = GetStringData(EntityId(info->second.jsonStringId)); return utf::Mutf8AsCString(sd.data); } - CString message = "find jsonStringId failed: " + recordName; - THROW_REFERENCE_ERROR_AND_RETURN(thread, message.c_str(), ""); + CString msg = "Faild to load file '" + recordName + "', please check the request path."; + THROW_REFERENCE_ERROR_AND_RETURN(thread, msg.c_str(), ""); } -CString JSPandaFile::FindEntryPoint(const CString &recordName) const +CString JSPandaFile::FindNpmEntryPoint(const CString &recordName) const { if (HasRecord(recordName)) { return recordName; diff --git a/ecmascript/jspandafile/js_pandafile.h b/ecmascript/jspandafile/js_pandafile.h index d43a462463..aa59614192 100644 --- a/ecmascript/jspandafile/js_pandafile.h +++ b/ecmascript/jspandafile/js_pandafile.h @@ -230,9 +230,9 @@ public: return pf_->GetHeader()->file_size; } - bool PUBLIC_API IsModule(const CString &recordName = ENTRY_FUNCTION_NAME) const; + bool PUBLIC_API IsModule(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME) const; - bool IsCjs(const CString &recordName = ENTRY_FUNCTION_NAME) const; + bool IsCjs(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME) const; bool IsJson(JSThread *thread, const CString &recordName = ENTRY_FUNCTION_NAME) const; @@ -298,7 +298,7 @@ public: void CheckIsBundlePack(); void CheckIsNewRecord(EcmaVM *vm); - CString FindEntryPoint(const CString &record) const; + CString FindNpmEntryPoint(const CString &record) const; static CString ParseOhmUrl(EcmaVM *vm, const CString &inputFileName, CString &outFileName); static std::string ParseHapPath(const CString &fileName); diff --git a/ecmascript/jspandafile/js_pandafile_executor.cpp b/ecmascript/jspandafile/js_pandafile_executor.cpp index e4e52353f2..966854bc6f 100644 --- a/ecmascript/jspandafile/js_pandafile_executor.cpp +++ b/ecmascript/jspandafile/js_pandafile_executor.cpp @@ -70,11 +70,15 @@ Expected JSPandaFileExecutor::ExecuteFromFile(JSThread *thr JSPandaFile::CroppingRecord(entry); } } - bool isModule = jsPandaFile->IsModule(entry.c_str()); + bool isModule = jsPandaFile->IsModule(thread, entry.c_str()); + if (thread->HasPendingException()) { + vm->HandleUncaughtException(thread->GetException()); + return JSTaggedValue::Undefined(); + } if (isModule) { [[maybe_unused]] EcmaHandleScope scope(thread); ModuleManager *moduleManager = vm->GetModuleManager(); - JSHandle moduleRecord(thread->GlobalConstants()->GetHandledUndefined()); + JSHandle moduleRecord(thread->GlobalConstants()->GetHandledUndefined()); if (jsPandaFile->IsBundlePack()) { moduleRecord = moduleManager->HostResolveImportedModule(name); } else { @@ -87,9 +91,9 @@ Expected JSPandaFileExecutor::ExecuteFromFile(JSThread *thr } return JSTaggedValue::Undefined(); } - - moduleRecord->SetStatus(ModuleStatus::INSTANTIATED); - SourceTextModule::Evaluate(thread, moduleRecord, nullptr, 0, excuteFromJob); + JSHandle module = JSHandle::Cast(moduleRecord); + module->SetStatus(ModuleStatus::INSTANTIATED); + SourceTextModule::Evaluate(thread, module, nullptr, 0, excuteFromJob); return JSTaggedValue::Undefined(); } return JSPandaFileExecutor::Execute(thread, jsPandaFile, entry.c_str(), excuteFromJob); @@ -107,7 +111,7 @@ Expected JSPandaFileExecutor::ExecuteFromBuffer(JSThread *t } CString entry = entryPoint.data(); - bool isModule = jsPandaFile->IsModule(entry); + bool isModule = jsPandaFile->IsModule(thread, entry); bool isBundle = jsPandaFile->IsBundlePack(); if (isModule) { return CommonExecuteBuffer(thread, isBundle, normalName, entry, buffer, size); @@ -135,8 +139,16 @@ Expected JSPandaFileExecutor::ExecuteModuleBuffer( const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, name, entry.c_str(), buffer, size); if (jsPandaFile == nullptr) { - return Unexpected(false); + if (thread->GetEcmaVM()->IsWorkerThread()) { + CString mesWorker = "Excute worker's entryPoint failed: " + entry + + ". Please check worker's reference path ."; + THROW_REFERENCE_ERROR_AND_RETURN(thread, mesWorker.c_str(), Unexpected(false)); + } + CString message = "Excute file's entryPoint failed: " + entry + + ". Please check the reference path ."; + THROW_REFERENCE_ERROR_AND_RETURN(thread, message.c_str(), Unexpected(false)); } + ASSERT(jsPandaFile->IsModule(thread, entry.c_str())); bool isBundle = jsPandaFile->IsBundlePack(); if (!isBundle) { const_cast(jsPandaFile)->CheckIsNewRecord(vm); @@ -144,7 +156,7 @@ Expected JSPandaFileExecutor::ExecuteModuleBuffer( JSPandaFile::CroppingRecord(entry); } } - ASSERT(jsPandaFile->IsModule(entry.c_str())); + ASSERT(jsPandaFile->IsModule(thread, entry.c_str())); return CommonExecuteBuffer(thread, isBundle, name, entry, buffer, size); } @@ -155,7 +167,7 @@ Expected JSPandaFileExecutor::CommonExecuteBuffer(JSThread EcmaVM *vm = thread->GetEcmaVM(); ModuleManager *moduleManager = vm->GetModuleManager(); moduleManager->SetExecuteMode(true); - JSHandle moduleRecord(thread->GlobalConstants()->GetHandledUndefined()); + JSHandle moduleRecord(thread->GlobalConstants()->GetHandledUndefined()); if (isBundle) { moduleRecord = moduleManager->HostResolveImportedModule(buffer, size, filename); } else { @@ -166,8 +178,9 @@ Expected JSPandaFileExecutor::CommonExecuteBuffer(JSThread vm->HandleUncaughtException(thread->GetException()); return JSTaggedValue::Undefined(); } - moduleRecord->SetStatus(ModuleStatus::INSTANTIATED); - SourceTextModule::Evaluate(thread, moduleRecord, buffer, size); + JSHandle module = JSHandle::Cast(moduleRecord); + module->SetStatus(ModuleStatus::INSTANTIATED); + SourceTextModule::Evaluate(thread, module, buffer, size); return JSTaggedValue::Undefined(); } diff --git a/ecmascript/jspandafile/literal_data_extractor.cpp b/ecmascript/jspandafile/literal_data_extractor.cpp index 7a89c56824..140f7d437f 100644 --- a/ecmascript/jspandafile/literal_data_extractor.cpp +++ b/ecmascript/jspandafile/literal_data_extractor.cpp @@ -267,7 +267,7 @@ JSHandle LiteralDataExtractor::DefineMethodInLiteral(JSThread *threa moduleName = entryPoint; entry = entryPoint; } - if (jsPandaFile->IsModule(entry)) { + if (jsPandaFile->IsModule(thread, entry)) { EcmaVM *vm = thread->GetEcmaVM(); JSHandle module = vm->GetModuleManager()->HostGetImportedModule(moduleName); jsFunc->SetModule(thread, module.GetTaggedValue()); diff --git a/ecmascript/jspandafile/panda_file_translator.cpp b/ecmascript/jspandafile/panda_file_translator.cpp index 647edfb80e..57ce593307 100644 --- a/ecmascript/jspandafile/panda_file_translator.cpp +++ b/ecmascript/jspandafile/panda_file_translator.cpp @@ -223,11 +223,12 @@ void PandaFileTranslator::ParseFuncAndLiteralConstPool(EcmaVM *vm, const JSPanda JSHandle constpool) { auto &recordInfo = const_cast(jsPandaFile)->FindRecordInfo(entryPoint); + JSThread *thread = vm->GetJSThread(); + ASSERT(!thread->HasPendingException()); if (recordInfo.IsParsedConstpoolOfCurrentVM(vm)) { return; } - JSThread *thread = vm->GetJSThread(); ObjectFactory *factory = vm->GetFactory(); [[maybe_unused]] EcmaHandleScope handleScope(thread); diff --git a/ecmascript/jspandafile/tests/js_pandafile_test.cpp b/ecmascript/jspandafile/tests/js_pandafile_test.cpp index 085aecc99a..c890566817 100644 --- a/ecmascript/jspandafile/tests/js_pandafile_test.cpp +++ b/ecmascript/jspandafile/tests/js_pandafile_test.cpp @@ -271,8 +271,8 @@ HWTEST_F_L0(JSPandaFileTest, IsModule_IsCjs) )"; const CString fileName1 = "test1.pa"; JSPandaFile *pf1 = CreateJSPandaFile(source1, fileName1); - EXPECT_EQ(pf1->IsModule(), false); - EXPECT_EQ(pf1->IsCjs(), false); + EXPECT_EQ(pf1->IsModule(thread), false); + EXPECT_EQ(pf1->IsCjs(thread), false); JSPandaFileManager::RemoveJSPandaFile(pf1); } diff --git a/ecmascript/module/js_module_manager.cpp b/ecmascript/module/js_module_manager.cpp index 08439c4b56..4a38e974b8 100644 --- a/ecmascript/module/js_module_manager.cpp +++ b/ecmascript/module/js_module_manager.cpp @@ -279,8 +279,8 @@ bool ModuleManager::IsImportedModuleLoaded(JSTaggedValue referencing) return (entry != -1); } -JSHandle ModuleManager::HostResolveImportedModuleWithMerge(const CString &moduleFileName, - const CString &recordName) +JSHandle ModuleManager::HostResolveImportedModuleWithMerge(const CString &moduleFileName, + const CString &recordName) { JSThread *thread = vm_->GetJSThread(); ObjectFactory *factory = vm_->GetFactory(); @@ -289,7 +289,7 @@ JSHandle ModuleManager::HostResolveImportedModuleWithMerge(con NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject()); int entry = dict->FindEntry(recordNameHandle.GetTaggedValue()); if (entry != -1) { - return JSHandle(thread, dict->GetValue(entry)); + return JSHandle(thread, dict->GetValue(entry)); } const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->FindJSPandaFile(moduleFileName); if (jsPandaFile == nullptr) { @@ -312,11 +312,14 @@ JSHandle ModuleManager::HostResolveImportedModuleWithMerge(con } } if (jsPandaFile == nullptr) { - LOG_FULL(FATAL) << "open jsPandaFile " << moduleFileName << " error"; - UNREACHABLE(); + LOG_ECMA(ERROR) << "Try to load record " << recordName << " in abc : " << moduleFileName; + CString msg = "Faild to load file '" + recordName + "', please check the request path."; + + THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str()); } - JSHandle moduleRecord = ResolveModuleWithMerge(thread, jsPandaFile, recordName); + JSHandle moduleRecord = ResolveModuleWithMerge(thread, jsPandaFile, recordName); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); JSHandle handleDict(thread, resolvedModules_); resolvedModules_ = NameDictionary::Put(thread, handleDict, JSHandle(recordNameHandle), JSHandle(moduleRecord), PropertyAttributes::Default()) @@ -325,40 +328,42 @@ JSHandle ModuleManager::HostResolveImportedModuleWithMerge(con return moduleRecord; } -JSHandle ModuleManager::HostResolveImportedModule(const CString &referencingModule) +JSHandle ModuleManager::HostResolveImportedModule(const CString &referencingModule) { JSThread *thread = vm_->GetJSThread(); ObjectFactory *factory = vm_->GetFactory(); JSHandle referencingHandle = factory->NewFromUtf8(referencingModule); CString moduleFileName = referencingModule; - if (!vm_->GetResolvePathCallback()) { + if (vm_->IsBundlePack()) { if (AOTFileManager::GetAbsolutePath(referencingModule, moduleFileName)) { referencingHandle = factory->NewFromUtf8(moduleFileName); } else { - LOG_FULL(FATAL) << "absolute " << referencingModule << " path error"; - UNREACHABLE(); + CString msg = "Parse absolute " + referencingModule + " path failed"; + THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str()); } } NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject()); int entry = dict->FindEntry(referencingHandle.GetTaggedValue()); if (entry != -1) { - return JSHandle(thread, dict->GetValue(entry)); + return JSHandle(thread, dict->GetValue(entry)); } const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFileName, JSPandaFile::ENTRY_MAIN_FUNCTION); if (jsPandaFile == nullptr) { - LOG_FULL(FATAL) << "open jsPandaFile " << moduleFileName << " error"; - UNREACHABLE(); + LOG_ECMA(ERROR) << "Try to load abc : " << moduleFileName; + CString msg = "Faild to load file '" + moduleFileName + "', please check the request path."; + + THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str()); } return ResolveModule(thread, jsPandaFile); } -JSHandle ModuleManager::HostResolveImportedModule(const void *buffer, size_t size, - const CString &filename) +JSHandle ModuleManager::HostResolveImportedModule(const void *buffer, size_t size, + const CString &filename) { JSThread *thread = vm_->GetJSThread(); ObjectFactory *factory = vm_->GetFactory(); @@ -367,34 +372,32 @@ JSHandle ModuleManager::HostResolveImportedModule(const void * NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject()); int entry = dict->FindEntry(referencingHandle.GetTaggedValue()); if (entry != -1) { - return JSHandle(thread, dict->GetValue(entry)); + return JSHandle(thread, dict->GetValue(entry)); } const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, filename, JSPandaFile::ENTRY_MAIN_FUNCTION, buffer, size); if (jsPandaFile == nullptr) { - LOG_FULL(FATAL) << "open jsPandaFile " << filename << " error"; - UNREACHABLE(); + CString msg = "Faild to load file '" + filename + "', please check the request path."; + THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str()); } return ResolveModule(thread, jsPandaFile); } -JSHandle ModuleManager::ResolveModule(JSThread *thread, const JSPandaFile *jsPandaFile) +JSHandle ModuleManager::ResolveModule(JSThread *thread, const JSPandaFile *jsPandaFile) { ObjectFactory *factory = vm_->GetFactory(); CString moduleFileName = jsPandaFile->GetJSPandaFileDesc(); JSHandle moduleRecord = thread->GlobalConstants()->GetHandledUndefined(); - if (jsPandaFile->IsCjs()) { - moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile); - } else if (jsPandaFile->IsModule()) { + if (jsPandaFile->IsModule(thread)) { moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, moduleFileName, moduleFileName); } else if (jsPandaFile->IsJson(thread)) { moduleRecord = ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, moduleFileName); } else { - LOG_FULL(FATAL) << "jsPandaFile: " << moduleFileName << " is not CjsModule or EcmaModule or JsonModule"; - UNREACHABLE(); + ASSERT(jsPandaFile->IsCjs(thread)); + moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile); } JSHandle dict(thread, resolvedModules_); @@ -402,117 +405,29 @@ JSHandle ModuleManager::ResolveModule(JSThread *thread, const resolvedModules_ = NameDictionary::Put(thread, dict, referencingHandle, moduleRecord, PropertyAttributes::Default()) .GetTaggedValue(); - return JSHandle::Cast(moduleRecord); + return moduleRecord; } -JSHandle ModuleManager::ResolveModuleWithMerge( +JSHandle ModuleManager::ResolveModuleWithMerge( JSThread *thread, const JSPandaFile *jsPandaFile, const CString &recordName) { ObjectFactory *factory = vm_->GetFactory(); CString moduleFileName = jsPandaFile->GetJSPandaFileDesc(); JSHandle moduleRecord = thread->GlobalConstants()->GetHandledUndefined(); - if (jsPandaFile->IsCjs(recordName)) { - moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile); - } else if (jsPandaFile->IsModule(recordName)) { + if (jsPandaFile->IsModule(thread, recordName)) { + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); moduleRecord = ModuleDataExtractor::ParseModule(thread, jsPandaFile, recordName, moduleFileName); } else if (jsPandaFile->IsJson(thread, recordName)) { moduleRecord = ModuleDataExtractor::ParseJsonModule(thread, jsPandaFile, moduleFileName, recordName); } else { - LOG_FULL(FATAL) << "jsPandaFile: " << moduleFileName << " is not CjsModule or EcmaModule or JsonModule"; - UNREACHABLE(); + ASSERT(jsPandaFile->IsCjs(thread, recordName)); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); + moduleRecord = ModuleDataExtractor::ParseCjsModule(thread, jsPandaFile); } JSHandle recordNameHandle = JSHandle::Cast(factory->NewFromUtf8(recordName)); JSHandle::Cast(moduleRecord)->SetEcmaModuleRecordName(thread, recordNameHandle); - return JSHandle::Cast(moduleRecord); -} - -void ModuleManager::ConcatFileName(std::string &dirPath, std::string &requestPath, std::string &fileName) -{ - JSThread *thread = vm_->GetJSThread(); - int suffixEnd = static_cast(requestPath.find_last_of('.')); - if (suffixEnd == -1) { - RETURN_IF_ABRUPT_COMPLETION(thread); - } -#if defined(PANDA_TARGET_WINDOWS) - if (requestPath[1] == ':') { // absoluteFilePath - fileName = requestPath.substr(0, suffixEnd) + ".abc"; - } else { - int pos = static_cast(dirPath.find_last_of('\\')); - if (pos == -1) { - RETURN_IF_ABRUPT_COMPLETION(thread); - } - fileName = dirPath.substr(0, pos + 1) + requestPath.substr(0, suffixEnd) + ".abc"; - } -#else - if (requestPath.find("./") == 0) { - requestPath = requestPath.substr(2); // 2 : delete './' - suffixEnd -= 2; // 2 : delete './' - } - if (requestPath[0] == '/') { // absoluteFilePath - fileName = requestPath.substr(0, suffixEnd) + ".abc"; - } else { - int pos = static_cast(dirPath.find_last_of('/')); - if (pos == -1) { - RETURN_IF_ABRUPT_COMPLETION(thread); - } - fileName = dirPath.substr(0, pos + 1) + requestPath.substr(0, suffixEnd) + ".abc"; - } -#endif -} - -JSHandle ModuleManager::HostResolveImportedModule(std::string &baseFilename, - std::string &moduleFilename) -{ - JSThread *thread = vm_->GetJSThread(); - bool mode = GetCurrentMode(); - std::string moduleFullname; - if (!mode) { - ResolvePathCallback resolvePathCallback = thread->GetEcmaVM()->GetResolvePathCallback(); - if (resolvePathCallback != nullptr) { - moduleFullname = resolvePathCallback(baseFilename, moduleFilename); - if (moduleFullname == "") { - LOG_FULL(FATAL) << "dirPath: " << baseFilename << "\n" << " requestPath: " << moduleFilename << "\n" - << " moduleRequest callbackModuleName is hole failed"; - UNREACHABLE(); - } - return HostResolveImportedModule(moduleFullname.c_str()); - } - ConcatFileName(baseFilename, moduleFilename, moduleFullname); - return HostResolveImportedModule(moduleFullname.c_str()); - } else { - // mode == true buffer -#if !defined(PANDA_TARGET_WINDOWS) && !defined(PANDA_TARGET_MACOS) - ResolveBufferCallback resolveBufferCallback = thread->GetEcmaVM()->GetResolveBufferCallback(); - if (resolveBufferCallback != nullptr) { - std::vector data = resolveBufferCallback(baseFilename); - size_t size = data.size(); - if (data.empty()) { - LOG_FULL(FATAL) << " moduleRequest callbackModuleName " << moduleFullname << "is hole failed"; - UNREACHABLE(); - } - ConcatFileName(baseFilename, moduleFilename, moduleFullname); - return HostResolveImportedModule(data.data(), - size, moduleFullname.c_str()); - } -#else - ResolvePathCallback resolvePathCallback = thread->GetEcmaVM()->GetResolvePathCallback(); - std::string modulePath = moduleFilename; -#ifdef PANDA_TARGET_WINDOWS - replace(modulePath.begin(), modulePath.end(), '/', '\\'); -#endif - if (resolvePathCallback != nullptr) { - moduleFullname = resolvePathCallback(baseFilename, modulePath); - if (moduleFullname == "") { - LOG_FULL(FATAL) << "dirPath: " << baseFilename << "\n" << " requestPath: " << modulePath << "\n" - << " moduleRequest callbackModuleName is hole failed"; - UNREACHABLE(); - } - return HostResolveImportedModule(moduleFullname.c_str()); - } -#endif - return JSHandle(thread, JSTaggedValue::Undefined()); - } + return moduleRecord; } void ModuleManager::AddResolveImportedModule(const JSPandaFile *jsPandaFile, const CString &referencingModule) @@ -557,7 +472,7 @@ JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedV JSTaggedValue requestedModule = module->GetRequestedModules(); JSTaggedValue moduleName = TaggedArray::Cast(requestedModule.GetTaggedObject())->Get(index); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); - JSHandle requiredModule; + JSHandle requiredModule; if (moduleRecordName.IsUndefined()) { requiredModule = SourceTextModule::HostResolveImportedModule(thread, JSHandle(thread, module), JSHandle(thread, moduleName)); @@ -566,13 +481,16 @@ JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedV requiredModule = SourceTextModule::HostResolveImportedModuleWithMerge(thread, JSHandle(thread, module), JSHandle(thread, moduleName)); } - // if requiredModule is CommonJS - if (requiredModule->GetTypes() == ModuleTypes::CJSMODULE) { - JSHandle cjsModuleName(thread, GetModuleName(requiredModule.GetTaggedValue())); + + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception()); + // if requiredModuleST is CommonJS + JSHandle requiredModuleST = JSHandle::Cast(requiredModule); + if (requiredModuleST->GetTypes() == ModuleTypes::CJSMODULE) { + JSHandle cjsModuleName(thread, GetModuleName(requiredModuleST.GetTaggedValue())); return CjsModule::SearchFromModuleCache(thread, cjsModuleName).GetTaggedValue(); } - // if requiredModule is ESM - JSHandle moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule); + // if requiredModuleST is ESM + JSHandle moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModuleST); ASSERT(moduleNamespace->IsModuleNamespace()); return moduleNamespace.GetTaggedValue(); } @@ -691,6 +609,9 @@ CString ModuleManager::ConcatFileNameWithMerge(const JSPandaFile *jsPandaFile, C while ((pos = PackageName.rfind(JSPandaFile::NODE_MODULES)) != CString::npos) { key = PackageName + "/" + JSPandaFile::NODE_MODULES + moduleRequestName; AddIndexToEntryPoint(jsPandaFile, entryPoint, key); + if (entryPoint.empty()) { + break; + } PackageName = PackageName.substr(0, pos > 0 ? pos - 1 : 0); } } @@ -731,10 +652,10 @@ bool ModuleManager::IsImportedPath(const CString &moduleRequestName, size_t &typ void ModuleManager::AddIndexToEntryPoint(const JSPandaFile *jsPandaFile, CString &entryPoint, CString &key) { - entryPoint = jsPandaFile->FindEntryPoint(key); + entryPoint = jsPandaFile->FindNpmEntryPoint(key); if (entryPoint.empty()) { key += "/index"; - entryPoint = jsPandaFile->FindEntryPoint(key); + entryPoint = jsPandaFile->FindNpmEntryPoint(key); } } diff --git a/ecmascript/module/js_module_manager.h b/ecmascript/module/js_module_manager.h index b67c8faa53..6f2f4759fd 100644 --- a/ecmascript/module/js_module_manager.h +++ b/ecmascript/module/js_module_manager.h @@ -52,17 +52,20 @@ public: JSHandle HostGetImportedModule(JSTaggedValue referencing); bool IsImportedModuleLoaded(JSTaggedValue referencing); - JSHandle HostResolveImportedModule(const void *buffer, size_t size, const CString &filename); - JSHandle HostResolveImportedModule(std::string &baseFilename, std::string &moduleFilename); - JSHandle HostResolveImportedModule(const CString &referencingModule); - JSHandle PUBLIC_API HostResolveImportedModuleWithMerge(const CString &referencingModule, - const CString &recordName); + JSHandle HostResolveImportedModule(const void *buffer, size_t size, const CString &filename); + JSHandle HostResolveImportedModule(const CString &referencingModule); + JSHandle PUBLIC_API HostResolveImportedModuleWithMerge(const CString &referencingModule, + const CString &recordName); JSTaggedValue GetCurrentModule(); void AddResolveImportedModule(const JSPandaFile *jsPandaFile, const CString &referencingModule); void AddResolveImportedModule(const CString &referencingModule, JSHandle moduleRecord); void Iterate(const RootVisitor &v); + + static CString ConcatFileNameWithMerge(const JSPandaFile *jsPandaFile, CString &baseFilename, + CString moduleRecordName, CString moduleRequestName); + bool GetCurrentMode() const { return isExecuteBuffer_; @@ -71,9 +74,7 @@ public: { isExecuteBuffer_ = mode; } - void ConcatFileName(std::string &dirPath, std::string &requestPath, std::string &fileName); - static CString ConcatFileNameWithMerge(const JSPandaFile *jsPandaFile, CString &baseFilename, - CString moduleRecordName, CString moduleRequestName); + static CString GetRecordName(JSTaggedValue module); static int GetExportObjectIndex(EcmaVM *vm, JSHandle ecmaModule, const std::string &key); static bool IsImportedPath(const CString &moduleRequestName, size_t &typePos); @@ -93,9 +94,9 @@ private: JSTaggedValue key, JSTaggedValue value); // deprecated end - JSHandle ResolveModule(JSThread *thread, const JSPandaFile *jsPandaFile); - JSHandle ResolveModuleWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile, - const CString &recodeName); + JSHandle ResolveModule(JSThread *thread, const JSPandaFile *jsPandaFile); + JSHandle ResolveModuleWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile, + const CString &recodeName); static constexpr uint32_t DEAULT_DICTIONART_CAPACITY = 4; diff --git a/ecmascript/module/js_module_record.cpp b/ecmascript/module/js_module_record.cpp index c915de5747..e707eef706 100644 --- a/ecmascript/module/js_module_record.cpp +++ b/ecmascript/module/js_module_record.cpp @@ -20,8 +20,7 @@ namespace panda::ecmascript { int32_t ModuleRecord::Instantiate(JSThread *thread, const JSHandle &module) { if (module->IsSourceTextModule()) { - JSHandle moduleRecord = JSHandle::Cast(module); - return SourceTextModule::Instantiate(thread, moduleRecord); + return SourceTextModule::Instantiate(thread, module); } LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); diff --git a/ecmascript/module/js_module_source_text.cpp b/ecmascript/module/js_module_source_text.cpp index 08e79a4bde..e868e7e690 100644 --- a/ecmascript/module/js_module_source_text.cpp +++ b/ecmascript/module/js_module_source_text.cpp @@ -16,6 +16,7 @@ #include "ecmascript/module/js_module_source_text.h" #include "ecmascript/global_env.h" +#include "ecmascript/base/path_helper.h" #include "ecmascript/base/string_helper.h" #include "ecmascript/jspandafile/js_pandafile_executor.h" #include "ecmascript/jspandafile/js_pandafile_manager.h" @@ -23,6 +24,7 @@ #include "ecmascript/linked_hash_table.h" #include "ecmascript/module/js_module_manager.h" #include "ecmascript/module/js_module_namespace.h" +#include "ecmascript/platform/file.h" #include "ecmascript/tagged_dictionary.h" namespace panda::ecmascript { @@ -71,47 +73,49 @@ CVector SourceTextModule::GetExportedNames(JSThread *thread, const } // new way with module -JSHandle SourceTextModule::HostResolveImportedModuleWithMerge( +JSHandle SourceTextModule::HostResolveImportedModuleWithMerge( JSThread *thread, const JSHandle &module, const JSHandle &moduleRequest) { DISALLOW_GARBAGE_COLLECTION; auto moduleManager = thread->GetEcmaVM()->GetModuleManager(); if (moduleManager->IsImportedModuleLoaded(moduleRequest.GetTaggedValue())) { - return moduleManager->HostGetImportedModule(moduleRequest.GetTaggedValue()); + return JSHandle(moduleManager->HostGetImportedModule(moduleRequest.GetTaggedValue())); } ASSERT(module->GetEcmaModuleFilename().IsHeapObject()); - CString baseFilename = - ConvertToString(EcmaString::Cast(module->GetEcmaModuleFilename().GetTaggedObject())); + CString baseFilename = ConvertToString(module->GetEcmaModuleFilename()); ASSERT(module->GetEcmaModuleRecordName().IsHeapObject()); - CString moduleRecordName = - ConvertToString(EcmaString::Cast(module->GetEcmaModuleRecordName().GetTaggedObject())); + CString moduleRecordName = ConvertToString(module->GetEcmaModuleRecordName()); const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, baseFilename, moduleRecordName); - CString moduleRequestName = ConvertToString(EcmaString::Cast(moduleRequest->GetTaggedObject())); + CString moduleRequestName = ConvertToString(moduleRequest.GetTaggedValue()); CString entryPoint = ModuleManager::ConcatFileNameWithMerge(jsPandaFile, baseFilename, moduleRecordName, moduleRequestName); #if defined(PANDA_TARGET_WINDOWS) || defined(PANDA_TARGET_MACOS) if (entryPoint == JSPandaFile::PREVIEW_OF_ACROSS_HAP_FLAG) { - JSHandle throwValue(thread, JSTaggedValue::Undefined()); - THROW_SYNTAX_ERROR_AND_RETURN(thread, "", throwValue); + THROW_SYNTAX_ERROR_AND_RETURN(thread, "", thread->GlobalConstants()->GetHandledUndefined()); } #endif return moduleManager->HostResolveImportedModuleWithMerge(baseFilename, entryPoint); } // old way with bundle -JSHandle SourceTextModule::HostResolveImportedModule(JSThread *thread, - const JSHandle &module, - const JSHandle &moduleRequest) +JSHandle SourceTextModule::HostResolveImportedModule(JSThread *thread, + const JSHandle &module, + const JSHandle &moduleRequest) { auto moduleManage = thread->GetEcmaVM()->GetModuleManager(); if (moduleManage->IsImportedModuleLoaded(moduleRequest.GetTaggedValue())) { - return moduleManage->HostGetImportedModule(moduleRequest.GetTaggedValue()); + return JSHandle(moduleManage->HostGetImportedModule(moduleRequest.GetTaggedValue())); } - std::string baseFilename = EcmaStringAccessor(module->GetEcmaModuleFilename()).ToStdString(); - std::string moduleFilename = EcmaStringAccessor(moduleRequest->GetTaggedObject()).ToStdString(); - return thread->GetEcmaVM()->GetModuleManager()->HostResolveImportedModule(baseFilename, moduleFilename); + + JSHandle dirname = base::PathHelper::ResolveDirPath(thread, + JSHandle(thread, module->GetEcmaModuleFilename())); + JSHandle moduleFilename = ResolveFilenameFromNative(thread, dirname.GetTaggedValue(), + moduleRequest.GetTaggedValue()); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); + return thread->GetEcmaVM()->GetModuleManager()-> + HostResolveImportedModule(ConvertToString(moduleFilename.GetTaggedValue())); } bool SourceTextModule::CheckCircularImport(const JSHandle &module, @@ -285,8 +289,10 @@ void SourceTextModule::CJSInstantiate(JSThread *thread, const JSHandle &module) +int SourceTextModule::Instantiate(JSThread *thread, const JSHandle &moduleHdl) { + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX); + JSHandle module = JSHandle::Cast(moduleHdl); // 1. Let module be this Source Text Module Record. // 2. Assert: module.[[Status]] is not "instantiating" or "evaluating". ASSERT(module->GetStatus() != ModuleStatus::INSTANTIATING && module->GetStatus() != ModuleStatus::EVALUATING); @@ -364,12 +370,17 @@ int SourceTextModule::InnerModuleInstantiation(JSThread *thread, const JSHandle< JSMutableHandle requiredModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - requiredModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, required)); + JSHandle requiredVal = + SourceTextModule::HostResolveImportedModule(thread, module, required); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX); + requiredModule.Update(JSHandle::Cast(requiredVal)); requestedModules->Set(thread, idx, requiredModule->GetEcmaModuleFilename()); } else { ASSERT(moduleRecordName.IsString()); - requiredModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required)); - RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index); + JSHandle requiredVal = + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX); + requiredModule.Update(JSHandle::Cast(requiredVal)); requestedModules->Set(thread, idx, requiredModule->GetEcmaModuleRecordName()); } @@ -465,10 +476,16 @@ void SourceTextModule::ModuleDeclarationEnvironmentSetup(JSThread *thread, JSMutableHandle importedModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - importedModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest)); + JSHandle importedVal = + SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest); + RETURN_IF_ABRUPT_COMPLETION(thread); + importedModule.Update(JSHandle::Cast(importedVal)); } else { ASSERT(moduleRecordName.IsString()); - importedModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest)); + JSHandle importedVal = + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest); + RETURN_IF_ABRUPT_COMPLETION(thread); + importedModule.Update(JSHandle::Cast(importedVal)); } // c. If in.[[ImportName]] is "*", then JSHandle starString = globalConstants->GetHandledStarString(); @@ -539,10 +556,16 @@ void SourceTextModule::ModuleDeclarationArrayEnvironmentSetup(JSThread *thread, JSMutableHandle importedModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - importedModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest)); + JSHandle importedVal = + SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest); + RETURN_IF_ABRUPT_COMPLETION(thread); + importedModule.Update(JSHandle::Cast(importedVal)); } else { ASSERT(moduleRecordName.IsString()); - importedModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest)); + JSHandle importedVal = + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest); + RETURN_IF_ABRUPT_COMPLETION(thread); + importedModule.Update(JSHandle::Cast(importedVal)); } // c. If in.[[ImportName]] is "*", then JSHandle starString = globalConstants->GetHandledStarString(); @@ -737,10 +760,16 @@ int SourceTextModule::InnerModuleEvaluation(JSThread *thread, const JSHandle requiredModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - requiredModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, required)); + JSHandle requiredVal = + SourceTextModule::HostResolveImportedModule(thread, module, required); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX); + requiredModule.Update(JSHandle::Cast(requiredVal)); } else { ASSERT(moduleRecordName.IsString()); - requiredModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required)); + JSHandle requiredVal = + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required); + RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX); + requiredModule.Update(JSHandle::Cast(requiredVal)); } // c. Set index to ? InnerModuleEvaluation(requiredModule, stack, index). JSHandle requiredModuleRecord = JSHandle::Cast(requiredModule); @@ -864,8 +893,9 @@ void SourceTextModule::ModuleExecution(JSThread *thread, const JSHandle requestedModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - requestedModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest)); + JSHandle requestedVal = + SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest); + RETURN_IF_ABRUPT_COMPLETION(thread); + requestedModule.Update(JSHandle::Cast(requestedVal)); } else { ASSERT(moduleRecordName.IsString()); - requestedModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest)); + JSHandle requestedVal = + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest); + RETURN_IF_ABRUPT_COMPLETION(thread); + requestedModule.Update(JSHandle::Cast(requestedVal)); } // b. Let starNames be ? requestedModule.GetExportedNames(exportStarSet). CVector starNames = @@ -1076,12 +1112,17 @@ JSHandle SourceTextModule::GetStarResolution(JSThread *thread, JSMutableHandle importedModule(thread, thread->GlobalConstants()->GetUndefined()); JSTaggedValue moduleRecordName = module->GetEcmaModuleRecordName(); if (moduleRecordName.IsUndefined()) { - importedModule.Update(SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest)); + JSHandle importedVal = + SourceTextModule::HostResolveImportedModule(thread, module, moduleRequest); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); + importedModule.Update(JSHandle::Cast(importedVal)); } else { ASSERT(moduleRecordName.IsString()); - importedModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest)); + JSHandle importedVal = + SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, moduleRequest); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); + importedModule.Update(JSHandle::Cast(importedVal)); } - RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); // b. Let resolution be ? importedModule.ResolveExport(exportName, resolveVector). JSHandle resolution = SourceTextModule::ResolveExport(thread, importedModule, exportName, resolveVector); diff --git a/ecmascript/module/js_module_source_text.h b/ecmascript/module/js_module_source_text.h index ae7bc07403..5a6da498e4 100644 --- a/ecmascript/module/js_module_source_text.h +++ b/ecmascript/module/js_module_source_text.h @@ -33,10 +33,10 @@ public: CAST_CHECK(SourceTextModule, IsSourceTextModule); // 15.2.1.17 Runtime Semantics: HostResolveImportedModule ( referencingModule, specifier ) - static JSHandle HostResolveImportedModule(JSThread *thread, + static JSHandle HostResolveImportedModule(JSThread *thread, const JSHandle &module, const JSHandle &moduleRequest); - static JSHandle HostResolveImportedModuleWithMerge( + static JSHandle HostResolveImportedModuleWithMerge( JSThread *thread, const JSHandle &module, const JSHandle &moduleRequest); // 15.2.1.16.2 GetExportedNames(exportStarSet) @@ -117,7 +117,7 @@ public: // 15.2.1.16.4 Instantiate() static void CJSInstantiate(JSThread *thread, const JSHandle &module, const JSHandle &requiredModule); - static int Instantiate(JSThread *thread, const JSHandle &module); + static int Instantiate(JSThread *thread, const JSHandle &moduleHdl); JSTaggedValue GetModuleValue(JSThread *thread, int32_t index, bool isThrow); void StoreModuleValue(JSThread *thread, int32_t index, const JSHandle &value); diff --git a/ecmascript/module/tests/ecma_module_test.cpp b/ecmascript/module/tests/ecma_module_test.cpp index 3c3a9d78ed..f7616d89bc 100644 --- a/ecmascript/module/tests/ecma_module_test.cpp +++ b/ecmascript/module/tests/ecma_module_test.cpp @@ -397,7 +397,7 @@ HWTEST_F_L0(EcmaModuleTest, HostResolveImportedModule) JSHandle module = factory->NewSourceTextModule(); JSHandle moduleRecord(thread, module.GetTaggedValue()); moduleManager->AddResolveImportedModule(baseFileName.c_str(), moduleRecord); - JSHandle res = moduleManager->HostResolveImportedModule(baseFileName.c_str()); + JSHandle res = moduleManager->HostResolveImportedModule(baseFileName.c_str()); EXPECT_EQ(moduleRecord->GetRawData(), res.GetTaggedValue().GetRawData()); } diff --git a/ecmascript/napi/include/jsnapi.h b/ecmascript/napi/include/jsnapi.h index 01f2b5077e..69f9b76276 100644 --- a/ecmascript/napi/include/jsnapi.h +++ b/ecmascript/napi/include/jsnapi.h @@ -1265,8 +1265,6 @@ public: static Local DeserializeValue(const EcmaVM *vm, void *recoder, void *hint); static void DeleteSerializationData(void *data); static void SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data); - static void SetHostResolvePathTracker(EcmaVM *vm, - std::function cb); static void SetHostResolveBufferTracker(EcmaVM *vm, std::function(std::string dirPath)> cb); static void SetNativePtrGetter(EcmaVM *vm, void* cb); static void SetHostEnqueueJob(const EcmaVM* vm, Local cb); diff --git a/ecmascript/napi/jsnapi.cpp b/ecmascript/napi/jsnapi.cpp index be73ae7065..e703dbb82b 100644 --- a/ecmascript/napi/jsnapi.cpp +++ b/ecmascript/napi/jsnapi.cpp @@ -583,12 +583,6 @@ void JSNApi::SetHostPromiseRejectionTracker(EcmaVM *vm, void *cb, void* data) vm->SetData(data); } -void JSNApi::SetHostResolvePathTracker(EcmaVM *vm, - std::function cb) -{ - vm->SetResolvePathCallback(cb); -} - void JSNApi::SetHostResolveBufferTracker(EcmaVM *vm, std::function(std::string dirPath)> cb) { vm->SetResolveBufferCallback(cb); @@ -2719,10 +2713,10 @@ bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local function) ecmascript::CString moduleName = jsPandaFile->GetJSPandaFileDesc(); ecmascript::CString recordName = method->GetRecordName(); - bool isModule = jsPandaFile->IsModule(recordName); + bool isModule = jsPandaFile->IsModule(thread, recordName); if (isModule) { ecmascript::ModuleManager *moduleManager = vm->GetModuleManager(); - JSHandle moduleRecord; + JSHandle moduleRecord; if (jsPandaFile->IsBundlePack()) { moduleRecord = moduleManager->HostResolveImportedModule(moduleName); } else { @@ -2733,9 +2727,10 @@ bool JSNApi::InitForConcurrentFunction(EcmaVM *vm, Local function) vm->HandleUncaughtException(thread->GetException()); return false; } - moduleRecord->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); - ecmascript::SourceTextModule::EvaluateForConcurrent(thread, moduleRecord); - transFunc->SetModule(thread, moduleRecord); + JSHandle module = JSHandle::Cast(moduleRecord); + module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); + ecmascript::SourceTextModule::EvaluateForConcurrent(thread, module); + transFunc->SetModule(thread, module); return true; } return false; diff --git a/ecmascript/napi/test/jsnapi_tests.cpp b/ecmascript/napi/test/jsnapi_tests.cpp index 9a911d82ea..e700b35b65 100644 --- a/ecmascript/napi/test/jsnapi_tests.cpp +++ b/ecmascript/napi/test/jsnapi_tests.cpp @@ -1228,22 +1228,6 @@ HWTEST_F_L0(JSNApiTests, JSNApi_SetHostPromiseRejectionTracker) ASSERT_EQ(res, reinterpret_cast(data)); } -HWTEST_F_L0(JSNApiTests, JSNApi_SetHostResolvePathTracker) -{ - std::string dirPath; - std::string requestPath; - using CallbackType = std::function; - CallbackType callback = [dirPath, requestPath](std::string dp, std::string rp) -> std::string { - dp = dirPath; - rp = requestPath; - return dp + rp; - }; - JSNApi::SetHostResolvePathTracker(vm_, callback); - ResolvePathCallback res = nullptr; - res = vm_->GetResolvePathCallback(); - EXPECT_TRUE(res); -} - HWTEST_F_L0(JSNApiTests, JSNApi_SetNativePtrGetter_SetHostEnqueueJob) { void *cb = reinterpret_cast(BuiltinsFunction::FunctionPrototypeInvokeSelf); diff --git a/ecmascript/patch/patch_loader.cpp b/ecmascript/patch/patch_loader.cpp index 1a5908eeaf..d6cd4d54fc 100644 --- a/ecmascript/patch/patch_loader.cpp +++ b/ecmascript/patch/patch_loader.cpp @@ -89,7 +89,7 @@ void PatchLoader::ParseConstpoolWithMerge(JSThread *thread, const JSPandaFile *j for (const auto &item : patchRecordInfos) { const CString &recordName = item.first; vm->GetModuleManager()->HostResolveImportedModuleWithMerge(fileName, recordName); - + ASSERT(!thread->HasPendingException()); if (!isNewVersion) { PandaFileTranslator::ParseFuncAndLiteralConstPool(vm, jsPandaFile, recordName, constpool); } @@ -357,11 +357,11 @@ bool PatchLoader::CheckIsInvalidPatch(const JSPandaFile *baseFile, const JSPanda CString baseRecordName = patchRecordName; ASSERT(baseRecordInfos.find(baseRecordName) != baseRecordInfos.end()); - JSHandle patchModule = + JSHandle patchModule = moduleManager->ResolveModuleWithMerge(thread, patchFile, patchRecordName); JSHandle baseModule = moduleManager->HostGetImportedModule(baseRecordName); - if (CheckIsModuleMismatch(thread, patchModule, baseModule)) { + if (CheckIsModuleMismatch(thread, JSHandle(patchModule), baseModule)) { return true; } } diff --git a/ecmascript/platform/file.h b/ecmascript/platform/file.h index 43b06609f6..545ef942ae 100644 --- a/ecmascript/platform/file.h +++ b/ecmascript/platform/file.h @@ -26,6 +26,8 @@ #include +#include "ecmascript/ecma_string.h" +#include "ecmascript/js_tagged_value.h" namespace panda::ecmascript { #ifdef PANDA_TARGET_WINDOWS using fd_t = HANDLE; @@ -53,5 +55,7 @@ fd_t Open(const char *file, int flag); void Close(fd_t fd); void *FileMmap(fd_t fd, uint64_t size, uint64_t offset, fd_t *extra); int FileUnMap(void *addr, uint64_t size, fd_t *extra); +JSHandle ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname, + JSTaggedValue request); } // namespace panda::ecmascript #endif // ECMASCRIPT_PLATFORM_FILE_H diff --git a/ecmascript/platform/unix/file.cpp b/ecmascript/platform/unix/file.cpp index d43219ac65..1da7812b69 100644 --- a/ecmascript/platform/unix/file.cpp +++ b/ecmascript/platform/unix/file.cpp @@ -19,6 +19,8 @@ #include #include +#include "ecmascript/js_tagged_value-inl.h" +#include "ecmascript/ecma_macros.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/platform/map.h" @@ -74,4 +76,40 @@ int FileUnMap(void *addr, uint64_t size, [[maybe_unused]] fd_t *extra) { return munmap(addr, size); } + +JSHandle ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname, + JSTaggedValue request) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + CString fullname; + CString resolvedFilename; + CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetTaggedObject())); + CString requestStr = ConvertToString(EcmaString::Cast(request.GetTaggedObject())); + + if (requestStr.find("./") == 0) { + requestStr = requestStr.substr(2); // 2 : delete './' + } + int suffixEnd = static_cast(requestStr.find_last_of('.')); + if (suffixEnd == -1) { + RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); + } + if (requestStr[0] == '/') { // absolute FilePath + fullname = requestStr.substr(0, suffixEnd) + ".abc"; + } else { + int pos = static_cast(dirnameStr.find_last_of('/')); + if (pos == -1) { + RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); + } + fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc"; + } + + std::string relativePath = ConvertToStdString(fullname); + std::string absPath = ""; + if (RealPath(relativePath, absPath)) { + resolvedFilename = ConvertToString(absPath); + return factory->NewFromUtf8(resolvedFilename); + } + CString msg = "resolve absolute path fail"; + THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, EcmaString, msg.c_str()); +} } // namespace panda::ecmascript diff --git a/ecmascript/platform/windows/file.cpp b/ecmascript/platform/windows/file.cpp index 2711406c36..2aa405845b 100644 --- a/ecmascript/platform/windows/file.cpp +++ b/ecmascript/platform/windows/file.cpp @@ -23,6 +23,17 @@ #undef ERROR #endif +#ifdef VOID +#undef VOID +#endif + +#ifdef CONST +#undef CONST +#endif + +#include "ecmascript/ecma_macros.h" +#include "ecmascript/ecma_string.h" +#include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/platform/map.h" @@ -97,4 +108,36 @@ int FileUnMap(void *addr, [[maybe_unused]] uint64_t size, fd_t *extra) } return FILE_SUCCESS; } + +JSHandle ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname, + JSTaggedValue request) +{ + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + CString fullname; + CString resolvedFilename; + CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetTaggedObject())); + CString requestStr = ConvertToString(EcmaString::Cast(request.GetTaggedObject())); + int suffixEnd = static_cast(requestStr.find_last_of('.')); + if (suffixEnd == -1) { + RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); + } + if (requestStr[1] == ':') { // absoluteFilePath + fullname = requestStr.substr(0, suffixEnd) + ".abc"; + } else { + int pos = static_cast(dirnameStr.find_last_of('\\')); + if (pos == -1) { + RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); + } + fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc"; + } + + std::string relativePath = ConvertToStdString(fullname); + std::string absPath = ""; + if (RealPath(relativePath, absPath)) { + resolvedFilename = ConvertToString(absPath); + return factory->NewFromUtf8(resolvedFilename); + } + CString msg = "resolve absolute path fail"; + THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, EcmaString, msg.c_str()); +} } // namespace panda::ecmascript diff --git a/ecmascript/platform/windows/map.cpp b/ecmascript/platform/windows/map.cpp index 88c778dee4..d6fab07a7e 100644 --- a/ecmascript/platform/windows/map.cpp +++ b/ecmascript/platform/windows/map.cpp @@ -22,6 +22,14 @@ #undef ERROR #endif +#ifdef VOID +#undef VOID +#endif + +#ifdef CONST +#undef CONST +#endif + #include "ecmascript/log_wrapper.h" #include "ecmascript/mem/mem.h" diff --git a/ecmascript/require/js_cjs_module.cpp b/ecmascript/require/js_cjs_module.cpp index cbba8baf5c..51d20449b3 100644 --- a/ecmascript/require/js_cjs_module.cpp +++ b/ecmascript/require/js_cjs_module.cpp @@ -16,9 +16,11 @@ #include "ecmascript/require/js_cjs_module.h" #include "ecmascript/aot_file_manager.h" +#include "ecmascript/base/path_helper.h" #include "ecmascript/builtins/builtins_json.h" #include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/interpreter/slow_runtime_stub.h" +#include "ecmascript/platform/file.h" #include "ecmascript/require/js_cjs_module_cache.h" #include "ecmascript/require/js_require_manager.h" #include "ecmascript/jspandafile/js_pandafile.h" @@ -28,6 +30,7 @@ namespace panda::ecmascript { using BuiltinsJson = builtins::BuiltinsJson; +using PathHelper = base::PathHelper; void CjsModule::InitializeModule(JSThread *thread, JSHandle &module, JSHandle &filename, JSHandle &dirname) { @@ -102,9 +105,10 @@ JSHandle CjsModule::Load(JSThread *thread, JSHandle & JSMutableHandle filename(thread, JSTaggedValue::Undefined()); if (jsPandaFile->IsBundlePack()) { - RequireManager::ResolveCurrentPath(thread, parent, dirname, jsPandaFile); + PathHelper::ResolveCurrentPath(thread, parent, dirname, jsPandaFile); filename.Update(ResolveFilenameFromNative(thread, dirname.GetTaggedValue(), request.GetTaggedValue())); + RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSTaggedValue, thread); mergedFilename = ConvertToString(filename.GetTaggedValue()); } else { CString currentEntryPoint = ConvertToString(entrypointVal.GetTaggedValue()); @@ -123,7 +127,7 @@ JSHandle CjsModule::Load(JSThread *thread, JSHandle & // Don't get required exports from cache, execute required JSPandaFile. // module = new Module(), which belongs to required JSPandaFile. JSHandle module = factory->NewCjsModule(); - RequireManager::ResolveDirPath(thread, dirname, filename); + dirname.Update(PathHelper::ResolveDirPath(thread, filename)); InitializeModule(thread, module, filename, dirname); PutIntoCache(thread, module, filename); @@ -138,7 +142,10 @@ JSHandle CjsModule::Load(JSThread *thread, JSHandle & } // Execute required JSPandaFile RequireExecution(thread, mergedFilename, requestEntryPoint); - + if (thread->HasPendingException()) { + thread->GetEcmaVM()->HandleUncaughtException(thread->GetException()); + return thread->GlobalConstants()->GetHandledUndefined(); + } // Search from Module.cache after execution. JSHandle cachedExports = SearchFromModuleCache(thread, filename); if (cachedExports->IsHole()) { @@ -153,61 +160,13 @@ void CjsModule::RequireExecution(JSThread *thread, CString mergedFilename, CStri const JSPandaFile *jsPandaFile = JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, mergedFilename, requestEntryPoint); if (jsPandaFile == nullptr) { - LOG_ECMA(FATAL) << "open jsPandaFile : " << mergedFilename << - " , record name : " << requestEntryPoint << " error"; - UNREACHABLE(); + LOG_ECMA(ERROR) << "Try to load cjs module " << requestEntryPoint << " in abc : " << mergedFilename; + CString msg = "Faild to load file '" + requestEntryPoint + "', please check the request path."; + THROW_ERROR(thread, ErrorType::REFERENCE_ERROR, msg.c_str()); } JSPandaFileExecutor::Execute(thread, jsPandaFile, requestEntryPoint); } -JSHandle CjsModule::ResolveFilename(JSThread *thread, JSTaggedValue dirname, JSTaggedValue request) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - - ResolvePathCallback resolvePathCallback = thread->GetEcmaVM()->GetResolvePathCallback(); - if (resolvePathCallback == nullptr) { - JSHandle nativeRequireName = ResolveFilenameFromNative(thread, dirname, request); - return nativeRequireName; - } - std::string modDirname = std::string(ConvertToString(EcmaString::Cast(dirname.GetTaggedObject()))); - std::string modFile = std::string(ConvertToString(EcmaString::Cast(request.GetTaggedObject()))); - std::string callbackRequireName = resolvePathCallback(modDirname, modFile); - CString fullname = callbackRequireName.c_str(); - return factory->NewFromUtf8(fullname); -} - -JSHandle CjsModule::ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname, - JSTaggedValue request) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - - CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetTaggedObject())); - CString requestStr = ConvertToString(EcmaString::Cast(request.GetTaggedObject())); - if (requestStr.find("./") == 0) { - requestStr = requestStr.substr(2); // 2 : delete './' - } - int suffixEnd = static_cast(requestStr.find_last_of('.')); - if (suffixEnd == -1) { - RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); - } - CString fullname; - CString res; - if (requestStr[0] == '/') { // absolute FilePath - fullname = requestStr.substr(0, suffixEnd) + ".abc"; - } else { - int pos = static_cast(dirnameStr.find_last_of('/')); - if (pos == -1) { - RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread); - } - fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc"; - } - - if (!AOTFileManager::GetAbsolutePath(fullname, res)) { - LOG_FULL(FATAL) << "resolve absolute path fail"; - } - return factory->NewFromUtf8(res); -} - JSTaggedValue CjsModule::Require(JSThread *thread, JSHandle &request, [[maybe_unused]] JSHandle &parent, [[maybe_unused]] bool isMain) diff --git a/ecmascript/require/js_cjs_module.h b/ecmascript/require/js_cjs_module.h index c6d6bec015..0be63fe2a3 100644 --- a/ecmascript/require/js_cjs_module.h +++ b/ecmascript/require/js_cjs_module.h @@ -54,11 +54,6 @@ public: static JSTaggedValue Require(JSThread *thread, JSHandle &request, JSHandle &parent, bool isMain); - static JSHandle ResolveFilename(JSThread *thread, JSTaggedValue dirname, JSTaggedValue filename); - - static JSHandle ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname, - JSTaggedValue request); - static void RequireExecution(JSThread *thread, CString mergedFilename, CString requestEntryPoint); }; } // namespace panda::ecmascript diff --git a/ecmascript/require/js_require_manager.cpp b/ecmascript/require/js_require_manager.cpp index 0de9e33170..fc190ca155 100644 --- a/ecmascript/require/js_require_manager.cpp +++ b/ecmascript/require/js_require_manager.cpp @@ -22,42 +22,6 @@ #include "ecmascript/ecma_string.h" namespace panda::ecmascript { -void RequireManager::ResolveCurrentPath(JSThread *thread, - JSMutableHandle &dirPath, - JSMutableHandle &fileName, - const JSPandaFile *jsPandaFile) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - CString fullName = jsPandaFile->GetJSPandaFileDesc(); - // find last '/' - int foundPos = static_cast(fullName.find_last_of("/\\")); - if (foundPos == -1) { - RETURN_IF_ABRUPT_COMPLETION(thread); - } - CString dirPathStr = fullName.substr(0, foundPos + 1); - JSHandle dirPathName = factory->NewFromUtf8(dirPathStr); - dirPath.Update(dirPathName.GetTaggedValue()); - - // Get filename from JSPandaFile - JSHandle cbFileName = factory->NewFromUtf8(fullName); - fileName.Update(cbFileName.GetTaggedValue()); -} - -void RequireManager::ResolveDirPath(JSThread *thread, - JSMutableHandle &dirPath, - JSHandle &fileName) -{ - ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); - CString fullName = ConvertToString(fileName.GetTaggedValue()); - // find last '/' - int foundPos = static_cast(fullName.find_last_of("/\\")); - if (foundPos == -1) { - RETURN_IF_ABRUPT_COMPLETION(thread); - } - CString dirPathStr = fullName.substr(0, foundPos + 1); - dirPath.Update((factory->NewFromUtf8(dirPathStr)).GetTaggedValue()); -} - void RequireManager::InitializeCommonJS(JSThread *thread, CJSInfo cjsInfo) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); diff --git a/ecmascript/require/js_require_manager.h b/ecmascript/require/js_require_manager.h index 7c8a477671..7e2c4255c3 100644 --- a/ecmascript/require/js_require_manager.h +++ b/ecmascript/require/js_require_manager.h @@ -39,13 +39,6 @@ struct CJSInfo { }; class RequireManager { public: - - static void ResolveCurrentPath(JSThread *thread, JSMutableHandle &dirPath, - JSMutableHandle &file, - const JSPandaFile *jsPandaFile); - static void ResolveDirPath(JSThread *thread, JSMutableHandle &dirPath, - JSHandle &file); - static void InitializeCommonJS(JSThread *thread, CJSInfo cjsInfo); static void CollectExecutedExp(JSThread *thread, CJSInfo cjsInfo); diff --git a/test/fuzztest/BUILD.gn b/test/fuzztest/BUILD.gn index 28b2aa162c..e1e448264e 100644 --- a/test/fuzztest/BUILD.gn +++ b/test/fuzztest/BUILD.gn @@ -212,7 +212,6 @@ group("fuzztest") { "jsnapideleteserializationdata_fuzzer:fuzztest", "jsnapideserializevalue_fuzzer:fuzztest", "jsnapisethostpromiserejectiontracker_fuzzer:fuzztest", - "jsnapisethostresolvepathtracker_fuzzer:fuzztest", "jsnapistartdebugger_fuzzer:fuzztest", "jsonparse_fuzzer:fuzztest", "jsonstringify_fuzzer:fuzztest", diff --git a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/BUILD.gn b/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/BUILD.gn deleted file mode 100644 index 3f984f45d6..0000000000 --- a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/BUILD.gn +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2022 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. - -#####################################hydra-fuzz############################### -import("//arkcompiler/ets_runtime/js_runtime_config.gni") -import("//arkcompiler/ets_runtime/test/test_helper.gni") -import("//build/config/features.gni") -import("//build/ohos.gni") - -####################################fuzztest################################## -ohos_fuzztest("JSNApiSetHostResolvePathTrackerFuzzTest") { - module_out_path = "arkcompiler/ets_runtime" - - fuzz_config_file = "//arkcompiler/ets_runtime/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer" - - sources = [ "jsnapisethostresolvepathtracker_fuzzer.cpp" ] - - configs = [ "//arkcompiler/ets_runtime:ecma_test_config" ] - - deps = [ - "//arkcompiler/ets_runtime:libark_jsruntime", - sdk_libc_secshared_dep, - ] -} - -group("fuzztest") { - testonly = true - deps = [] - deps += [ ":JSNApiSetHostResolvePathTrackerFuzzTest" ] -} diff --git a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/corpus/init b/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/corpus/init deleted file mode 100644 index b9a20c8eb6..0000000000 --- a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/corpus/init +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2021 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. - -FUZZ \ No newline at end of file diff --git a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/jsnapisethostresolvepathtracker_fuzzer.cpp b/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/jsnapisethostresolvepathtracker_fuzzer.cpp deleted file mode 100644 index 3adad3bf3a..0000000000 --- a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/jsnapisethostresolvepathtracker_fuzzer.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ - -#include "jsnapisethostresolvepathtracker_fuzzer.h" - -#include "ecmascript/napi/include/jsnapi.h" - -using namespace panda; -using namespace panda::ecmascript; - -namespace OHOS { - void JSNApiSetHostResolvePathTrackerFuzzTest(const uint8_t* data, size_t size) - { - RuntimeOption option; - option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); - EcmaVM *vm = JSNApi::CreateJSVM(option); - if (size <= 0) { - return; - } - std::string dirPath(data, data + size); - std::string requestPath(data, data + size); - using CallbackType = std::function; - CallbackType callback = [dirPath, requestPath](std::string dp, std::string rp) -> std::string { - dp = dirPath; - rp = requestPath; - return dp + rp; - }; - JSNApi::SetHostResolvePathTracker(vm, callback); - JSNApi::DestroyJSVM(vm); - } -} - -// Fuzzer entry point. -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - // Run your code on data. - OHOS::JSNApiSetHostResolvePathTrackerFuzzTest(data, size); - return 0; -} \ No newline at end of file diff --git a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/jsnapisethostresolvepathtracker_fuzzer.h b/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/jsnapisethostresolvepathtracker_fuzzer.h deleted file mode 100644 index c5acea5980..0000000000 --- a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/jsnapisethostresolvepathtracker_fuzzer.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ - -#ifndef JSNAPISETHOSTRESOLVEPATHTRACKER_FUZZER_H -#define JSNAPISETHOSTRESOLVEPATHTRACKER_FUZZER_H - -#define FUZZ_PROJECT_NAME "jsnapisethostresolvepathtracker_fuzzer.h" - -#endif \ No newline at end of file diff --git a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/project.xml b/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/project.xml deleted file mode 100644 index 6e8ad2cfde..0000000000 --- a/test/fuzztest/jsnapisethostresolvepathtracker_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - -