Support using dynamic-import to load native module

issue :  https://gitee.com/openharmony/developtools_ace_ets2bundle/issues/I76TBP?from=project-issue

Signed-off-by: DaiHN <daihuina1@huawei.com>
Change-Id: I7e5eab96e7fe252aa96bb38256728234bd2d90d5
This commit is contained in:
DaiHN 2023-06-01 19:30:08 +08:00
parent 8c6170a146
commit 52d373fa63
12 changed files with 255 additions and 148 deletions

View File

@ -726,6 +726,7 @@ ecma_source = [
"ecmascript/mem/verification.cpp",
"ecmascript/mem/work_manager.cpp",
"ecmascript/module/js_module_manager.cpp",
"ecmascript/module/js_dynamic_import.cpp",
"ecmascript/module/js_module_namespace.cpp",
"ecmascript/module/js_module_record.cpp",
"ecmascript/module/js_module_source_text.cpp",

View File

@ -528,6 +528,19 @@ public:
return res;
}
inline static bool IsNativeModuleRequest(const CString &requestName)
{
if (requestName[0] != '@') {
return false;
}
if (StringHelper::StringStartWith(requestName, PathHelper::REQUIRE_NAPI_OHOS_PREFIX) ||
StringHelper::StringStartWith(requestName, PathHelper::REQUIRE_NAPI_APP_PREFIX) ||
StringHelper::StringStartWith(requestName, PathHelper::REQUIRE_NAITVE_MODULE_PREFIX)) {
return true;
}
return false;
}
static CString ConcatFileNameWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile, CString &baseFileName,
CString recordName, CString requestName)
{
@ -552,6 +565,26 @@ public:
}
return entryPoint;
}
static CString GetStrippedModuleName(const CString &moduleRequestName)
{
// @xxx:**** -> ****
size_t pos = moduleRequestName.find(':');
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Unknown format " << moduleRequestName;
}
return moduleRequestName.substr(pos + 1);
}
static CString GetInternalModulePrefix(const CString &moduleRequestName)
{
// @xxx:* -> xxx
size_t pos = moduleRequestName.find(':');
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Unknown format " << moduleRequestName;
}
return moduleRequestName.substr(1, pos - 1);
}
};
} // namespace panda::ecmascript::base
#endif // ECMASCRIPT_BASE_PATH_HELPER_H

View File

