From d54dbd5de2cd4591b05d8ad90989287d215f0912 Mon Sep 17 00:00:00 2001 From: dy_study Date: Mon, 15 Aug 2022 15:10:23 +0800 Subject: [PATCH] Update unzip load code. Signed-off-by: dy_study Change-Id: I386bdc51a10afaaf0e5f30e84b1079b138b4b2c7 --- .../native/ability_runtime/js_ability.cpp | 3 +- .../native/form_runtime/js_form_extension.cpp | 3 +- .../ability/native/js_service_extension.cpp | 3 +- .../native/js_static_subscriber_extension.cpp | 3 +- .../runner_runtime/js_test_runner.cpp | 6 +- .../ability_runtime/app/js_ability_stage.cpp | 6 +- .../native/runtime/js_module_reader.cpp | 71 +++ frameworks/native/runtime/js_module_reader.h | 45 ++ .../native/runtime/js_module_searcher.cpp | 364 +------------- .../native/runtime/js_module_searcher.h | 23 +- frameworks/native/runtime/js_runtime.cpp | 69 +-- .../native/runtime/js_runtime_utils.cpp | 467 +++++++++++++++++- .../native/runtime/runtime_extractor.cpp | 6 - interfaces/inner_api/runtime/BUILD.gn | 25 +- .../inner_api/runtime/include/js_runtime.h | 4 +- .../runtime/include/js_runtime_utils.h | 17 +- .../runtime/include/runtime_extractor.h | 10 +- 17 files changed, 647 insertions(+), 478 deletions(-) create mode 100755 frameworks/native/runtime/js_module_reader.cpp create mode 100755 frameworks/native/runtime/js_module_reader.h diff --git a/frameworks/native/ability/native/ability_runtime/js_ability.cpp b/frameworks/native/ability/native/ability_runtime/js_ability.cpp index 0111d33a81..db2867724c 100644 --- a/frameworks/native/ability/native/ability_runtime/js_ability.cpp +++ b/frameworks/native/ability/native/ability_runtime/js_ability.cpp @@ -113,7 +113,8 @@ void JsAbility::Init(const std::shared_ptr &abilityInfo, auto &engine = jsRuntime_.GetNativeEngine(); jsAbilityObj_ = - jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE, abilityInfo->hapPath); + jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo->hapPath, + abilityInfo->compileMode == AppExecFwk::CompileMode::ES_MODULE); if (jsAbilityObj_ == nullptr) { HILOG_ERROR("Failed to get AbilityStage object"); return; diff --git a/frameworks/native/ability/native/form_runtime/js_form_extension.cpp b/frameworks/native/ability/native/form_runtime/js_form_extension.cpp index 2c0a29f453..2b01a0d02f 100644 --- a/frameworks/native/ability/native/form_runtime/js_form_extension.cpp +++ b/frameworks/native/ability/native/form_runtime/js_form_extension.cpp @@ -92,7 +92,8 @@ void JsFormExtension::Init(const std::shared_ptr &record, HandleScope handleScope(jsRuntime_); auto& engine = jsRuntime_.GetNativeEngine(); - jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->compileMode == CompileMode::ES_MODULE, abilityInfo_->hapPath); + jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath, + abilityInfo_->compileMode == CompileMode::ES_MODULE); if (jsObj_ == nullptr) { HILOG_ERROR("Failed to get jsObj_"); return; diff --git a/frameworks/native/ability/native/js_service_extension.cpp b/frameworks/native/ability/native/js_service_extension.cpp index a17304d315..dca76a71c4 100644 --- a/frameworks/native/ability/native/js_service_extension.cpp +++ b/frameworks/native/ability/native/js_service_extension.cpp @@ -90,7 +90,8 @@ void JsServiceExtension::Init(const std::shared_ptr &record, HandleScope handleScope(jsRuntime_); auto& engine = jsRuntime_.GetNativeEngine(); - jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->compileMode == CompileMode::ES_MODULE, abilityInfo_->hapPath); + jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath, + abilityInfo_->compileMode == CompileMode::ES_MODULE); if (jsObj_ == nullptr) { HILOG_ERROR("Failed to get jsObj_"); return; diff --git a/frameworks/native/ability/native/js_static_subscriber_extension.cpp b/frameworks/native/ability/native/js_static_subscriber_extension.cpp index aaecad01e8..2d1b65489c 100644 --- a/frameworks/native/ability/native/js_static_subscriber_extension.cpp +++ b/frameworks/native/ability/native/js_static_subscriber_extension.cpp @@ -92,7 +92,8 @@ void JsStaticSubscriberExtension::Init(const std::shared_ptr HandleScope handleScope(jsRuntime_); auto& engine = jsRuntime_.GetNativeEngine(); - jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->compileMode == CompileMode::ES_MODULE, abilityInfo_->hapPath); + jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath, + abilityInfo_->compileMode == CompileMode::ES_MODULE); if (jsObj_ == nullptr) { HILOG_ERROR("Failed to get jsObj_"); return; diff --git a/frameworks/native/appkit/ability_delegator/runner_runtime/js_test_runner.cpp b/frameworks/native/appkit/ability_delegator/runner_runtime/js_test_runner.cpp index 40e9169e85..b1cdd70713 100644 --- a/frameworks/native/appkit/ability_delegator/runner_runtime/js_test_runner.cpp +++ b/frameworks/native/appkit/ability_delegator/runner_runtime/js_test_runner.cpp @@ -68,8 +68,8 @@ JsTestRunner::JsTestRunner( std::string moduleName; hapPath_ = bundleInfo.hapModuleInfos.back().hapPath; HILOG_DEBUG("JsTestRunner hapPath is %{public}s", hapPath_.c_str()); - jsTestRunnerObj_ = jsRuntime_.LoadModule(moduleName, srcPath_, - bundleInfo.hapModuleInfos.back().compileMode == AppExecFwk::CompileMode::ES_MODULE, hapPath_); + jsTestRunnerObj_ = jsRuntime_.LoadModule(moduleName, srcPath_, hapPath_, + bundleInfo.hapModuleInfos.back().compileMode == AppExecFwk::CompileMode::ES_MODULE); } } @@ -78,7 +78,7 @@ JsTestRunner::~JsTestRunner() = default; bool JsTestRunner::Initialize() { if (isFaJsModel_) { - if (!jsRuntime_.RunScript("/system/etc/strip.native.min.abc")) { + if (!jsRuntime_.RunScript("/system/etc/strip.native.min.abc", hapPath_)) { HILOG_ERROR("RunScript err"); return false; } diff --git a/frameworks/native/appkit/ability_runtime/app/js_ability_stage.cpp b/frameworks/native/appkit/ability_runtime/app/js_ability_stage.cpp index ba4d04b88b..1b0ec10ae7 100644 --- a/frameworks/native/appkit/ability_runtime/app/js_ability_stage.cpp +++ b/frameworks/native/appkit/ability_runtime/app/js_ability_stage.cpp @@ -70,7 +70,8 @@ std::shared_ptr JsAbilityStage::Create( std::string moduleName(hapModuleInfo.moduleName); moduleName.append("::").append("AbilityStage"); auto moduleObj = - jsRuntime.LoadModule(moduleName, srcPath, hapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE, hapModuleInfo.hapPath); + jsRuntime.LoadModule(moduleName, srcPath, hapModuleInfo.hapPath, + hapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE); return std::make_shared(jsRuntime, std::move(moduleObj)); } @@ -83,7 +84,8 @@ std::shared_ptr JsAbilityStage::Create( std::string moduleName(hapModuleInfo.moduleName); moduleName.append("::").append("AbilityStage"); moduleObj = - jsRuntime.LoadModule(moduleName, srcPath, hapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE, hapModuleInfo.hapPath); + jsRuntime.LoadModule(moduleName, srcPath, hapModuleInfo.hapPath, + hapModuleInfo.compileMode == AppExecFwk::CompileMode::ES_MODULE); HILOG_INFO("JsAbilityStage srcPath is %{public}s", srcPath.c_str()); } return std::make_shared(jsRuntime, std::move(moduleObj)); diff --git a/frameworks/native/runtime/js_module_reader.cpp b/frameworks/native/runtime/js_module_reader.cpp new file mode 100755 index 0000000000..fae8f6ead5 --- /dev/null +++ b/frameworks/native/runtime/js_module_reader.cpp @@ -0,0 +1,71 @@ +/* + * 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 "js_module_reader.h" + +#include "hilog_wrapper.h" +#include "js_runtime_utils.h" + +namespace OHOS { +namespace AbilityRuntime { +std::vector JsModuleReader::operator()( + const std::string& curJsModulePath, const std::string& newJsModuleUri) const +{ + HILOG_INFO("Read JS module (%{public}s, %{public}s) begin", curJsModulePath.c_str(), newJsModuleUri.c_str()); + + std::vector buffer; + if (curJsModulePath.empty() || newJsModuleUri.empty()) { + return buffer; + } + + std::string normalizeUri = newJsModuleUri; + std::replace(normalizeUri.begin(), normalizeUri.end(), '\\', '/'); + + std::string newJsModulePath; + switch (normalizeUri[0]) { + case '.': { + newJsModulePath = MakeNewJsModulePath(curJsModulePath, normalizeUri); + break; + } + case '@': { + newJsModulePath = ParseOhmUri(bundleName_, curJsModulePath, normalizeUri); + if (newJsModulePath.empty()) { + newJsModulePath = FindNpmPackage(curJsModulePath, normalizeUri); + } + break; + } + default: { + newJsModulePath = FindNpmPackage(curJsModulePath, normalizeUri); + break; + } + } + FixExtName(newJsModulePath); + + std::ostringstream dest; + if (!GetFileBufferFromHap(hapPath_, newJsModulePath, dest)) { + HILOG_ERROR("Get abc file failed"); + return buffer; + } + + const auto& outStr = dest.str(); + buffer.assign(outStr.begin(), outStr.end()); + + HILOG_INFO("Read JS module (%{public}s, %{public}s) => %{public}s end", + curJsModulePath.c_str(), normalizeUri.c_str(), newJsModulePath.c_str()); + + return buffer; +} +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/runtime/js_module_reader.h b/frameworks/native/runtime/js_module_reader.h new file mode 100755 index 0000000000..fd5f47634f --- /dev/null +++ b/frameworks/native/runtime/js_module_reader.h @@ -0,0 +1,45 @@ +/* + * 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 OHOS_ABILITY_RUNTIME_JS_MODULE_READER_H +#define OHOS_ABILITY_RUNTIME_JS_MODULE_READER_H + +#include +#include + +namespace OHOS { +namespace AbilityRuntime { +class JsModuleReader final { +public: + explicit JsModuleReader(const std::string& bundleName, const std::string& hapPath) + : bundleName_(bundleName), hapPath_(hapPath) + {} + ~JsModuleReader() = default; + + JsModuleReader(const JsModuleReader&) = default; + JsModuleReader(JsModuleReader&&) = default; + JsModuleReader& operator=(const JsModuleReader&) = default; + JsModuleReader& operator=(JsModuleReader&&) = default; + + std::vector operator()(const std::string& curJsModulePath, const std::string& newJsModuleUri) const; + +private: + std::string bundleName_; + std::string hapPath_; +}; +} // namespace AbilityRuntime +} // namespace OHOS + +#endif // OHOS_ABILITY_RUNTIME_JS_MODULE_READER_H \ No newline at end of file diff --git a/frameworks/native/runtime/js_module_searcher.cpp b/frameworks/native/runtime/js_module_searcher.cpp index 7153b3cfb4..486a33d996 100644 --- a/frameworks/native/runtime/js_module_searcher.cpp +++ b/frameworks/native/runtime/js_module_searcher.cpp @@ -15,370 +15,32 @@ #include "js_module_searcher.h" -#include -#include -#include - #include "hilog_wrapper.h" #include "js_runtime_utils.h" -#ifdef WINDOWS_PLATFORM -#include - -namespace { -char* realpath(const char* path, char* resolvedPath) -{ - if (_access(path, 0) < 0) { - return nullptr; - } - if (strcpy_s(resolvedPath, PATH_MAX, path) != 0) { - return nullptr; - } - return resolvedPath; -} -} -#endif - namespace OHOS { namespace AbilityRuntime { -namespace { -constexpr char PREFIX_BUNDLE[] = "@bundle:"; -constexpr char PREFIX_MODULE[] = "@module:"; -constexpr char PREFIX_LOCAL[] = "@local:"; - -constexpr char NPM_PATH_SEGMENT[] = "node_modules"; - -constexpr char NPM_ENTRY_FILE[] = "index.abc"; -constexpr char NPM_ENTRY_LINK[] = "entry.txt"; - -constexpr char EXT_NAME_ABC[] = ".abc"; -constexpr char EXT_NAME_ETS[] = ".ets"; -constexpr char EXT_NAME_TS[] = ".ts"; -constexpr char EXT_NAME_JS[] = ".js"; - -constexpr size_t MAX_NPM_LEVEL = 1; - -inline bool StringEndWith(const std::string& str, const char* endStr, size_t endStrLen) -{ - size_t len = str.length(); - return ((len >= endStrLen) && (str.compare(len - endStrLen, endStrLen, endStr) == 0)); -} - -void SplitString(const std::string& str, std::vector& out, size_t pos = 0, const char* seps = "\\/") -{ - if (str.empty() || pos >= str.length()) { - return; - } - - size_t startPos = pos; - size_t endPos = 0; - while ((endPos = str.find_first_of(seps, startPos)) != std::string::npos) { - if (endPos > startPos) { - out.emplace_back(str.substr(startPos, endPos - startPos)); - } - startPos = endPos + 1; - } - - if (startPos < str.length()) { - out.emplace_back(str.substr(startPos)); - } -} - -std::string JoinString(const std::vector& strs, char sep, size_t startIndex = 0) -{ - std::string out; - for (size_t index = startIndex; index < strs.size(); ++index) { - if (!strs[index].empty()) { - out.append(strs[index]) += sep; - } - } - if (!out.empty()) { - out.pop_back(); - } - return out; -} - -inline std::string StripString(const std::string& str, const char* charSet = " \t\n\r") -{ - size_t startPos = str.find_first_not_of(charSet); - if (startPos == std::string::npos) { - return std::string(); - } - - return str.substr(startPos, str.find_last_not_of(charSet) - startPos + 1); -} -} - std::string JsModuleSearcher::operator()(const std::string& curJsModulePath, const std::string& newJsModuleUri) const { - return ParseJsModuleUri(curJsModulePath, newJsModuleUri); -} - -void JsModuleSearcher::FixExtName(std::string& path) -{ - if (path.empty()) { - return; - } - - if (StringEndWith(path, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) { - return; - } - - if (StringEndWith(path, EXT_NAME_ETS, sizeof(EXT_NAME_ETS) - 1)) { - path.erase(path.length() - (sizeof(EXT_NAME_ETS) - 1), sizeof(EXT_NAME_ETS) - 1); - } else if (StringEndWith(path, EXT_NAME_TS, sizeof(EXT_NAME_TS) - 1)) { - path.erase(path.length() - (sizeof(EXT_NAME_TS) - 1), sizeof(EXT_NAME_TS) - 1); - } else if (StringEndWith(path, EXT_NAME_JS, sizeof(EXT_NAME_JS) - 1)) { - path.erase(path.length() - (sizeof(EXT_NAME_JS) - 1), sizeof(EXT_NAME_JS) - 1); - } - - path.append(EXT_NAME_ABC); -} - -std::string JsModuleSearcher::GetInstallPath(const std::string& curJsModulePath, bool module) const -{ - size_t pos = std::string::npos; - if (StringStartWith(curJsModulePath, bundleInstallPath_.c_str(), bundleInstallPath_.length())) { - pos = bundleInstallPath_.length() - 1; - } else { - if (!StringStartWith(curJsModulePath, otherBundleInstallPath_.c_str(), otherBundleInstallPath_.length())) { - return std::string(); - } - - pos = curJsModulePath.find('/', otherBundleInstallPath_.length()); - if (pos == std::string::npos) { - return std::string(); - } - } - - if (module) { - pos = curJsModulePath.find('/', pos + 1); - if (pos == std::string::npos) { - return std::string(); - } - } - - return curJsModulePath.substr(0, pos + 1); -} - -std::string JsModuleSearcher::MakeNewJsModulePath( - const std::string& curJsModulePath, const std::string& newJsModuleUri) const -{ - std::string moduleInstallPath = GetInstallPath(curJsModulePath, true); - if (moduleInstallPath.empty()) { - return std::string(); - } - - std::vector pathVector; - SplitString(curJsModulePath, pathVector, moduleInstallPath.length()); - - if (pathVector.empty()) { - return std::string(); - } - - // Remove file name, reserve only dir name - pathVector.pop_back(); - - std::vector relativePathVector; - SplitString(newJsModuleUri, relativePathVector); - - for (auto& value : relativePathVector) { - if (value == ".") { - continue; - } else if (value == "..") { - if (pathVector.empty()) { - return std::string(); - } - pathVector.pop_back(); - } else { - pathVector.emplace_back(std::move(value)); - } - } - - std::string jsModulePath = moduleInstallPath + JoinString(pathVector, '/'); - FixExtName(jsModulePath); - if (jsModulePath.size() >= PATH_MAX) { - return std::string(); - } - - char path[PATH_MAX]; - if (realpath(jsModulePath.c_str(), path) != nullptr) { - return std::string(path); - } - return std::string(); -} - -std::string JsModuleSearcher::FindNpmPackageInPath(const std::string& npmPath) const -{ - std::string fileName = npmPath + "/" + NPM_ENTRY_FILE; - - char path[PATH_MAX]; - if (fileName.size() >= PATH_MAX) { - return std::string(); - } - if (realpath(fileName.c_str(), path) != nullptr) { - return path; - } - - fileName = npmPath + "/" + NPM_ENTRY_LINK; - if (fileName.size() >= PATH_MAX) { - return std::string(); - } - if (realpath(fileName.c_str(), path) == nullptr) { - return std::string(); - } - - std::ifstream stream(path, std::ios::ate); - if (!stream.is_open()) { - return std::string(); - } - - auto fileLen = stream.tellg(); - if (fileLen >= PATH_MAX) { - return std::string(); - } - - stream.seekg(0); - stream.read(path, fileLen); - path[fileLen] = '\0'; - return npmPath + '/' + StripString(path); -} - -std::string JsModuleSearcher::FindNpmPackageInTopLevel( - const std::string& moduleInstallPath, const std::string& npmPackage, size_t start) const -{ - for (size_t level = start; level <= MAX_NPM_LEVEL; ++level) { - std::string path = moduleInstallPath + NPM_PATH_SEGMENT + '/' + std::to_string(level) + '/' + npmPackage; - path = FindNpmPackageInPath(path); - if (!path.empty()) { - return path; - } - } - - return std::string(); -} - -std::string JsModuleSearcher::FindNpmPackage(const std::string& curJsModulePath, const std::string& npmPackage) const -{ - std::string newJsModulePath = MakeNewJsModulePath(curJsModulePath, npmPackage); - if (!newJsModulePath.empty()) { - return newJsModulePath; - } - std::string moduleInstallPath = GetInstallPath(curJsModulePath); - if (moduleInstallPath.empty()) { - return std::string(); - } - std::vector pathVector; - SplitString(curJsModulePath, pathVector, moduleInstallPath.length()); - if (pathVector.empty()) { - return std::string(); - } - - if (pathVector[0] != NPM_PATH_SEGMENT) { - return FindNpmPackageInTopLevel(moduleInstallPath, npmPackage); - } - - // Remove file name, reserve only dir name - pathVector.pop_back(); - - // Find npm package until reach top level npm path such as 'node_modules/0', - // so there must be 2 element in vector - while (pathVector.size() > 2) { - std::string path = - moduleInstallPath + JoinString(pathVector, '/') + '/' + NPM_PATH_SEGMENT + '/' + npmPackage; - path = FindNpmPackageInPath(path); - if (!path.empty()) { - return path; - } - - pathVector.pop_back(); - } - - char* p = nullptr; - size_t index = std::strtoul(pathVector.back().c_str(), &p, 10); - if (p == nullptr || *p != '\0') { - return std::string(); - } - - return FindNpmPackageInTopLevel(moduleInstallPath, npmPackage, index); -} - -std::string JsModuleSearcher::ParseOhmUri(const std::string& curJsModulePath, const std::string& newJsModuleUri) const -{ - std::string moduleInstallPath; - std::vector pathVector; - size_t index = 0; - - if (StringStartWith(newJsModuleUri, PREFIX_BUNDLE, sizeof(PREFIX_BUNDLE) - 1)) { - SplitString(newJsModuleUri, pathVector, sizeof(PREFIX_BUNDLE) - 1); - - // Uri should have atleast 3 segments - if (pathVector.size() < 3) { - return std::string(); - } - - const auto& bundleName = pathVector[index++]; - if (bundleName == bundleName_) { - moduleInstallPath = bundleInstallPath_; - } else { - moduleInstallPath = otherBundleInstallPath_; - moduleInstallPath.append(bundleName).append("/"); - } - moduleInstallPath.append(pathVector[index++]).append("/"); - } else if (StringStartWith(newJsModuleUri, PREFIX_MODULE, sizeof(PREFIX_MODULE) - 1)) { - SplitString(newJsModuleUri, pathVector, sizeof(PREFIX_MODULE) - 1); - - // Uri should have atleast 2 segments - if (pathVector.size() < 2) { - return std::string(); - } - - moduleInstallPath = GetInstallPath(curJsModulePath, false); - if (moduleInstallPath.empty()) { - return std::string(); - } - moduleInstallPath.append(pathVector[index++]).append("/"); - } else if (StringStartWith(newJsModuleUri, PREFIX_LOCAL, sizeof(PREFIX_LOCAL) - 1)) { - SplitString(newJsModuleUri, pathVector, sizeof(PREFIX_LOCAL) - 1); - - if (pathVector.empty()) { - return std::string(); - } - - moduleInstallPath = GetInstallPath(curJsModulePath); - if (moduleInstallPath.empty()) { - return std::string(); - } - } else { - return std::string(); - } - - if (pathVector[index] != NPM_PATH_SEGMENT) { - return moduleInstallPath + JoinString(pathVector, '/', index); - } - - return FindNpmPackageInTopLevel(moduleInstallPath, JoinString(pathVector, '/', index + 1)); -} - -std::string JsModuleSearcher::ParseJsModuleUri(const std::string& curJsModulePath, const std::string& newJsModuleUri) const -{ - HILOG_DEBUG("Search JS module ParseJsModuleUri (%{public}s, %{public}s) begin", curJsModulePath.c_str(), - newJsModuleUri.c_str()); + HILOG_INFO("Search JS module (%{public}s, %{public}s) begin", + curJsModulePath.c_str(), newJsModuleUri.c_str()); std::string newJsModulePath; + if (curJsModulePath.empty() || newJsModuleUri.empty()) { return newJsModulePath; } std::string normalizeUri = newJsModuleUri; std::replace(normalizeUri.begin(), normalizeUri.end(), '\\', '/'); + switch (normalizeUri[0]) { case '.': { newJsModulePath = MakeNewJsModulePath(curJsModulePath, normalizeUri); break; } case '@': { - newJsModulePath = ParseOhmUri(curJsModulePath, normalizeUri); + newJsModulePath = ParseOhmUri(bundleName_, curJsModulePath, normalizeUri); if (newJsModulePath.empty()) { newJsModulePath = FindNpmPackage(curJsModulePath, normalizeUri); } @@ -391,21 +53,11 @@ std::string JsModuleSearcher::ParseJsModuleUri(const std::string& curJsModulePat } FixExtName(newJsModulePath); - HILOG_DEBUG("Search JS module ParseJsModuleUri (%{public}s, %{public}s) => %{public}s end", + + HILOG_INFO("Search JS module (%{public}s, %{public}s) => %{public}s end", curJsModulePath.c_str(), normalizeUri.c_str(), newJsModulePath.c_str()); + return newJsModulePath; } - -bool JsModuleSearcher::GetABCFileBuffer( - const std::string& curJsModulePath, const std::string& newJsModuleUri, std::ostream &dest) const -{ - std::string newJsModulePath = ParseJsModuleUri(curJsModulePath, newJsModuleUri); - - if (!GetABCFile(hapPath_, newJsModulePath, dest)) { - HILOG_ERROR("Get abc file failed"); - return false; - } - return true; -} } // namespace AbilityRuntime } // namespace OHOS \ No newline at end of file diff --git a/frameworks/native/runtime/js_module_searcher.h b/frameworks/native/runtime/js_module_searcher.h index 8c60d8d26c..1a844a17e4 100644 --- a/frameworks/native/runtime/js_module_searcher.h +++ b/frameworks/native/runtime/js_module_searcher.h @@ -16,18 +16,13 @@ #ifndef OHOS_ABILITY_RUNTIME_JS_MODULE_SEARCHER_H #define OHOS_ABILITY_RUNTIME_JS_MODULE_SEARCHER_H -#include #include namespace OHOS { namespace AbilityRuntime { class JsModuleSearcher final { public: - explicit JsModuleSearcher(const std::string& bundleName, const std::string& hapPath, - const std::string& bundleInstallPath = "/data/storage/el1/bundle/", - const std::string& otherBundleInstallPath = "/data/bundles/") - : bundleName_(bundleName), hapPath_(hapPath), bundleInstallPath_(bundleInstallPath), - otherBundleInstallPath_(otherBundleInstallPath) + explicit JsModuleSearcher(const std::string& bundleName) : bundleName_(bundleName) {} ~JsModuleSearcher() = default; @@ -37,25 +32,9 @@ public: JsModuleSearcher& operator=(JsModuleSearcher&&) = default; std::string operator()(const std::string& curJsModulePath, const std::string& newJsModuleUri) const; - bool GetABCFileBuffer( - const std::string& curJsModulePath, const std::string& newJsModuleUri, std::ostream &dest) const; private: - static void FixExtName(std::string& path); - - std::string GetInstallPath(const std::string& curJsModulePath, bool module = true) const; - std::string MakeNewJsModulePath(const std::string& curJsModulePath, const std::string& newJsModuleUri) const; - std::string FindNpmPackageInPath(const std::string& npmPath) const; - std::string FindNpmPackageInTopLevel( - const std::string& moduleInstallPath, const std::string& npmPackage, size_t start = 0) const; - std::string FindNpmPackage(const std::string& curJsModulePath, const std::string& npmPackage) const; - std::string ParseOhmUri(const std::string& curJsModulePath, const std::string& newJsModuleUri) const; - std::string ParseJsModuleUri(const std::string& curJsModulePath, const std::string& newJsModuleUri) const; - std::string bundleName_; - std::string hapPath_; - std::string bundleInstallPath_; - std::string otherBundleInstallPath_; }; } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/runtime/js_runtime.cpp b/frameworks/native/runtime/js_runtime.cpp index 2e18dcae4a..93b8ffc032 100644 --- a/frameworks/native/runtime/js_runtime.cpp +++ b/frameworks/native/runtime/js_runtime.cpp @@ -22,13 +22,13 @@ #include #include - #include "connect_server_manager.h" #include "event_handler.h" #include "hdc_register.h" #include "hilog_wrapper.h" #include "js_console_log.h" #include "js_module_searcher.h" +#include "js_module_reader.h" #include "js_runtime_utils.h" #include "js_timer.h" #include "js_worker.h" @@ -111,12 +111,17 @@ public: { bool result = false; if (!hapPath.empty()) { - std::ostringstream outStreamForABC; - if (!GetABCFile(hapPath, path, outStreamForABC)) { + std::ostringstream outStream; + if (!GetFileBufferFromHap(hapPath, path, outStream)) { HILOG_ERROR("Get abc file failed"); return result; } - result = nativeEngine_->RunScriptPath(path.c_str()) != nullptr; //, (void *)outStreamForABC + + const auto& outStr = outStream.str(); + std::vector buffer; + buffer.assign(outStr.begin(), outStr.end()); + + result = nativeEngine_->RunScriptBuffer(path.c_str(), buffer) != nullptr; } else { result = nativeEngine_->RunScriptPath(path.c_str()) != nullptr; } @@ -189,7 +194,8 @@ private: if (!options.preload) { bundleName_ = options.bundleName; - panda::JSNApi::SetHostResolvePathTracker(vm_, JsModuleSearcher(options.bundleName, options.hapPath)); + panda::JSNApi::SetHostResolvePathTracker(vm_, JsModuleSearcher(options.bundleName)); + panda::JSNApi::SetHostResolveBufferTracker(vm_, JsModuleReader(options.bundleName, options.hapPath)); } return JsRuntime::Initialize(options); } @@ -234,46 +240,6 @@ void InitSyscapModule(NativeEngine& engine, NativeObject& globalObject) { BindNativeFunction(engine, globalObject, "canIUse", CanIUse); } - -bool MakeFilePath(const std::string& codePath, const std::string& modulePath, std::string& fileName) -{ - std::string path(codePath); - path.append("/").append(modulePath);// phone/./ets/MainAbility6/MainAbility6.abc - if (path.length() > PATH_MAX) { - HILOG_ERROR("Path length(%{public}d) longer than MAX(%{public}d)", (int32_t)path.length(), PATH_MAX); - return false; - } - char resolvedPath[PATH_MAX + 1] = { 0 }; - if (realpath(path.c_str(), resolvedPath) != nullptr) { - fileName = resolvedPath; - return true; - } - - auto start = path.find_last_of('/'); - auto end = path.find_last_of('.'); - if (end == std::string::npos || end == 0) { - HILOG_ERROR("No secondary file path"); - return false; - } - - auto pos = path.find_last_of('.', end - 1); - if (pos == std::string::npos) { - HILOG_ERROR("No secondary file path"); - return false; - } - - path.erase(start + 1, pos - start); - HILOG_INFO("Try using secondary file path: %{public}s", path.c_str()); - - if (realpath(path.c_str(), resolvedPath) == nullptr) { - HILOG_ERROR("Failed to call realpath, errno = %{public}d", errno); - return false; - } - - fileName = resolvedPath; - return true; -} - class UvLoopHandler : public AppExecFwk::FileDescriptorListener, public std::enable_shared_from_this { public: explicit UvLoopHandler(uv_loop_t* uvLoop) : uvLoop_(uvLoop) {} @@ -507,7 +473,7 @@ NativeValue* JsRuntime::LoadJsBundle(const std::string& path, const std::string& } std::unique_ptr JsRuntime::LoadModule(const std::string& moduleName, - const std::string& modulePath, bool esmodule, const std::string& hapPath) + const std::string& modulePath, const std::string& hapPath, bool esmodule) { HILOG_INFO("JsRuntime::LoadModule(%{public}s, %{public}s, %{public}s)", moduleName.c_str(), modulePath.c_str(), esmodule ? "true" : "false"); @@ -566,12 +532,17 @@ bool JsRuntime::RunScript(const std::string& path, const std::string& hapPath) { bool result = false; if (!hapPath.empty()) { - std::ostringstream outStreamForABC; - if (!GetABCFile(hapPath, path, outStreamForABC)) { + std::ostringstream outStream; + if (!GetFileBufferFromHap(hapPath, path, outStream)) { HILOG_ERROR("Get abc file failed"); return result; } - result = nativeEngine_->RunScript(path.c_str()) != nullptr; //, (void *)outStreamForABC + + const auto& outStr = outStream.str(); + std::vector buffer; + buffer.assign(outStr.begin(), outStr.end()); + + result = nativeEngine_->RunScriptBuffer(path.c_str(), buffer) != nullptr; } else { result = nativeEngine_->RunScript(path.c_str()) != nullptr; } diff --git a/frameworks/native/runtime/js_runtime_utils.cpp b/frameworks/native/runtime/js_runtime_utils.cpp index 31f3c65258..f179c8dedb 100644 --- a/frameworks/native/runtime/js_runtime_utils.cpp +++ b/frameworks/native/runtime/js_runtime_utils.cpp @@ -15,16 +15,49 @@ #include "js_runtime_utils.h" +#include #include +#include #include "ability_constants.h" #include "hilog_wrapper.h" #include "js_runtime.h" #include "runtime_extractor.h" +#ifdef WINDOWS_PLATFORM +#include + +namespace { +char* realpath(const char* path, char* resolvedPath) +{ + if (_access(path, 0) < 0) { + return nullptr; + } + if (strcpy_s(resolvedPath, PATH_MAX, path) != 0) { + return nullptr; + } + return resolvedPath; +} +} +#endif namespace OHOS { namespace AbilityRuntime { namespace { +constexpr char EXT_NAME_ABC[] = ".abc"; +constexpr char EXT_NAME_ETS[] = ".ets"; +constexpr char EXT_NAME_TS[] = ".ts"; +constexpr char EXT_NAME_JS[] = ".js"; +constexpr char PREFIX_BUNDLE[] = "@bundle:"; +constexpr char PREFIX_MODULE[] = "@module:"; +constexpr char PREFIX_LOCAL[] = "@local:"; +constexpr char NPM_PATH_SEGMENT[] = "node_modules"; +constexpr char NPM_ENTRY_FILE[] = "index.abc"; +constexpr char NPM_ENTRY_LINK[] = "entry.txt"; +constexpr char BUNDLE_INSTALL_PATH[] = "/data/storage/el1/bundle/"; +constexpr char OTHER_BUNDLE_INSTALL_PATH[] = "/data/bundles/"; + +constexpr size_t MAX_NPM_LEVEL = 1; + std::unique_ptr CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam, std::unique_ptr&& execute, std::unique_ptr&& complete, NativeValue** result) @@ -39,14 +72,64 @@ std::unique_ptr CreateAsyncTaskWithLastParam(NativeEngine& engine, Na return std::make_unique(callbackRef, std::move(execute), std::move(complete)); } } -} // namespace -// Help Functions -bool StringStartWith(const std::string& str, const char* startStr, size_t startStrLen) +inline bool StringStartWith(const std::string& str, const char* startStr, size_t startStrLen) { return ((str.length() >= startStrLen) && (str.compare(0, startStrLen, startStr) == 0)); } +inline bool StringEndWith(const std::string& str, const char* endStr, size_t endStrLen) +{ + size_t len = str.length(); + return ((len >= endStrLen) && (str.compare(len - endStrLen, endStrLen, endStr) == 0)); +} + +void SplitString(const std::string& str, std::vector& out, size_t pos = 0, const char* seps = "\\/") +{ + if (str.empty() || pos >= str.length()) { + return; + } + + size_t startPos = pos; + size_t endPos = 0; + while ((endPos = str.find_first_of(seps, startPos)) != std::string::npos) { + if (endPos > startPos) { + out.emplace_back(str.substr(startPos, endPos - startPos)); + } + startPos = endPos + 1; + } + + if (startPos < str.length()) { + out.emplace_back(str.substr(startPos)); + } +} + +std::string JoinString(const std::vector& strs, char sep, size_t startIndex = 0) +{ + std::string out; + for (size_t index = startIndex; index < strs.size(); ++index) { + if (!strs[index].empty()) { + out.append(strs[index]) += sep; + } + } + if (!out.empty()) { + out.pop_back(); + } + return out; +} + +inline std::string StripString(const std::string& str, const char* charSet = " \t\n\r") +{ + size_t startPos = str.find_first_not_of(charSet); + if (startPos == std::string::npos) { + return std::string(); + } + + return str.substr(startPos, str.find_last_not_of(charSet) - startPos + 1); +} +} // namespace + +// Help Functions NativeValue* CreateJsError(NativeEngine& engine, int32_t errCode, const std::string& message) { return engine.CreateError(CreateJsValue(engine, errCode), CreateJsValue(engine, message)); @@ -247,10 +330,332 @@ std::unique_ptr CreateAsyncTaskWithLastParam(NativeEngine& engine, Na std::unique_ptr(), result); } -bool GetABCFile(const std::string& hapPath, const std::string& srcPath, std::ostream &dest) +void FixExtName(std::string& path) +{ + if (path.empty()) { + return; + } + + if (StringEndWith(path, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) { + return; + } + + if (StringEndWith(path, EXT_NAME_ETS, sizeof(EXT_NAME_ETS) - 1)) { + path.erase(path.length() - (sizeof(EXT_NAME_ETS) - 1), sizeof(EXT_NAME_ETS) - 1); + } else if (StringEndWith(path, EXT_NAME_TS, sizeof(EXT_NAME_TS) - 1)) { + path.erase(path.length() - (sizeof(EXT_NAME_TS) - 1), sizeof(EXT_NAME_TS) - 1); + } else if (StringEndWith(path, EXT_NAME_JS, sizeof(EXT_NAME_JS) - 1)) { + path.erase(path.length() - (sizeof(EXT_NAME_JS) - 1), sizeof(EXT_NAME_JS) - 1); + } + + path.append(EXT_NAME_ABC); +} + +std::string GetInstallPath(const std::string& curJsModulePath, bool module) +{ + size_t pos = std::string::npos; + if (StringStartWith(curJsModulePath, BUNDLE_INSTALL_PATH, std::string(BUNDLE_INSTALL_PATH).length())) { + pos = std::string(BUNDLE_INSTALL_PATH).length() - 1; + } else { + if (!StringStartWith(curJsModulePath, OTHER_BUNDLE_INSTALL_PATH, + std::string(OTHER_BUNDLE_INSTALL_PATH).length())) { + return std::string(); + } + + pos = curJsModulePath.find('/', std::string(OTHER_BUNDLE_INSTALL_PATH).length()); + if (pos == std::string::npos) { + return std::string(); + } + } + + if (module) { + pos = curJsModulePath.find('/', pos + 1); + if (pos == std::string::npos) { + return std::string(); + } + } + + return curJsModulePath.substr(0, pos + 1); +} + +std::string MakeNewJsModulePath( + const std::string& curJsModulePath, const std::string& newJsModuleUri) +{ + std::string moduleInstallPath = GetInstallPath(curJsModulePath, true); + if (moduleInstallPath.empty()) { + return std::string(); + } + + std::vector pathVector; + SplitString(curJsModulePath, pathVector, moduleInstallPath.length()); + + if (pathVector.empty()) { + return std::string(); + } + + // Remove file name, reserve only dir name + pathVector.pop_back(); + + std::vector relativePathVector; + SplitString(newJsModuleUri, relativePathVector); + + for (auto& value : relativePathVector) { + if (value == ".") { + continue; + } else if (value == "..") { + if (pathVector.empty()) { + return std::string(); + } + pathVector.pop_back(); + } else { + pathVector.emplace_back(std::move(value)); + } + } + + std::string jsModulePath = moduleInstallPath + JoinString(pathVector, '/'); + FixExtName(jsModulePath); + if (jsModulePath.size() >= PATH_MAX) { + return std::string(); + } + + char path[PATH_MAX]; + if (realpath(jsModulePath.c_str(), path) != nullptr) { + return std::string(path); + } + return std::string(); +} + +std::string FindNpmPackageInPath(const std::string& npmPath) +{ + std::string fileName = npmPath + "/" + NPM_ENTRY_FILE; + + char path[PATH_MAX]; + if (fileName.size() >= PATH_MAX) { + return std::string(); + } + if (realpath(fileName.c_str(), path) != nullptr) { + return path; + } + + fileName = npmPath + "/" + NPM_ENTRY_LINK; + if (fileName.size() >= PATH_MAX) { + return std::string(); + } + if (realpath(fileName.c_str(), path) == nullptr) { + return std::string(); + } + + std::ifstream stream(path, std::ios::ate); + if (!stream.is_open()) { + return std::string(); + } + + auto fileLen = stream.tellg(); + if (fileLen >= PATH_MAX) { + return std::string(); + } + + stream.seekg(0); + stream.read(path, fileLen); + path[fileLen] = '\0'; + return npmPath + '/' + StripString(path); +} + +std::string FindNpmPackageInTopLevel( + const std::string& moduleInstallPath, const std::string& npmPackage, size_t start) +{ + for (size_t level = start; level <= MAX_NPM_LEVEL; ++level) { + std::string path = moduleInstallPath + NPM_PATH_SEGMENT + '/' + std::to_string(level) + '/' + npmPackage; + path = FindNpmPackageInPath(path); + if (!path.empty()) { + return path; + } + } + + return std::string(); +} + +std::string FindNpmPackage(const std::string& curJsModulePath, const std::string& npmPackage) +{ + std::string newJsModulePath = MakeNewJsModulePath(curJsModulePath, npmPackage); + if (!newJsModulePath.empty()) { + return newJsModulePath; + } + std::string moduleInstallPath = GetInstallPath(curJsModulePath); + if (moduleInstallPath.empty()) { + return std::string(); + } + std::vector pathVector; + SplitString(curJsModulePath, pathVector, moduleInstallPath.length()); + if (pathVector.empty()) { + return std::string(); + } + + if (pathVector[0] != NPM_PATH_SEGMENT) { + return FindNpmPackageInTopLevel(moduleInstallPath, npmPackage); + } + + // Remove file name, reserve only dir name + pathVector.pop_back(); + + // Find npm package until reach top level npm path such as 'node_modules/0', + // so there must be 2 element in vector + while (pathVector.size() > 2) { + std::string path = + moduleInstallPath + JoinString(pathVector, '/') + '/' + NPM_PATH_SEGMENT + '/' + npmPackage; + path = FindNpmPackageInPath(path); + if (!path.empty()) { + return path; + } + + pathVector.pop_back(); + } + + char* p = nullptr; + size_t index = std::strtoul(pathVector.back().c_str(), &p, 10); + if (p == nullptr || *p != '\0') { + return std::string(); + } + + return FindNpmPackageInTopLevel(moduleInstallPath, npmPackage, index); +} + +std::string ParseOhmUri( + const std::string originBundleName, const std::string& curJsModulePath, const std::string& newJsModuleUri) +{ + std::string moduleInstallPath; + std::vector pathVector; + size_t index = 0; + + if (StringStartWith(newJsModuleUri, PREFIX_BUNDLE, sizeof(PREFIX_BUNDLE) - 1)) { + SplitString(newJsModuleUri, pathVector, sizeof(PREFIX_BUNDLE) - 1); + + // Uri should have atleast 3 segments + if (pathVector.size() < 3) { + return std::string(); + } + + const auto& bundleName = pathVector[index++]; + if (bundleName == originBundleName) { + moduleInstallPath = std::string(BUNDLE_INSTALL_PATH); + } else { + moduleInstallPath = std::string(OTHER_BUNDLE_INSTALL_PATH); + moduleInstallPath.append(bundleName).append("/"); + } + moduleInstallPath.append(pathVector[index++]).append("/"); + } else if (StringStartWith(newJsModuleUri, PREFIX_MODULE, sizeof(PREFIX_MODULE) - 1)) { + SplitString(newJsModuleUri, pathVector, sizeof(PREFIX_MODULE) - 1); + + // Uri should have atleast 2 segments + if (pathVector.size() < 2) { + return std::string(); + } + + moduleInstallPath = GetInstallPath(curJsModulePath, false); + if (moduleInstallPath.empty()) { + return std::string(); + } + moduleInstallPath.append(pathVector[index++]).append("/"); + } else if (StringStartWith(newJsModuleUri, PREFIX_LOCAL, sizeof(PREFIX_LOCAL) - 1)) { + SplitString(newJsModuleUri, pathVector, sizeof(PREFIX_LOCAL) - 1); + + if (pathVector.empty()) { + return std::string(); + } + + moduleInstallPath = GetInstallPath(curJsModulePath); + if (moduleInstallPath.empty()) { + return std::string(); + } + } else { + return std::string(); + } + + if (pathVector[index] != NPM_PATH_SEGMENT) { + return moduleInstallPath + JoinString(pathVector, '/', index); + } + + return FindNpmPackageInTopLevel(moduleInstallPath, JoinString(pathVector, '/', index + 1)); +} + +bool MakeFilePath(const std::string& codePath, const std::string& modulePath, std::string& fileName) +{ + std::string path(codePath); + path.append("/").append(modulePath); + if (path.length() > PATH_MAX) { + HILOG_ERROR("Path length(%{public}d) longer than MAX(%{public}d)", (int32_t)path.length(), PATH_MAX); + return false; + } + char resolvedPath[PATH_MAX + 1] = { 0 }; + if (realpath(path.c_str(), resolvedPath) != nullptr) { + fileName = resolvedPath; + return true; + } + + auto start = path.find_last_of('/'); + auto end = path.find_last_of('.'); + if (end == std::string::npos || end == 0) { + HILOG_ERROR("No secondary file path"); + return false; + } + + auto pos = path.find_last_of('.', end - 1); + if (pos == std::string::npos) { + HILOG_ERROR("No secondary file path"); + return false; + } + + path.erase(start + 1, pos - start); + HILOG_INFO("Try using secondary file path: %{public}s", path.c_str()); + + if (realpath(path.c_str(), resolvedPath) == nullptr) { + HILOG_ERROR("Failed to call realpath, errno = %{public}d", errno); + return false; + } + + fileName = resolvedPath; + return true; +} + +std::string GetOhmUri(const std::shared_ptr &abilityInfo) +{ + std::string ohmUri; + if (!abilityInfo) { + HILOG_ERROR("GetOhmUri::AbilityInfo is nullptr"); + return ohmUri; + } + + std::string srcPath(abilityInfo->package); + if (!abilityInfo->isModuleJson) { + /* temporary compatibility api8 + config.json */ + srcPath.append("/assets/js/"); + if (!abilityInfo->srcPath.empty()) { + srcPath.append(abilityInfo->srcPath); + } + srcPath.append("/").append(abilityInfo->name).append(".abc"); + } else { + if (abilityInfo->srcEntrance.empty()) { + HILOG_ERROR("GetOhmUri::AbilityInfo srcEntrance is empty"); + return ohmUri; + } + srcPath.append("/"); + srcPath.append(abilityInfo->srcEntrance); + srcPath.erase(srcPath.rfind(".")); + srcPath.append(".abc"); + } + HILOG_DEBUG("GetOhmUri::JsAbility srcPath is %{public}s", srcPath.c_str()); + + if (!MakeFilePath(Constants::LOCAL_CODE_PATH, srcPath, ohmUri)) { + HILOG_ERROR("GetOhmUri::Failed to make module file path: %{private}s", srcPath.c_str()); + } + + return ohmUri; +} + +bool GetFileBufferFromHap(const std::string& hapPath, const std::string& srcPath, std::ostream &dest) { if (hapPath.empty() || srcPath.empty()) { - HILOG_ERROR("GetABCFile::hapPath or srcPath is nullptr"); + HILOG_ERROR("GetFileBufferFromHap::hapPath or srcPath is nullptr"); return false; } @@ -265,19 +670,65 @@ bool GetABCFile(const std::string& hapPath, const std::string& srcPath, std::ost } RuntimeExtractor runtimeExtractor(loadPath); if (!runtimeExtractor.Init()) { - HILOG_ERROR("GetABCFile::Runtime extractor init failed"); + HILOG_ERROR("GetFileBufferFromHap::Runtime extractor init failed"); return false; } std::regex srcPattern(std::string(Constants::LOCAL_CODE_PATH) + std::string(Constants::FILE_SEPARATOR)); std::string relativePath = std::regex_replace(srcPath, srcPattern, ""); relativePath = relativePath.substr(relativePath.find(std::string(Constants::FILE_SEPARATOR)) + 1); - if (!runtimeExtractor.ExtractABCFile(relativePath, dest)) { - HILOG_ERROR("GetABCFile::Extract abc file failed"); + if (!runtimeExtractor.ExtractByName(relativePath, dest)) { + HILOG_ERROR("GetFileBufferFromHap::Extract abc file failed"); return false; } return true; } + +bool GetFileListFromHap(const std::string& hapPath, const std::string& srcPath, std::vector& assetList) +{ + if (hapPath.empty() || srcPath.empty()) { + HILOG_ERROR("GetFileListFromHap::hapPath or srcPath is nullptr"); + return false; + } + + std::string loadPath; + if (!StringStartWith(hapPath, Constants::SYSTEM_APP_PATH, sizeof(Constants::SYSTEM_APP_PATH) - 1)) { + std::regex hapPattern(std::string(Constants::ABS_CODE_PATH) + std::string(Constants::FILE_SEPARATOR)); + loadPath = std::regex_replace(hapPath, hapPattern, ""); + loadPath = std::string(Constants::LOCAL_CODE_PATH) + std::string(Constants::FILE_SEPARATOR) + + loadPath.substr(loadPath.find(std::string(Constants::FILE_SEPARATOR)) + 1); + } else { + loadPath = hapPath; + } + RuntimeExtractor runtimeExtractor(loadPath); + if (!runtimeExtractor.Init()) { + HILOG_ERROR("GetFileListFromHap::Runtime extractor init failed"); + return false; + } + + std::regex srcPattern(std::string(Constants::LOCAL_CODE_PATH) + std::string(Constants::FILE_SEPARATOR)); + std::string relativePath = std::regex_replace(srcPath, srcPattern, ""); + relativePath = relativePath.substr(relativePath.find(std::string(Constants::FILE_SEPARATOR)) + 1); + + std::vector fileList; + if (!runtimeExtractor.GetZipFileNames(fileList)) { + HILOG_ERROR("GetFileListFromHap::Get file list failed"); + return false; + } + + std::regex replacePattern(relativePath); + for (auto value : fileList) { + if (StringStartWith(value, relativePath.c_str(), sizeof(relativePath.c_str()) - 1)) { + std::string realpath = std::regex_replace(value, replacePattern, ""); + if (realpath.find(Constants::FILE_SEPARATOR) != std::string::npos) { + continue; + } + assetList.emplace_back(value); + } + } + + return true; +} } // namespace AbilityRuntime } // namespace OHOS diff --git a/frameworks/native/runtime/runtime_extractor.cpp b/frameworks/native/runtime/runtime_extractor.cpp index 2b51e23cc6..831cee93a4 100755 --- a/frameworks/native/runtime/runtime_extractor.cpp +++ b/frameworks/native/runtime/runtime_extractor.cpp @@ -28,11 +28,5 @@ RuntimeExtractor::~RuntimeExtractor() { HILOG_DEBUG("RuntimeExtractor destroyed"); } - -bool RuntimeExtractor::ExtractABCFile(const std::string& srcPath, std::ostream &dest) const -{ - HILOG_DEBUG("%{public}s: hapPath is %{public}s", __func__, srcPath.c_str()); - return AppExecFwk::BaseExtractor::ExtractByName(srcPath, dest); -} } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/runtime/BUILD.gn b/interfaces/inner_api/runtime/BUILD.gn index b1740a1f35..e5b82d43f7 100644 --- a/interfaces/inner_api/runtime/BUILD.gn +++ b/interfaces/inner_api/runtime/BUILD.gn @@ -37,6 +37,7 @@ ohos_shared_library("runtime") { "${ability_runtime_native_path}/runtime/hdc_register.cpp", "${ability_runtime_native_path}/runtime/js_console_log.cpp", "${ability_runtime_native_path}/runtime/js_data_struct_converter.cpp", + "${ability_runtime_native_path}/runtime/js_module_reader.cpp", "${ability_runtime_native_path}/runtime/js_module_searcher.cpp", "${ability_runtime_native_path}/runtime/js_runtime.cpp", "${ability_runtime_native_path}/runtime/js_runtime_utils.cpp", @@ -53,11 +54,14 @@ ohos_shared_library("runtime") { public_configs = [ ":runtime_public_config" ] deps = [ + ":runtime_extractor", "//arkcompiler/ets_runtime:libark_jsruntime", "//foundation/arkui/napi:ace_napi_ark", - ":runtime_extractor" ] + public_deps = + [ "${bundlefwk_inner_api_path}/appexecfwk_base:appexecfwk_base" ] + external_deps = [ "ability_base:base", "ability_base:configuration", @@ -65,7 +69,6 @@ ohos_shared_library("runtime") { "ability_base:zuri", "ability_runtime:ability_manager", "ability_runtime:app_manager", - "bundle_framework:appexecfwk_base", "eventhandler:libeventhandler", "hiviewdfx_hilog_native:libhilog", "napi:ace_napi", @@ -97,26 +100,18 @@ ohos_shared_library("runtime") { ohos_source_set("runtime_extractor") { include_dirs = [ "include" ] - sources = [ - "${ability_runtime_native_path}/runtime/runtime_extractor.cpp", - ] + sources = [ "${ability_runtime_native_path}/runtime/runtime_extractor.cpp" ] - configs = [ - "${ability_runtime_services_path}/common:common_config", - ] + configs = [ "${ability_runtime_services_path}/common:common_config" ] cflags = [] if (target_cpu == "arm") { cflags += [ "-DBINDER_IPC_32BIT" ] } - public_deps = [ - "${bundlefwk_services_path}/bundlemgr:parser_common", - ] - - external_deps = [ - "hiviewdfx_hilog_native:libhilog", - ] + public_deps = [ "${bundlefwk_services_path}/bundlemgr:parser_common" ] + + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] subsystem_name = "ability" part_name = "ability_runtime" diff --git a/interfaces/inner_api/runtime/include/js_runtime.h b/interfaces/inner_api/runtime/include/js_runtime.h index d7d7191835..19631c7a87 100644 --- a/interfaces/inner_api/runtime/include/js_runtime.h +++ b/interfaces/inner_api/runtime/include/js_runtime.h @@ -56,7 +56,7 @@ public: } std::unique_ptr LoadModule(const std::string& moduleName, - const std::string& modulePath, bool esmodule = false, const std::string& hapPath = nullptr); + const std::string& modulePath, const std::string& hapPath, bool esmodule = false); std::unique_ptr LoadSystemModule( const std::string& moduleName, NativeValue* const* argv = nullptr, size_t argc = 0); void PostTask(const std::function& task, const std::string& name, int64_t delayTime); @@ -66,7 +66,7 @@ public: void NotifyApplicationState(bool isBackground) override; bool RunSandboxScript(const std::string& path, const std::string& hapPath); - virtual bool RunScript(const std::string& path, const std::string& hapPath = nullptr) = 0; + virtual bool RunScript(const std::string& path, const std::string& hapPath) = 0; void PreloadSystemModule(const std::string& moduleName) override; diff --git a/interfaces/inner_api/runtime/include/js_runtime_utils.h b/interfaces/inner_api/runtime/include/js_runtime_utils.h index 9091fb7935..146b74210c 100644 --- a/interfaces/inner_api/runtime/include/js_runtime_utils.h +++ b/interfaces/inner_api/runtime/include/js_runtime_utils.h @@ -23,6 +23,7 @@ #include "native_engine/native_engine.h" +#include "ability_info.h" #include "js_runtime.h" namespace OHOS { @@ -112,7 +113,6 @@ NativeValue* CreateNativeArray(NativeEngine& engine, const std::vector& data) return arrayValue; } -bool StringStartWith(const std::string& str, const char* startStr, size_t startStrLen); NativeValue* CreateJsError(NativeEngine& engine, int32_t errCode, const std::string& message = std::string()); void BindNativeFunction(NativeEngine& engine, NativeObject& object, const char* name, NativeCallback func); void BindNativeProperty(NativeObject& object, const char* name, NativeCallback getter); @@ -187,7 +187,20 @@ std::unique_ptr CreateAsyncTaskWithLastParam(NativeEngine& engine, Na std::unique_ptr CreateAsyncTaskWithLastParam(NativeEngine& engine, NativeValue* lastParam, nullptr_t, nullptr_t, NativeValue** result); -bool GetABCFile(const std::string& hapPath, const std::string& srcPath, std::ostream &dest); +void FixExtName(std::string& path); +std::string GetInstallPath(const std::string& curJsModulePath, bool module = true); +std::string MakeNewJsModulePath(const std::string& curJsModulePath, const std::string& newJsModuleUri); +std::string FindNpmPackageInPath(const std::string& npmPath); +std::string FindNpmPackageInTopLevel( + const std::string& moduleInstallPath, const std::string& npmPackage, size_t start = 0); +std::string FindNpmPackage(const std::string& curJsModulePath, const std::string& npmPackage); +std::string ParseOhmUri( + const std::string bundleName, const std::string& curJsModulePath, const std::string& newJsModuleUri); +std::string ParseJsModuleUri(const std::string& curJsModulePath, const std::string& newJsModuleUri); +bool MakeFilePath(const std::string& codePath, const std::string& modulePath, std::string& fileName); +std::string GetOhmUri(const std::shared_ptr &abilityInfo); +bool GetFileBufferFromHap(const std::string& hapPath, const std::string& srcPath, std::ostream &dest); +bool GetFileListFromHap(const std::string& hapPath, const std::string& srcPath, std::vector& assetList); } // namespace AbilityRuntime } // namespace OHOS diff --git a/interfaces/inner_api/runtime/include/runtime_extractor.h b/interfaces/inner_api/runtime/include/runtime_extractor.h index a76a9272dc..26c09333a7 100755 --- a/interfaces/inner_api/runtime/include/runtime_extractor.h +++ b/interfaces/inner_api/runtime/include/runtime_extractor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -24,14 +24,6 @@ class RuntimeExtractor : public AppExecFwk::BaseExtractor { public: explicit RuntimeExtractor(const std::string &source); virtual ~RuntimeExtractor() override; - - /** - * @brief Extract the abc file of a hap to dest stream. - * @param srcPath Indicates the src path of the abc file in hap. - * @param dest Indicates the obtained std::ostream object. - * @return Returns true if the Profile is successfully extracted; returns false otherwise. - */ - bool ExtractABCFile(const std::string& srcPath, std::ostream &dest) const; }; } // namespace AbilityRuntime } // namespace OHOS