@ -25,6 +25,7 @@
#include "ecmascript/jspandafile/js_pandafile_manager.h"
#include "ecmascript/js_promise.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/module/js_dynamic_import.h"
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/platform/file.h"
#include "ecmascript/require/js_cjs_module.h"
@ -147,6 +148,13 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
CString entryPoint = JSPandaFile::ENTRY_MAIN_FUNCTION;
CString baseFilename = ConvertToString(dirPath.GetTaggedValue());
CString fileNameStr = "";
CString requestPath = ConvertToString(specifierString.GetTaggedValue());
// resolve native module
auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(requestPath);
if (isNative) {
return DynamicImport::ExecuteNativeModule(thread, specifierString, moduleType, resolve, reject);
}
if (recordName->IsUndefined()) {
moduleName = ResolveFilenameFromNative(thread, dirPath.GetTaggedValue(),
specifierString.GetTaggedValue());
@ -154,7 +162,6 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
fileNameStr = ConvertToString(moduleName.GetTaggedValue());
} else {
CString recordNameStr = ConvertToString(recordName.GetTaggedValue());
CString requestModule = ConvertToString(specifierString.GetTaggedValue());
std::shared_ptr<JSPandaFile> jsPandaFile =
JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, baseFilename, recordNameStr.c_str());
if (jsPandaFile == nullptr) {
@ -164,7 +171,7 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
}
entryPoint =
PathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(), baseFilename, recordNameStr, requestModule);
PathHelper::ConcatFileNameWithMerge(thread, jsPandaFile.get(), baseFilename, recordNameStr, requestPath);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
fileNameStr = baseFilename;
moduleName = vm->GetFactory()->NewFromUtf8(entryPoint);
@ -177,8 +184,10 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, CatchException(thread, reject));
}
bool isModule = jsPandaFile->IsModule(thread, entryPoint);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
ModuleManager *moduleManager = vm->GetModuleManager();
JSMutableHandle<JSTaggedValue> moduleNamespace(thread, JSTaggedValue::Undefined());
if (!vm->GetModuleManager()->IsImportedModuleLoaded(moduleName.GetTaggedValue())) {
if (!moduleManager->IsImportedModuleLoaded(moduleName.GetTaggedValue())) {
if (!JSPandaFileExecutor::ExecuteFromFile(thread, fileNameStr.c_str(), entryPoint.c_str(), false, true)) {
CString msg = "Cannot execute request dynamic-imported module : " + entryPoint;
JSTaggedValue error = factory->GetJSError(ErrorType::REFERENCE_ERROR, msg.c_str()).GetTaggedValue();
@ -192,11 +201,11 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
} else {
// b. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
JSHandle<SourceTextModule> moduleRecord =
vm->GetModuleManager()->HostGetImportedModule(moduleName.GetTaggedValue());
moduleManager->HostGetImportedModule(moduleName.GetTaggedValue());
// d. Let namespace be ? GetModuleNamespace(moduleRecord).
moduleNamespace.Update(SourceTextModule::GetModuleNamespace(thread, moduleRecord));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
}
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread,

View File

@ -659,8 +659,7 @@ void BytecodeInfoCollector::CollectRecordExportInfo(const CString &recordName)
starExportEntry.Update(starEntriesArray->Get(index));
JSTaggedValue moduleRequest = starExportEntry->GetModuleRequest();
CString moduleRequestName = ConvertToString(EcmaString::Cast(moduleRequest.GetTaggedObject()));
auto [isNative, _] = ModuleManager::CheckNativeModule(moduleRequestName);
if (isNative) {
if (base::PathHelper::IsNativeModuleRequest(moduleRequestName)) {
return;
}
CString baseFileName = jsPandaFile_->GetJSPandaFileDesc();

View File

@ -0,0 +1,52 @@
/*
* 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.
*/
#include "ecmascript/module/js_dynamic_import.h"
#include "ecmascript/base/path_helper.h"
#include "ecmascript/builtins/builtins_promise_job.h"
#include "ecmascript/js_function.h"
#include "ecmascript/module/js_module_manager.h"
namespace panda::ecmascript {
using PathHelper = base::PathHelper;
using BuiltinsPromiseJob = builtins::BuiltinsPromiseJob;
JSTaggedValue DynamicImport::ExecuteNativeModule(JSThread *thread, JSHandle<EcmaString> specifierString,
ModuleTypes moduleType, JSHandle<JSPromiseReactionsFunction> resolve, JSHandle<JSPromiseReactionsFunction> reject)
{
ModuleManager *moduleManager = thread->GetEcmaVM()->GetModuleManager();
CString requestPath = ConvertToString(specifierString.GetTaggedValue());
CString entryPoint = PathHelper::GetStrippedModuleName(requestPath);
JSHandle<JSTaggedValue> nativeModule = moduleManager->ResolveNativeModule(requestPath, moduleType);
JSHandle<SourceTextModule> requiredModule = JSHandle<SourceTextModule>::Cast(nativeModule);
if (!SourceTextModule::LoadNativeModule(thread, requiredModule,
JSHandle<JSTaggedValue>(specifierString), moduleType)) {
LOG_FULL(WARN) << "LoadNativeModule " << requestPath << " failed";
}
JSHandle<JSTaggedValue> nativeExports(thread, requiredModule->GetModuleValue(thread, 0, false));
requiredModule->SetStatus(ModuleStatus::EVALUATED);
JSHandle<JSTaggedValue> moduleNamespace = SourceTextModule::GetModuleNamespace(thread, requiredModule);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, BuiltinsPromiseJob::CatchException(thread, reject));
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
EcmaRuntimeCallInfo *info =
EcmaInterpreter::NewRuntimeCallInfo(thread,
JSHandle<JSTaggedValue>(resolve),
undefined, undefined, 1);
info->SetCallArg(moduleNamespace.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
return JSFunction::Call(info);
}
} // namespace panda::ecmascript

View File

@ -0,0 +1,31 @@
/*
* 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_MODULE_JS_DYNAMIC_IMPORT_H
#define ECMASCRIPT_MODULE_JS_DYNAMIC_IMPORT_H
#include "ecmascript/builtins/builtins_promise_job.h"
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/module/js_module_source_text.h"
namespace panda::ecmascript {
class DynamicImport {
public:
static JSTaggedValue ExecuteNativeModule(JSThread *thread, JSHandle<EcmaString> specifierString,
ModuleTypes moduleType, JSHandle<JSPromiseReactionsFunction> resolve,
JSHandle<JSPromiseReactionsFunction> reject);
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_MODULE_JS_DYNAMIC_IMPORT_H

View File

@ -108,7 +108,7 @@ JSTaggedValue ModuleManager::GetModuleValueOutterInternal(int32_t index, JSTagge
SourceTextModule *module = SourceTextModule::Cast(resolvedModule.GetTaggedObject());
ModuleTypes moduleType = module->GetTypes();
if (IsNativeModule(moduleType)) {
if (SourceTextModule::IsNativeModule(moduleType)) {
return GetNativeModuleValue(thread, currentModule, resolvedModule, binding);
}
if (module->GetTypes() == ModuleTypes::CJS_MODULE) {
@ -559,7 +559,7 @@ JSTaggedValue ModuleManager::GetModuleNamespaceInternal(int32_t index, JSTaggedV
JSHandle<SourceTextModule> requiredModuleST = JSHandle<SourceTextModule>::Cast(requiredModule);
ModuleTypes moduleType = requiredModuleST->GetTypes();
// if requiredModuleST is Native module
if (ModuleManager::IsNativeModule(moduleType)) {
if (SourceTextModule::IsNativeModule(moduleType)) {
return SourceTextModule::Cast(requiredModuleST.GetTaggedValue())->GetModuleValue(thread, 0, false);
}
// if requiredModuleST is CommonJS
@ -647,114 +647,6 @@ int ModuleManager::GetExportObjectIndex(EcmaVM *vm, JSHandle<SourceTextModule> e
return index;
}
std::pair<bool, ModuleTypes> ModuleManager::CheckNativeModule(const CString &moduleRequestName)
{
if (moduleRequestName[0] != '@' ||
StringHelper::StringStartWith(moduleRequestName, PathHelper::PREFIX_BUNDLE) ||
StringHelper::StringStartWith(moduleRequestName, PathHelper::PREFIX_PACKAGE)||
moduleRequestName.find(':') == CString::npos) {
return {false, ModuleTypes::UNKNOWN};
}
if (StringHelper::StringStartWith(moduleRequestName, PathHelper::REQUIRE_NAPI_OHOS_PREFIX)) {
return {true, ModuleTypes::OHOS_MODULE};
} else if (StringHelper::StringStartWith(moduleRequestName, PathHelper::REQUIRE_NAPI_APP_PREFIX)) {
return {true, ModuleTypes::APP_MODULE};
} else if (StringHelper::StringStartWith(moduleRequestName, PathHelper::REQUIRE_NAITVE_MODULE_PREFIX)) {
return {true, ModuleTypes::NATIVE_MODULE};
} else {
return {true, ModuleTypes::INTERNAL_MODULE};
}
}
CString ModuleManager::GetStrippedModuleName(const CString &moduleRequestName)
{
size_t pos = moduleRequestName.find(':');
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Unknown format " << moduleRequestName;
}
return moduleRequestName.substr(pos + 1);
}
CString ModuleManager::GetInternalModuleDir(const CString &moduleRequestName)
{
// @xxx:* -> xxx
size_t pos = moduleRequestName.find(':');
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Unknown format " << moduleRequestName;
}
return moduleRequestName.substr(1, pos - 1);
}
Local<JSValueRef> ModuleManager::GetRequireNativeModuleFunc(EcmaVM *vm, ModuleTypes moduleType)
{
Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm);
auto globalConstants = vm->GetJSThread()->GlobalConstants();
auto funcName = (moduleType == ModuleTypes::NATIVE_MODULE) ?
globalConstants->GetHandledRequireNativeModuleString() :
globalConstants->GetHandledRequireNapiString();
return globalObject->Get(vm, JSNApiHelper::ToLocal<StringRef>(funcName));
}
void ModuleManager::MakeAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
const CString &moduleName)
{
size_t pos = moduleName.find_last_of('/');
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Invalid native module " << moduleName;
UNREACHABLE();
}
CString soName = moduleName.substr(pos + 1);
CString path = moduleName.substr(0, pos);
// use module name as so name
arguments[0] = StringRef::NewFromUtf8(vm, soName.c_str());
arguments.emplace_back(BooleanRef::New(vm, true));
arguments.emplace_back(StringRef::NewFromUtf8(vm, path.c_str()));
}
void ModuleManager::MakeInternalArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
const CString &moduleRequestName)
{
arguments.emplace_back(BooleanRef::New(vm, false));
arguments.emplace_back(StringRef::NewFromUtf8(vm, ""));
CString moduleDir = GetInternalModuleDir(moduleRequestName);
arguments.emplace_back(StringRef::NewFromUtf8(vm, moduleDir.c_str()));
}
bool ModuleManager::LoadNativeModule(JSThread *thread, JSHandle<SourceTextModule> &requiredModule,
const JSHandle<JSTaggedValue> &moduleRequest, ModuleTypes moduleType)
{
EcmaVM *vm = thread->GetEcmaVM();
LocalScope scope(vm);
CString moduleRequestName = ConvertToString(EcmaString::Cast(moduleRequest->GetTaggedObject()));
CString moduleName = GetStrippedModuleName(moduleRequestName);
std::vector<Local<JSValueRef>> arguments;
LOG_FULL(DEBUG) << "Request module is " << moduleRequestName;
arguments.emplace_back(StringRef::NewFromUtf8(vm, moduleName.c_str()));
if (moduleType == ModuleTypes::APP_MODULE) {
MakeAppArgs(vm, arguments, moduleName);
} else if (moduleType == ModuleTypes::INTERNAL_MODULE) {
MakeInternalArgs(vm, arguments, moduleRequestName);
}
auto maybeFuncRef = GetRequireNativeModuleFunc(vm, moduleType);
// some function(s) may not registered in global object for non-main thread
if (!maybeFuncRef->IsFunction()) {
LOG_FULL(WARN) << "Not found require func";
return false;
}
Local<FunctionRef> funcRef = maybeFuncRef;
auto exportObject = funcRef->Call(vm, JSValueRef::Undefined(vm), arguments.data(), arguments.size());
if (UNLIKELY(thread->HasPendingException())) {
thread->ClearException();
LOG_FULL(ERROR) << "LoadNativeModule has exception";
return false;
}
requiredModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject));
return true;
}
JSHandle<JSTaggedValue> ModuleManager::HostResolveImportedModule(const JSPandaFile *jsPandaFile,
const CString &filename)
{

View File

@ -79,16 +79,6 @@ public:
static CString GetRecordName(JSTaggedValue module);
static int GetExportObjectIndex(EcmaVM *vm, JSHandle<SourceTextModule> ecmaModule, const std::string &key);
inline static bool IsNativeModule(ModuleTypes moduleType)
{
return moduleType == ModuleTypes::OHOS_MODULE ||
moduleType == ModuleTypes::APP_MODULE ||
moduleType == ModuleTypes::NATIVE_MODULE ||
moduleType == ModuleTypes::INTERNAL_MODULE;
}
static std::pair<bool, ModuleTypes> CheckNativeModule(const CString &moduleRequestName);
static bool LoadNativeModule(JSThread *thread, JSHandle<SourceTextModule> &requiredModule,
const JSHandle<JSTaggedValue> &moduleRequest, ModuleTypes moduleType);
private:
NO_COPY_SEMANTIC(ModuleManager);
NO_MOVE_SEMANTIC(ModuleManager);
@ -117,13 +107,6 @@ private:
JSHandle<JSTaggedValue> ResolveModuleWithMerge(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &recordName);
static Local<JSValueRef> GetRequireNativeModuleFunc(EcmaVM *vm, ModuleTypes moduleType);
static CString GetStrippedModuleName(const CString &moduleRequestName);
static CString GetInternalModuleDir(const CString &moduleRequestName);
static void MakeAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments, const CString &moduleName);
static void MakeInternalArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
const CString &moduleRequestName);
static constexpr uint32_t DEAULT_DICTIONART_CAPACITY = 4;
EcmaVM *vm_ {nullptr};

View File

@ -29,6 +29,8 @@
namespace panda::ecmascript {
using PathHelper = base::PathHelper;
using StringHelper = base::StringHelper;
CVector<std::string> SourceTextModule::GetExportedNames(JSThread *thread, const JSHandle<SourceTextModule> &module,
const JSHandle<TaggedArray> &exportStarSet)
{
@ -84,7 +86,7 @@ JSHandle<JSTaggedValue> SourceTextModule::HostResolveImportedModuleWithMerge(
}
CString moduleRequestName = ConvertToString(EcmaString::Cast(moduleRequest->GetTaggedObject()));
auto [isNative, moduleType] = ModuleManager::CheckNativeModule(moduleRequestName);
auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(moduleRequestName);
if (isNative) {
return moduleManager->ResolveNativeModule(moduleRequestName, moduleType);
}
@ -265,12 +267,103 @@ void SourceTextModule::InstantiateCJS(JSThread *thread, const JSHandle<SourceTex
InitializeEnvironment(thread, currentModule, cjsModuleName, cjsExports, isBundle);
}
std::pair<bool, ModuleTypes> SourceTextModule::CheckNativeModule(const CString &moduleRequestName)
{
if (moduleRequestName[0] != '@' ||
StringHelper::StringStartWith(moduleRequestName, PathHelper::PREFIX_BUNDLE) ||
StringHelper::StringStartWith(moduleRequestName, PathHelper::PREFIX_PACKAGE)||
moduleRequestName.find(':') == CString::npos) {
return {false, ModuleTypes::UNKNOWN};
}
if (StringHelper::StringStartWith(moduleRequestName, PathHelper::REQUIRE_NAPI_OHOS_PREFIX)) {
return {true, ModuleTypes::OHOS_MODULE};
}
if (StringHelper::StringStartWith(moduleRequestName, PathHelper::REQUIRE_NAPI_APP_PREFIX)) {
return {true, ModuleTypes::APP_MODULE};
}
if (StringHelper::StringStartWith(moduleRequestName, PathHelper::REQUIRE_NAITVE_MODULE_PREFIX)) {
return {true, ModuleTypes::NATIVE_MODULE};
}
return {true, ModuleTypes::INTERNAL_MODULE};
}
Local<JSValueRef> SourceTextModule::GetRequireNativeModuleFunc(EcmaVM *vm, ModuleTypes moduleType)
{
Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm);
auto globalConstants = vm->GetJSThread()->GlobalConstants();
auto funcName = (moduleType == ModuleTypes::NATIVE_MODULE) ?
globalConstants->GetHandledRequireNativeModuleString() :
globalConstants->GetHandledRequireNapiString();
return globalObject->Get(vm, JSNApiHelper::ToLocal<StringRef>(funcName));
}
void SourceTextModule::MakeAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
const CString &moduleName)
{
size_t pos = moduleName.find_last_of('/');
if (pos == CString::npos) {
LOG_FULL(FATAL) << "Invalid native module " << moduleName;
UNREACHABLE();
}
CString soName = moduleName.substr(pos + 1);
CString path = moduleName.substr(0, pos);
// use module name as so name
arguments[0] = StringRef::NewFromUtf8(vm, soName.c_str());
arguments.emplace_back(BooleanRef::New(vm, true));
arguments.emplace_back(StringRef::NewFromUtf8(vm, path.c_str()));
}
void SourceTextModule::MakeInternalArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
const CString &moduleRequestName)
{
arguments.emplace_back(BooleanRef::New(vm, false));
arguments.emplace_back(StringRef::NewFromUtf8(vm, ""));
CString moduleDir = PathHelper::GetInternalModulePrefix(moduleRequestName);
arguments.emplace_back(StringRef::NewFromUtf8(vm, moduleDir.c_str()));
}
bool SourceTextModule::LoadNativeModule(JSThread *thread, JSHandle<SourceTextModule> &requiredModule,
const JSHandle<JSTaggedValue> &moduleRequest, ModuleTypes moduleType)
{
EcmaVM *vm = thread->GetEcmaVM();
[[maybe_unused]] LocalScope scope(vm);
CString moduleRequestName = ConvertToString(EcmaString::Cast(moduleRequest->GetTaggedObject()));
CString moduleName = PathHelper::GetStrippedModuleName(moduleRequestName);
std::vector<Local<JSValueRef>> arguments;
LOG_FULL(DEBUG) << "Request module is " << moduleRequestName;
arguments.emplace_back(StringRef::NewFromUtf8(vm, moduleName.c_str()));
if (moduleType == ModuleTypes::APP_MODULE) {
MakeAppArgs(vm, arguments, moduleName);
} else if (moduleType == ModuleTypes::INTERNAL_MODULE) {
MakeInternalArgs(vm, arguments, moduleRequestName);
}
auto maybeFuncRef = GetRequireNativeModuleFunc(vm, moduleType);
// some function(s) may not registered in global object for non-main thread
if (!maybeFuncRef->IsFunction()) {
LOG_FULL(WARN) << "Not found require func";
return false;
}
Local<FunctionRef> funcRef = maybeFuncRef;
auto exportObject = funcRef->Call(vm, JSValueRef::Undefined(vm), arguments.data(), arguments.size());
if (UNLIKELY(thread->HasPendingException())) {
thread->ClearException();
LOG_FULL(ERROR) << "LoadNativeModule has exception";
return false;
}
requiredModule->StoreModuleValue(thread, 0, JSNApiHelper::ToJSHandle(exportObject));
return true;
}
void SourceTextModule::InstantiateNativeModule(JSThread *thread, JSHandle<SourceTextModule> &currentModule,
JSHandle<SourceTextModule> &requiredModule, const JSHandle<JSTaggedValue> &moduleRequest,
ModuleTypes moduleType)
{
if (requiredModule->GetStatus() != ModuleStatus::EVALUATED) {
if (!ModuleManager::LoadNativeModule(thread, requiredModule, moduleRequest, moduleType)) {
if (!SourceTextModule::LoadNativeModule(thread, requiredModule, moduleRequest, moduleType)) {
LOG_FULL(WARN) << "LoadNativeModule " << ConvertToString(
EcmaString::Cast(moduleRequest->GetTaggedObject())) << " failed";
return;
@ -845,7 +938,7 @@ int SourceTextModule::InnerModuleEvaluation(JSThread *thread, const JSHandle<Mod
requiredModule.Update(JSHandle<SourceTextModule>::Cast(requiredVal));
}
ModuleTypes moduleType = requiredModule->GetTypes();
if (ModuleManager::IsNativeModule(moduleType)) {
if (SourceTextModule::IsNativeModule(moduleType)) {
InstantiateNativeModule(thread, module, requiredModule, required, moduleType);
requiredModule->SetStatus(ModuleStatus::EVALUATED);
continue;
@ -930,7 +1023,7 @@ int SourceTextModule::ModuleEvaluation(JSThread *thread, const JSHandle<ModuleRe
requiredModule.Update(SourceTextModule::HostResolveImportedModuleWithMerge(thread, module, required));
}
ModuleTypes moduleType = requiredModule->GetTypes();
if (ModuleManager::IsNativeModule(moduleType)) {
if (SourceTextModule::IsNativeModule(moduleType)) {
InstantiateNativeModule(thread, module, requiredModule, required, moduleType);
requiredModule->SetStatus(ModuleStatus::EVALUATED);
continue;
@ -1309,7 +1402,7 @@ JSHandle<JSTaggedValue> SourceTextModule::ResolveLocalExport(JSThread *thread,
}
if ((JSTaggedValue::SameValue(ee->GetExportName(), exportName.GetTaggedValue())) ||
ModuleManager::IsNativeModule(moduleType)) {
IsNativeModule(moduleType)) {
// Adapter new module
if (module->GetIsNewBcVersion()) {
return JSHandle<JSTaggedValue>::Cast(factory->NewResolvedIndexBindingRecord(module,

View File

@ -90,6 +90,21 @@ public:
const JSHandle<IndirectExportEntry> &exportEntry, size_t idx, uint32_t len);
static void AddStarExportEntry(JSThread *thread, const JSHandle<SourceTextModule> &module,
const JSHandle<StarExportEntry> &exportEntry, size_t idx, uint32_t len);
static std::pair<bool, ModuleTypes> CheckNativeModule(const CString &moduleRequestName);
static Local<JSValueRef> GetRequireNativeModuleFunc(EcmaVM *vm, ModuleTypes moduleType);
static void MakeAppArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments, const CString &moduleName);
static void MakeInternalArgs(const EcmaVM *vm, std::vector<Local<JSValueRef>> &arguments,
const CString &moduleRequestName);
static bool LoadNativeModule(JSThread *thread, JSHandle<SourceTextModule> &requiredModule,
const JSHandle<JSTaggedValue> &moduleRequest, ModuleTypes moduleType);
inline static bool IsNativeModule(ModuleTypes moduleType)
{
return moduleType == ModuleTypes::OHOS_MODULE ||
moduleType == ModuleTypes::APP_MODULE ||
moduleType == ModuleTypes::NATIVE_MODULE ||
moduleType == ModuleTypes::INTERNAL_MODULE;
}
static constexpr size_t SOURCE_TEXT_MODULE_OFFSET = ModuleRecord::SIZE;
ACCESSORS(Environment, SOURCE_TEXT_MODULE_OFFSET, NAMESPACE_OFFSET);
ACCESSORS(Namespace, NAMESPACE_OFFSET, ECMA_MODULE_FILENAME);

View File

@ -511,31 +511,31 @@ HWTEST_F_L0(EcmaModuleTest, CheckNativeModule)
CString requestName6 = "@package:pkg_modules/.ohpm/json5@2.2.3/pkg_modules/json5/dist/index";
CString requestName7 = "@ohos/common";
std::pair<bool, ModuleTypes> res1 = ModuleManager::CheckNativeModule(requestName1);
std::pair<bool, ModuleTypes> res1 = SourceTextModule::CheckNativeModule(requestName1);
EXPECT_EQ(res1.first, false);
EXPECT_EQ(res1.second, ModuleTypes::UNKNOWN);
std::pair<bool, ModuleTypes> res2 = ModuleManager::CheckNativeModule(requestName2);
std::pair<bool, ModuleTypes> res2 = SourceTextModule::CheckNativeModule(requestName2);
EXPECT_EQ(res2.first, true);
EXPECT_EQ(res2.second, ModuleTypes::OHOS_MODULE);
std::pair<bool, ModuleTypes> res3 = ModuleManager::CheckNativeModule(requestName3);
std::pair<bool, ModuleTypes> res3 = SourceTextModule::CheckNativeModule(requestName3);
EXPECT_EQ(res3.first, true);
EXPECT_EQ(res3.second, ModuleTypes::APP_MODULE);
std::pair<bool, ModuleTypes> res4 = ModuleManager::CheckNativeModule(requestName4);
std::pair<bool, ModuleTypes> res4 = SourceTextModule::CheckNativeModule(requestName4);
EXPECT_EQ(res4.first, true);
EXPECT_EQ(res4.second, ModuleTypes::NATIVE_MODULE);
std::pair<bool, ModuleTypes> res5 = ModuleManager::CheckNativeModule(requestName5);
std::pair<bool, ModuleTypes> res5 = SourceTextModule::CheckNativeModule(requestName5);
EXPECT_EQ(res5.first, true);
EXPECT_EQ(res5.second, ModuleTypes::INTERNAL_MODULE);
std::pair<bool, ModuleTypes> res6 = ModuleManager::CheckNativeModule(requestName6);
std::pair<bool, ModuleTypes> res6 = SourceTextModule::CheckNativeModule(requestName6);
EXPECT_EQ(res6.first, false);
EXPECT_EQ(res6.second, ModuleTypes::UNKNOWN);
std::pair<bool, ModuleTypes> res7 = ModuleManager::CheckNativeModule(requestName7);
std::pair<bool, ModuleTypes> res7 = SourceTextModule::CheckNativeModule(requestName7);
EXPECT_EQ(res7.first, false);
EXPECT_EQ(res7.second, ModuleTypes::UNKNOWN);
}

View File

@ -142,8 +142,7 @@ GlobalTSTypeRef TSTypeParser::ResolveImportType(const JSPandaFile *jsPandaFile,
JSHandle<EcmaString> relativePath = GenerateImportRelativePath(importVarNamePath);
CString cstringRelativePath = ConvertToString(*relativePath);
// skip @ohos:|@app:|@native: prefixed imports
auto [isNative, _] = ModuleManager::CheckNativeModule(cstringRelativePath);
if (isNative) {
if (base::PathHelper::IsNativeModuleRequest(cstringRelativePath)) {
return GetAndStoreGT(jsPandaFile, typeId, recordName);
}