!7034 Bugfix of import shared-module cross hap and dynamic-importing

Merge pull request !7034 from DaiHN/fixsendable4
This commit is contained in:
openharmony_ci 2024-05-06 15:57:03 +00:00 committed by Gitee
commit b248dc6cf4
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
30 changed files with 493 additions and 59 deletions

View File

@ -271,6 +271,8 @@ private:
void InitializeModuleNamespace(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &objFuncClass) const;
void InitializeSModuleNamespace(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &sObjIHClass) const;
void InitializeCjsModule(const JSHandle<GlobalEnv> &env) const;
void InitializeCjsExports(const JSHandle<GlobalEnv> &env) const;

View File

@ -216,7 +216,7 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
}
// Loading request module.
thread->GetEcmaVM()->PushToDeregisterModuleList(entryPoint);
if (!moduleManager->IsImportedModuleLoaded(moduleName.GetTaggedValue())) {
if (!moduleManager->IsModuleLoaded(moduleName.GetTaggedValue())) {
if (!JSPandaFileExecutor::ExecuteFromAbcFile(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();
@ -234,7 +234,7 @@ JSTaggedValue BuiltinsPromiseJob::DynamicImportJob(EcmaRuntimeCallInfo *argv)
} else {
// b. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
JSHandle<SourceTextModule> moduleRecord =
moduleManager->HostGetImportedModule(moduleName.GetTaggedValue());
moduleManager->GetImportedModule(moduleName.GetTaggedValue());
JSHandle<JSTaggedValue> nameSp = SourceTextModule::GetModuleNamespace(thread, moduleRecord);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, CatchException(thread, reject));
// d. Let namespace be ? GetModuleNamespace(moduleRecord).

View File

@ -73,6 +73,7 @@ void Builtins::InitializeSObjectAndSFunction(const JSHandle<GlobalEnv> &env) con
InitializeSharedArray(env, sObjPrototype, sFuncPrototype);
InitializeSTypedArray(env, sObjPrototype, sFuncPrototype);
InitializeSArrayBuffer(env, sObjPrototype, sFuncPrototype);
InitializeSModuleNamespace(env, sObjIHClass);
env->SetSObjectFunctionPrototype(thread_, sObjPrototype);
}
@ -313,6 +314,25 @@ void Builtins::InitializeSMap(const JSHandle<GlobalEnv> &env, const JSHandle<JSO
env->SetSBuiltininMapFunction(thread_, mapFunction);
}
void Builtins::InitializeSModuleNamespace(const JSHandle<GlobalEnv> &env, const JSHandle<JSHClass> &sObjIHClass) const
{
[[maybe_unused]] EcmaHandleScope scope(thread_);
// SharedModuleNamespace.prototype
JSHandle<JSObject> moduleNamespacePrototype = factory_->NewSharedOldSpaceJSObjectWithInit(sObjIHClass);
JSHandle<JSTaggedValue> moduleNamespacePrototypeValue(moduleNamespacePrototype);
// SharedModuleNamespace.prototype_or_hclass
auto emptySLayout = thread_->GlobalConstants()->GetHandledEmptySLayoutInfo();
JSHandle<JSHClass> moduleNamespaceHClass = factory_->NewSEcmaHClass(ModuleNamespace::SIZE, 0,
JSType::JS_MODULE_NAMESPACE, moduleNamespacePrototypeValue, emptySLayout);
moduleNamespaceHClass->SetPrototype(thread_, JSTaggedValue::Null());
env->SetSharedModuleNamespaceClass(thread_, moduleNamespaceHClass.GetTaggedValue());
// SharedmoduleNamespace.prototype [ @@toStringTag ]
SetStringTagSymbol(env, moduleNamespacePrototype, "Module");
}
void Builtins::InitializeSFunction(const JSHandle<GlobalEnv> &env,
const JSHandle<JSFunction> &sFuncPrototype) const
{

View File

@ -305,7 +305,9 @@
V(JSTaggedValue, SharedFloat32ArrayRootHclassOnHeap, SHARED_FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX) \
V(JSTaggedValue, SharedFloat64ArrayRootHclassOnHeap, SHARED_FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX) \
V(JSTaggedValue, SharedBigInt64ArrayRootHclassOnHeap, SHARED_BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX) \
V(JSTaggedValue, SharedBigUint64ArrayRootHclassOnHeap, SHARED_BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX)
V(JSTaggedValue, SharedBigUint64ArrayRootHclassOnHeap, SHARED_BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX) \
V(JSTaggedValue, SharedModuleNamespaceClass, SHARED_MODULENAMESPACE_CLASS)
#define GLOBAL_ENV_FIELDS(V) \
GLOBAL_ENV_SHARED_FIELDS(V) \

View File

@ -1512,6 +1512,12 @@ inline bool JSTaggedValue::IsStarExportEntry() const
return IsHeapObject() && GetTaggedObject()->GetClass()->IsStarExportEntry();
}
inline bool JSTaggedValue::IsModuleBinding() const
{
return IsResolvedBinding() || IsResolvedIndexBinding() ||
IsResolvedRecordIndexBinding() || IsResolvedRecordBinding();
}
inline bool JSTaggedValue::IsResolvedBinding() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsResolvedBinding();

View File

@ -669,6 +669,7 @@ public:
bool IsLocalExportEntry() const;
bool IsIndirectExportEntry() const;
bool IsStarExportEntry() const;
bool IsModuleBinding() const;
bool IsResolvedBinding() const;
bool IsResolvedIndexBinding() const;
bool IsResolvedRecordIndexBinding() const;

View File

@ -117,7 +117,6 @@ Expected<JSTaggedValue, bool> JSPandaFileExecutor::ExecuteFromAbcFile(JSThread *
moduleRecord = sharedModuleManager->ResolveImportedModuleWithMerge(thread, name, entry, executeFromJob);
}
ASSERT(!SourceTextModule::IsSharedModule(JSHandle<SourceTextModule>(moduleRecord)));
SourceTextModule::Instantiate(thread, moduleRecord, executeFromJob);
if (thread->HasPendingException()) {
return Unexpected(false);

View File

@ -33,7 +33,7 @@ JSTaggedValue DynamicImport::ExecuteNativeOrJsonModule(JSThread *thread, JSHandl
{
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSMutableHandle<JSTaggedValue> requiredModule(thread, thread->GlobalConstants()->GetUndefined());
if (moduleManager->IsImportedModuleLoaded(specifierString.GetTaggedValue())) {
if (moduleManager->IsLocalModuleLoaded(specifierString.GetTaggedValue())) {
ModuleDeregister::ReviseLoadedModuleCount(thread, specifierString.GetTaggedValue());
JSHandle<SourceTextModule> moduleRecord =
moduleManager->HostGetImportedModule(specifierString.GetTaggedValue());

View File

@ -27,6 +27,7 @@
#include "ecmascript/module/js_module_deregister.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/module/js_shared_module_manager.h"
#include "ecmascript/module/module_data_extractor.h"
#include "ecmascript/module/module_manager_helper.h"
#include "ecmascript/module/module_path_helper.h"
@ -275,6 +276,15 @@ void ModuleManager::StoreModuleValueInternal(JSHandle<SourceTextModule> &current
JSHandle<JSTaggedValue> valueHandle(thread, value);
currentModule->StoreModuleValue(thread, keyHandle, valueHandle);
}
JSHandle<SourceTextModule> ModuleManager::GetImportedModule(JSTaggedValue referencing)
{
auto thread = vm_->GetJSThread();
if (!IsLocalModuleLoaded(referencing)) {
return SharedModuleManager::GetInstance()->GetSModule(thread, referencing);
} else {
return HostGetImportedModule(referencing);
}
}
JSHandle<SourceTextModule> ModuleManager::HostGetImportedModule(const CString &referencingModule)
{
@ -308,7 +318,7 @@ JSTaggedValue ModuleManager::HostGetImportedModule(void *src)
return result;
}
bool ModuleManager::IsImportedModuleLoaded(JSTaggedValue referencing)
bool ModuleManager::IsLocalModuleLoaded(JSTaggedValue referencing)
{
NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
int entry = dict->FindEntry(referencing);
@ -320,6 +330,21 @@ bool ModuleManager::IsImportedModuleLoaded(JSTaggedValue referencing)
return true;
}
bool ModuleManager::IsSharedModuleLoaded(JSTaggedValue referencing)
{
SharedModuleManager* sharedModuleManager = SharedModuleManager::GetInstance();
return sharedModuleManager->SearchInSModuleManager(vm_->GetJSThread(), ConvertToString(referencing));
}
bool ModuleManager::IsModuleLoaded(JSTaggedValue referencing)
{
if (IsLocalModuleLoaded(referencing)) {
return true;
}
SharedModuleManager* sharedModuleManager = SharedModuleManager::GetInstance();
return sharedModuleManager->SearchInSModuleManager(vm_->GetJSThread(), ConvertToString(referencing));
}
bool ModuleManager::IsEvaluatedModule(JSTaggedValue referencing)
{
NameDictionary *dict = NameDictionary::Cast(resolvedModules_.GetTaggedObject());
@ -556,6 +581,11 @@ CVector<CString> ModuleManager::GetInstantiatingSModuleList()
return InstantiatingSModuleList_;
}
void ModuleManager::ClearInstantiatingSModuleList()
{
InstantiatingSModuleList_.clear();
}
JSTaggedValue ModuleManager::GetModuleNamespace(int32_t index)
{
JSTaggedValue currentModule = GetCurrentModule();
@ -793,7 +823,7 @@ JSHandle<JSTaggedValue> ModuleManager::GetModuleNameSpaceFromFile(
JSThread *thread, std::string &recordNameStr, std::string &baseFileName)
{
JSHandle<EcmaString> recordName = thread->GetEcmaVM()->GetFactory()->NewFromASCII(recordNameStr.c_str());
if (!IsImportedModuleLoaded(recordName.GetTaggedValue())) {
if (!IsLocalModuleLoaded(recordName.GetTaggedValue())) {
if (!ecmascript::JSPandaFileExecutor::ExecuteFromAbcFile(
thread, baseFileName.c_str(), recordNameStr.c_str(), false, true)) {
LOG_ECMA(ERROR) << "LoadModuleNameSpaceFromFile:Cannot execute module: %{public}s, recordName: %{public}s",
@ -801,7 +831,7 @@ JSHandle<JSTaggedValue> ModuleManager::GetModuleNameSpaceFromFile(
return thread->GlobalConstants()->GetHandledUndefinedString();
}
}
JSHandle<ecmascript::SourceTextModule> moduleRecord = HostGetImportedModule(recordName.GetTaggedValue());
JSHandle<ecmascript::SourceTextModule> moduleRecord = GetImportedModule(recordName.GetTaggedValue());
moduleRecord->SetLoadingTypes(ecmascript::LoadingTypes::STABLE_MODULE);
return ecmascript::SourceTextModule::GetModuleNamespace(
thread, JSHandle<ecmascript::SourceTextModule>(moduleRecord));

View File

@ -26,7 +26,10 @@ namespace panda::ecmascript {
class ModuleManager {
public:
explicit ModuleManager(EcmaVM *vm);
~ModuleManager() = default;
~ModuleManager()
{
InstantiatingSModuleList_.clear();
}
JSTaggedValue GetModuleValueInner(int32_t index);
JSTaggedValue GetModuleValueInner(int32_t index, JSTaggedValue jsFunc);
@ -52,10 +55,14 @@ public:
JSTaggedValue GetModuleNamespaceInternal(JSTaggedValue localName, JSTaggedValue currentModule);
// deprecated end
JSHandle<SourceTextModule> GetImportedModule(JSTaggedValue referencing);
JSHandle<SourceTextModule> PUBLIC_API HostGetImportedModule(const CString &referencingModule);
JSHandle<SourceTextModule> HostGetImportedModule(JSTaggedValue referencing);
JSTaggedValue HostGetImportedModule(void *src);
bool IsImportedModuleLoaded(JSTaggedValue referencing);
bool IsLocalModuleLoaded(JSTaggedValue referencing);
bool IsSharedModuleLoaded(JSTaggedValue referencing);
bool IsModuleLoaded(JSTaggedValue referencing);
bool IsEvaluatedModule(JSTaggedValue referencing);
JSHandle<JSTaggedValue> ResolveNativeModule(const CString &moduleRequestName, const CString &baseFileName,
@ -136,6 +143,8 @@ private:
CVector<CString> GetInstantiatingSModuleList();
void ClearInstantiatingSModuleList();
void RemoveModuleFromCache(JSTaggedValue recordName);
static constexpr uint32_t DEAULT_DICTIONART_CAPACITY = 4;

View File

@ -17,13 +17,29 @@
#include "ecmascript/global_env.h"
#include "ecmascript/js_array.h"
#include "ecmascript/base/string_helper.h"
#include "ecmascript/object_factory-inl.h"
#include "ecmascript/module/js_module_deregister.h"
#include "ecmascript/module/js_module_record.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/base/string_helper.h"
#include "ecmascript/module/js_shared_module_manager.h"
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/shared_objects/js_shared_array.h"
namespace panda::ecmascript {
JSHandle<JSTaggedValue> ModuleNamespace::CreateSortedExports(JSThread *thread, const JSHandle<TaggedArray> &exports)
{
auto globalConst = thread->GlobalConstants();
// 7. Let sortedExports be a new List containing the same values as the list exports where the values
// are ordered as if an Array of the same values had been sorted using
// Array.prototype.sort using undefined as comparefn.
JSHandle<JSArray> exportsArray = JSArray::CreateArrayFromList(thread, exports);
JSHandle<JSTaggedValue> sortedExports = JSHandle<JSTaggedValue>::Cast(exportsArray);
JSHandle<JSTaggedValue> fn = globalConst->GetHandledUndefined();
JSArray::Sort(thread, sortedExports, fn);
return sortedExports;
}
JSHandle<ModuleNamespace> ModuleNamespace::ModuleNamespaceCreate(JSThread *thread,
const JSHandle<JSTaggedValue> &module,
const JSHandle<TaggedArray> &exports)
@ -31,6 +47,10 @@ JSHandle<ModuleNamespace> ModuleNamespace::ModuleNamespaceCreate(JSThread *threa
auto globalConst = thread->GlobalConstants();
// 1. Assert: module is a Module Record.
ASSERT(module->IsModuleRecord());
if (SourceTextModule::IsSharedModule(JSHandle<SourceTextModule>::Cast(module))) {
return SharedModuleManager::GetInstance()->SModuleNamespaceCreate(thread, module, exports);
}
// 2. Assert: module.[[Namespace]] is undefined.
JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
ASSERT(ModuleRecord::GetNamespace(moduleRecord.GetTaggedValue()).IsUndefined());
@ -41,13 +61,8 @@ JSHandle<ModuleNamespace> ModuleNamespace::ModuleNamespaceCreate(JSThread *threa
JSHandle<ModuleNamespace> mNp = factory->NewModuleNamespace();
// 6. Set M.[[Module]] to module.
mNp->SetModule(thread, module);
// 7. Let sortedExports be a new List containing the same values as the list exports where the values
// are ordered as if an Array of the same values had been sorted using
// Array.prototype.sort using undefined as comparefn.
JSHandle<JSArray> exportsArray = JSArray::CreateArrayFromList(thread, exports);
JSHandle<JSTaggedValue> sortedExports = JSHandle<JSTaggedValue>::Cast(exportsArray);
JSHandle<JSTaggedValue> fn = globalConst->GetHandledUndefined();
JSArray::Sort(thread, sortedExports, fn);
JSHandle<JSTaggedValue> sortedExports = CreateSortedExports(thread, exports);
// 8. Set M.[[Exports]] to sortedExports.
mNp->SetExports(thread, sortedExports);
// 9. Create own properties of M corresponding to the definitions in 26.3.
@ -81,7 +96,10 @@ OperationResult ModuleNamespace::GetProperty(JSThread *thread, const JSHandle<JS
if (exports->IsUndefined()) {
return OperationResult(thread, thread->GlobalConstants()->GetUndefined(), PropertyMetaData(false));
}
if (!JSArray::IncludeInSortedValue(thread, exports, key)) {
if (exports->IsJSArray()) {
if (!JSArray::IncludeInSortedValue(thread, exports, key))
return OperationResult(thread, thread->GlobalConstants()->GetUndefined(), PropertyMetaData(false));
} else if (exports->IsJSSharedArray() && !JSSharedArray::IncludeInSortedValue(thread, exports, key)) {
return OperationResult(thread, thread->GlobalConstants()->GetUndefined(), PropertyMetaData(false));
}
// 5. Let m be O.[[Module]].
@ -91,10 +109,12 @@ OperationResult ModuleNamespace::GetProperty(JSThread *thread, const JSHandle<JS
JSHandle<JSTaggedValue> binding = SourceTextModule::ResolveExport(thread, mm, key, resolveSet);
// 7. Assert: binding is a ResolvedBinding Record.
// Adapter new module
ASSERT(binding->IsResolvedBinding() || binding->IsResolvedIndexBinding());
ASSERT(binding->IsModuleBinding());
JSTaggedValue result;
// 8. Let targetModule be binding.[[Module]].
if (binding->IsResolvedBinding()) {
JSType type = binding->GetTaggedObject()->GetClass()->GetObjectType();
switch (type) {
case JSType::RESOLVEDBINDING_RECORD: {
JSHandle<ResolvedBinding> resolvedBind = JSHandle<ResolvedBinding>::Cast(binding);
JSTaggedValue targetModule = resolvedBind->GetModule();
// 9. Assert: targetModule is not undefined.
@ -106,7 +126,9 @@ OperationResult ModuleNamespace::GetProperty(JSThread *thread, const JSHandle<JS
result = SourceTextModule::Cast(targetModule.GetTaggedObject())->
GetModuleValue(thread, resolvedBind->GetBindingName(), true);
}
} else {
break;
}
case JSType::RESOLVEDINDEXBINDING_RECORD: {
JSHandle<ResolvedIndexBinding> resolvedBind = JSHandle<ResolvedIndexBinding>::Cast(binding);
JSTaggedValue targetModule = resolvedBind->GetModule();
// 9. Assert: targetModule is not undefined.
@ -118,6 +140,16 @@ OperationResult ModuleNamespace::GetProperty(JSThread *thread, const JSHandle<JS
result = SourceTextModule::Cast(targetModule.GetTaggedObject())->
GetModuleValue(thread, resolvedBind->GetIndex(), true);
}
break;
}
case JSType::RESOLVEDRECORDINDEXBINDING_RECORD:
LOG_FULL(INFO) << "RESOLVEDRECORDINDEXBINDING_RECORD";
break;
case JSType::RESOLVEDRECORDBINDING_RECORD:
LOG_FULL(INFO) << "RESOLVEDRECORDINDEXBINDING_RECORD";
break;
default:
LOG_FULL(FATAL) << "UNREACHABLE";
}
return OperationResult(thread, result, PropertyMetaData(true));
}

View File

@ -24,6 +24,8 @@ class ModuleNamespace final : public JSObject {
public:
CAST_CHECK(ModuleNamespace, IsModuleNamespace);
static JSHandle<JSTaggedValue> CreateSortedExports(JSThread *thread, const JSHandle<TaggedArray> &exports);
static void SetModuleDeregisterProcession(JSThread *thread, const JSHandle<ModuleNamespace> &nameSpace,
const NativePointerCallback &callback);

View File

@ -99,7 +99,7 @@ JSHandle<JSTaggedValue> SourceTextModule::HostResolveImportedModuleWithMerge(JST
auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(moduleRequestName);
if (isNative) {
if (moduleManager->IsImportedModuleLoaded(moduleRequestStr.GetTaggedValue())) {
if (moduleManager->IsLocalModuleLoaded(moduleRequestStr.GetTaggedValue())) {
return JSHandle<JSTaggedValue>(moduleManager->HostGetImportedModule(moduleRequestStr.GetTaggedValue()));
}
return moduleManager->ResolveNativeModule(moduleRequestName, baseFilename, moduleType);
@ -134,7 +134,7 @@ JSHandle<JSTaggedValue> SourceTextModule::HostResolveImportedModule(JSThread *th
bool executeFromJob)
{
auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
if (moduleManager->IsImportedModuleLoaded(moduleRequest.GetTaggedValue())) {
if (moduleManager->IsLocalModuleLoaded(moduleRequest.GetTaggedValue())) {
return JSHandle<JSTaggedValue>(moduleManager->HostGetImportedModule(moduleRequest.GetTaggedValue()));
}
@ -517,7 +517,6 @@ int SourceTextModule::Instantiate(JSThread *thread, const JSHandle<JSTaggedValue
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SourceTextModule::Instantiate");
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, SourceTextModule::UNDEFINED_INDEX);
JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleHdl);
ASSERT(!SourceTextModule::IsSharedModule(module));
// 1. Let module be this Source Text Module Record.
// 2. Assert: module.[[Status]] is one of UNLINKED, LINKED, EVALUATING-ASYNC, or EVALUATED.
ModuleStatus status = module->GetStatus();
@ -881,7 +880,7 @@ JSHandle<JSTaggedValue> SourceTextModule::GetModuleNamespace(JSThread *thread,
JSHandle<JSTaggedValue> resolution =
SourceTextModule::ResolveExport(thread, module, nameHandle, resolveVector);
// ii. If resolution is a ResolvedBinding Record, append name to unambiguousNames.
if (resolution->IsResolvedBinding() || resolution->IsResolvedIndexBinding()) {
if (resolution->IsModuleBinding()) {
unambiguousNames->Set(thread, idx, nameHandle);
idx++;
}
@ -948,7 +947,6 @@ JSTaggedValue SourceTextModule::Evaluate(JSThread *thread, const JSHandle<Source
// 1. Let module be this Source Text Module Record.
// 2. Assert: module.[[Status]] is one of LINKED, EVALUATING-ASYNC, or EVALUATED.
JSMutableHandle<SourceTextModule> module(thread, moduleHdl);
ASSERT(!SourceTextModule::IsSharedModule(module));
ModuleStatus status = module->GetStatus();
ASSERT((status == ModuleStatus::INSTANTIATED || status == ModuleStatus::EVALUATING_ASYNC ||
status == ModuleStatus::EVALUATED));
@ -967,7 +965,10 @@ JSTaggedValue SourceTextModule::Evaluate(JSThread *thread, const JSHandle<Source
JSPromise::NewPromiseCapability(thread, JSHandle<JSTaggedValue>::Cast(env->GetPromiseFunction()));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 7. Set module.[[TopLevelCapability]] to capability.
if (!SourceTextModule::IsSharedModule(module)) {
module->SetTopLevelCapability(thread, capability);
}
// 8. Let result be Completion(InnerModuleEvaluation(module, stack, 0)).
int result = SourceTextModule::InnerModuleEvaluation(thread, module, stack, 0, buffer, size, executeFromJob);
HandleEvaluateResult(thread, module, capability, stack, result);
@ -2132,7 +2133,7 @@ void SourceTextModule::CheckCircularImportTool(JSThread *thread, const CString &
auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<EcmaString> moduleRecordNameVal =
thread->GetEcmaVM()->GetFactory()->NewFromUtf8(circularModuleRecordName.c_str());
if (moduleManager->IsImportedModuleLoaded(moduleRecordNameVal.GetTaggedValue())) {
if (moduleManager->IsLocalModuleLoaded(moduleRecordNameVal.GetTaggedValue())) {
moduleRecord.Update(moduleManager->HostGetImportedModule(moduleRecordNameVal.GetTaggedValue()));
} else {
moduleRecord.Update(moduleManager->HostResolveImportedModule(circularModuleRecordName));
@ -2253,7 +2254,7 @@ std::tuple<bool, JSHandle<SourceTextModule>> SourceTextModule::GetResolvedModule
auto moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
auto [isNative, moduleType] = SourceTextModule::CheckNativeModule(moduleRequestName);
if (isNative) {
ASSERT(moduleManager->IsImportedModuleLoaded(moduleRequestStr.GetTaggedValue()));
ASSERT(moduleManager->IsLocalModuleLoaded(moduleRequestStr.GetTaggedValue()));
// native module cached by current context's module manager.
return std::make_tuple(!SourceTextModule::SHARED_MODULE_TAG,
moduleManager->HostGetImportedModule(moduleRequestStr.GetTaggedValue()));

View File

@ -12,9 +12,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/global_env.h"
#include "ecmascript/js_array.h"
#include "ecmascript/module/js_shared_module.h"
#include "ecmascript/module/module_data_extractor.h"
#include "ecmascript/object_factory-inl.h"
#include "ecmascript/shared_objects/js_shared_array.h"
#include "ecmascript/tagged_array-inl.h"
namespace panda::ecmascript {
JSHandle<JSTaggedValue> SendableClassModule::GenerateSendableFuncModule(JSThread *thread,
const JSHandle<JSTaggedValue> &module)
@ -140,4 +145,66 @@ JSHandle<JSTaggedValue> SharedModuleHelper::ParseSharedModule(JSThread *thread,
moduleRecord->SetIsNewBcVersion(true);
return JSHandle<JSTaggedValue>::Cast(moduleRecord);
}
JSHandle<TaggedArray> JSSharedModule::GenerateSharedExports(JSThread *thread, const JSHandle<TaggedArray> &oldExports)
{
uint32_t newLength = oldExports->GetLength();
if (newLength == 0) {
LOG_FULL(INFO) << "Empty exports in moduleNamespace";
}
JSHandle<TaggedArray> newArray = thread->GetEcmaVM()->GetFactory()->NewSTaggedArray(newLength);
for (uint32_t i = 0; i < newLength; i++) {
JSTaggedValue value = oldExports->Get(i);
ASSERT(value.IsString());
newArray->Set(thread, i, value);
}
return newArray;
}
JSHandle<JSTaggedValue> JSSharedModule::CreateSharedSortedExports(JSThread *thread,
const JSHandle<TaggedArray> &oldExports)
{
auto globalConst = thread->GlobalConstants();
JSHandle<TaggedArray> exports = GenerateSharedExports(thread, oldExports);
// 7. Let sortedExports be a new List containing the same values as the list exports where the values
// are ordered as if an Array of the same values had been sorted using
// Array.prototype.sort using undefined as comparefn.
JSHandle<JSSharedArray> exportsArray = JSSharedArray::CreateArrayFromList(thread, exports);
JSHandle<JSTaggedValue> sortedExports = JSHandle<JSTaggedValue>::Cast(exportsArray);
JSHandle<JSTaggedValue> fn = globalConst->GetHandledUndefined();
JSSharedArray::Sort(thread, sortedExports, fn);
return sortedExports;
}
JSHandle<ModuleNamespace> JSSharedModule::SModuleNamespaceCreate(JSThread *thread,
const JSHandle<JSTaggedValue> &module,
const JSHandle<TaggedArray> &exports)
{
auto globalConst = thread->GlobalConstants();
// 2. Assert: module.[[Namespace]] is undefined.
JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
ASSERT(ModuleRecord::GetNamespace(moduleRecord.GetTaggedValue()).IsUndefined());
// 3. Assert: exports is a List of String values.
// 4. Let M be a newly created object.
// 5. Set M's essential internal methods to the definitions specified in 9.4.6.
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<ModuleNamespace> mNp = factory->NewSModuleNamespace();
// 6. Set M.[[Module]] to module.
mNp->SetModule(thread, module);
JSHandle<JSTaggedValue> sortedExports = JSSharedModule::CreateSharedSortedExports(thread, exports);
// 8. Set M.[[Exports]] to sortedExports.
mNp->SetExports(thread, sortedExports);
// 9. Create own properties of M corresponding to the definitions in 26.3.
JSHandle<JSTaggedValue> toStringTag = thread->GetEcmaVM()->GetGlobalEnv()->GetToStringTagSymbol();
JSHandle<JSTaggedValue> moduleString = globalConst->GetHandledModuleString();
PropertyDescriptor des(thread, moduleString, false, false, false);
JSHandle<JSObject> mNpObj = JSHandle<JSObject>::Cast(mNp);
JSObject::DefineOwnProperty(thread, mNpObj, toStringTag, des);
// 10. Set module.[[Namespace]] to M.
ModuleRecord::SetNamespace(thread, moduleRecord.GetTaggedValue(), mNp.GetTaggedValue());
mNp->GetJSHClass()->SetExtensible(false);
return mNp;
}
} // namespace panda::ecmascript

View File

@ -39,6 +39,11 @@ class JSSharedModule {
public:
static JSHandle<TaggedArray> CloneEnvForSModule(JSThread *thread, const JSHandle<SourceTextModule> &module,
JSHandle<TaggedArray> &envRec);
static JSHandle<ModuleNamespace> SModuleNamespaceCreate(JSThread *thread, const JSHandle<JSTaggedValue> &module,
const JSHandle<TaggedArray> &exports);
private:
static JSHandle<JSTaggedValue> CreateSharedSortedExports(JSThread *thread, const JSHandle<TaggedArray> &exports);
static JSHandle<TaggedArray> GenerateSharedExports(JSThread *thread, const JSHandle<TaggedArray> &oldExports);
};
class ResolvedRecordIndexBinding final : public Record {

View File

@ -206,12 +206,26 @@ JSHandle<SourceTextModule> SharedModuleManager::GetSModuleUnsafe(JSThread *threa
return JSHandle<SourceTextModule>(thread, dict->GetValue(entry));
}
JSHandle<SourceTextModule> SharedModuleManager::GetSModuleUnsafe(JSThread *thread, JSTaggedValue recordName)
{
NameDictionary *dict = NameDictionary::Cast(resolvedSharedModules_.GetTaggedObject());
int entry = dict->FindEntry(recordName);
ASSERT(entry != -1);
return JSHandle<SourceTextModule>(thread, dict->GetValue(entry));
}
JSHandle<SourceTextModule> SharedModuleManager::GetSModule(JSThread *thread, const CString &recordName)
{
RuntimeLockHolder locker(thread, mutex_);
return GetSModuleUnsafe(thread, recordName);
}
JSHandle<SourceTextModule> SharedModuleManager::GetSModule(JSThread *thread, JSTaggedValue recordName)
{
RuntimeLockHolder locker(thread, mutex_);
return GetSModuleUnsafe(thread, recordName);
}
bool SharedModuleManager::SearchInSModuleManager(JSThread *thread, const CString &recordName)
{
RuntimeLockHolder locker(thread, mutex_);
@ -246,6 +260,7 @@ void SharedModuleManager::TransferSModule(JSThread *thread)
InsertInSModuleManager(thread, requireModule, module);
moduleManager->RemoveModuleFromCache(requireModule.GetTaggedValue());
}
moduleManager->ClearInstantiatingSModuleList();
}
StateVisit &SharedModuleManager::findModuleMutexWithLock(JSThread *thread, const JSHandle<SourceTextModule> &module)
@ -265,7 +280,6 @@ bool SharedModuleManager::IsInstaniatedSModule(JSThread *thread, const JSHandle<
return (module->GetStatus() >= ModuleStatus::INSTANTIATED);
}
JSHandle<JSTaggedValue> SharedModuleManager::GenerateFuncModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &entryPoint, ClassKind classKind)
{
@ -291,4 +305,11 @@ JSHandle<JSTaggedValue> SharedModuleManager::GenerateFuncModule(JSThread *thread
}
return JSHandle<JSTaggedValue>(vm->GetFactory()->NewFromUtf8(recordName));
}
JSHandle<ModuleNamespace> SharedModuleManager::SModuleNamespaceCreate(JSThread *thread,
const JSHandle<JSTaggedValue> &module, const JSHandle<TaggedArray> &exports)
{
RuntimeLockHolder locker(thread, mutex_);
return JSSharedModule::SModuleNamespaceCreate(thread, module, exports);
}
} // namespace panda::ecmascript

View File

@ -70,6 +70,9 @@ public:
JSHandle<JSTaggedValue> GenerateFuncModule(JSThread *thread, const JSPandaFile *jsPandaFile,
const CString &entryPoint, ClassKind classKind = ClassKind::NON_SENDABLE);
JSHandle<ModuleNamespace> SModuleNamespaceCreate(JSThread *thread, const JSHandle<JSTaggedValue> &module,
const JSHandle<TaggedArray> &exports);
private:
SharedModuleManager() = default;
~SharedModuleManager() = default;
@ -89,8 +92,12 @@ private:
JSHandle<SourceTextModule> GetSModuleUnsafe(JSThread *thread, const CString &recordName);
JSHandle<SourceTextModule> GetSModuleUnsafe(JSThread *thread, JSTaggedValue recordName);
JSHandle<SourceTextModule> GetSModule(JSThread *thread, const CString &recordName);
JSHandle<SourceTextModule> GetSModule(JSThread *thread, JSTaggedValue recordName);
static constexpr uint32_t DEAULT_DICTIONART_CAPACITY = 4;
JSTaggedValue resolvedSharedModules_ {JSTaggedValue::Hole()};
CMap<CString, StateVisit> sharedModuleMutex_;

View File

@ -154,8 +154,7 @@ JSTaggedValue ModuleManagerHelper::GetModuleValueFromIndexBinding(JSThread *thre
// moduleRecord is string, find at current vm
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<SourceTextModule> resolvedModule;
if (moduleManager->IsImportedModuleLoaded(moduleRecord.GetTaggedValue()) &&
moduleManager->IsEvaluatedModule(moduleRecord.GetTaggedValue())) {
if (moduleManager->IsEvaluatedModule(moduleRecord.GetTaggedValue())) {
resolvedModule = moduleManager->HostGetImportedModule(moduleRecord.GetTaggedValue());
} else {
auto isMergedAbc = !module->GetEcmaModuleRecordName().IsUndefined();

View File

@ -83,7 +83,7 @@ JSHandle<JSTaggedValue> NapiModuleLoader::LoadModuleNameSpaceWithPath(JSThread *
THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, ErrorType::REFERENCE_ERROR, JSTaggedValue, msg.c_str());
}
if (!moduleManager->IsImportedModuleLoaded(moduleName.GetTaggedValue())) {
if (!moduleManager->IsLocalModuleLoaded(moduleName.GetTaggedValue())) {
if (!JSPandaFileExecutor::ExecuteFromAbcFile(thread, abcFilePath.c_str(), entryPoint.c_str(), false, true)) {
CString msg = "Cannot execute request from napi load module : " + entryPoint +
", from napi load module";

View File

@ -4503,14 +4503,16 @@ Local<ObjectRef> JSNApi::GetExportObject(EcmaVM *vm, const std::string &file, co
}
}
ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(entry);
ObjectFactory *factory = vm->GetFactory();
JSHandle<EcmaString> referencingHandle = factory->NewFromUtf8(entry);
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->GetImportedModule(
referencingHandle.GetTaggedValue());
if (ecmaModule->GetIsNewBcVersion()) {
int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key);
JSTaggedValue result = ecmaModule->GetModuleValue(thread, index, false);
JSHandle<JSTaggedValue> exportObj(thread, result);
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
ObjectFactory *factory = vm->GetFactory();
JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
@ -4523,8 +4525,11 @@ Local<ObjectRef> JSNApi::GetExportObjectFromBuffer(EcmaVM *vm, const std::string
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, JSValueRef::Undefined(vm));
ecmascript::ThreadManagedScope scope(vm->GetJSThread());
ObjectFactory *factory = vm->GetFactory();
ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->HostGetImportedModule(file.c_str());
JSHandle<EcmaString> referencingHandle = factory->NewFromUtf8(file.c_str());
JSHandle<ecmascript::SourceTextModule> ecmaModule = moduleManager->GetImportedModule(
referencingHandle.GetTaggedValue());
if (ecmaModule->GetIsNewBcVersion()) {
int index = ecmascript::ModuleManager::GetExportObjectIndex(vm, ecmaModule, key);
@ -4533,7 +4538,6 @@ Local<ObjectRef> JSNApi::GetExportObjectFromBuffer(EcmaVM *vm, const std::string
return JSNApiHelper::ToLocal<ObjectRef>(exportObj);
}
ObjectFactory *factory = vm->GetFactory();
JSHandle<EcmaString> keyHandle = factory->NewFromASCII(key.c_str());
JSTaggedValue result = ecmaModule->GetModuleValue(thread, keyHandle.GetTaggedValue(), false);
JSHandle<JSTaggedValue> exportObj(thread, result);

View File

@ -779,6 +779,8 @@ public:
JSHandle<SourceTextModule> NewSSourceTextModule();
JSHandle<ModuleNamespace> NewSModuleNamespace();
JSHandle<ImportEntry> NewSImportEntry(const JSHandle<JSTaggedValue> &moduleRequest,
const JSHandle<JSTaggedValue> &importName,
const JSHandle<JSTaggedValue> &localName);

View File

@ -658,6 +658,20 @@ JSHandle<SourceTextModule> ObjectFactory::NewSSourceTextModule()
return obj;
}
JSHandle<ModuleNamespace> ObjectFactory::NewSModuleNamespace()
{
NewObjectHook();
JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
JSHandle<JSHClass> hclass = JSHandle<JSHClass>::Cast(env->GetSharedModuleNamespaceClass());
JSHandle<JSObject> obj = NewSharedOldSpaceJSObject(hclass);
JSHandle<ModuleNamespace> moduleNamespace = JSHandle<ModuleNamespace>::Cast(obj);
moduleNamespace->SetModule(thread_, JSTaggedValue::Undefined());
moduleNamespace->SetExports(thread_, JSTaggedValue::Undefined());
moduleNamespace->SetDeregisterProcession(thread_, JSTaggedValue::Undefined());
return moduleNamespace;
}
JSHandle<ImportEntry> ObjectFactory::NewSImportEntry(const JSHandle<JSTaggedValue> &moduleRequest,
const JSHandle<JSTaggedValue> &importName,
const JSHandle<JSTaggedValue> &localName)

View File

@ -598,7 +598,7 @@ void JSSharedArray::SortElementsByObject(JSThread *thread, const JSHandle<JSObje
bool JSSharedArray::IncludeInSortedValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &value)
{
ASSERT(obj->IsJSArray());
ASSERT(obj->IsJSSharedArray());
JSHandle<JSSharedArray> arrayObj = JSHandle<JSSharedArray>::Cast(obj);
int32_t length = static_cast<int32_t>(arrayObj->GetArrayLength());
if (length == 0) {

View File

@ -0,0 +1,22 @@
# 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.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_moduletest_action("dynamicimportsharedmodule") {
deps = []
entry_point = "--entry-point=dynamicimportsharedmodule"
is_merge = true
src_postfix = "ts"
is_merge_abc = true
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @tc.name:dynamicimportsharedmodule
* @tc.desc:test dynamicimportsharedmodule
* @tc.type: FUNC
* @tc.require: issue#I9IFCJ
*/
// @ts-nocheck
declare function print(str: any): string;
import {strA, strB} from "./string"
class SendableClassA {
static staticField: string = strA;
constructor() {
"use sendable";
}
testZeroLevelContext() {
print(SendableClassA.staticField);
}
testOneLevelContext() {
let x: number = 0;
(()=>{
print("testOneLevelContext");
print(SendableClassA.staticField + strB);
})();
}
testImportFunction() {
let x: number = 0;
(()=>{
print("testImportFunction");
})();
}
}
let sObj = new SendableClassA;
sObj.testZeroLevelContext();
sObj.testOneLevelContext();
sObj.testImportFunction();
import("./shared").then(m=>{
const instance = m.SingleCase.getInstance();
for(let i = 0; i < 5; i++) {
print(instance.incrementCount());
}}).catch(e=>{print(e);})

View File

@ -0,0 +1,4 @@
dynamicimportsharedmodule.ts;dynamicimportsharedmodule;esm;dynamicimportsharedmodule.ts;xxdynamicimportsharedmodulexx
string.ts;string;esm;string.ts;xxstringxx
func.ts;func;esm;func.ts;xxfuncxx
shared.ts;shared;esm;shared.ts;xxsharedxx;true

View File

@ -0,0 +1,20 @@
# Copyright (c) 2024 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
(This is strA!)
testOneLevelContext
(This is strA!)(This is strB!)
testImportFunction
foo():(This is strA!)
testImportFunction
ClassB:

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @tc.name:dynamicimportsharedmodule
* @tc.desc:test dynamicimportsharedmodule
* @tc.type: FUNC
* @tc.require: issue#I9IFCJ
*/
export class Test1 {
value1:string;
constructor(value1:string) {
"use sendable";
this.value1 = value1;
}
foo(): string {
return "foo():" + this.value1;
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @tc.name:dynamicimportsharedmodule
* @tc.desc:test dynamicimportsharedmodule
* @tc.type: FUNC
* @tc.require: issue#I9IFCJ
*/
declare function print(str: any): string;
"shared module"
export {SingleCase};
import("./func").then(m=>{
let tA = new m.Test1("Test1");
print(tA.foo());
})
class SingleCase {
private static sin : SingleCase;
private count : number = 0;
private constructor() {
"use sendable";
print("SingleCase constructor");
}
public static getInstance(): SingleCase {
if(!SingleCase.sin) {
SingleCase.sin = new SingleCase();
}
return SingleCase.sin;
}
public incrementCount():number {
return this.count++;
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @tc.name:dynamicimportsharedmodule
* @tc.desc:test dynamicimportsharedmodule
* @tc.type: FUNC
* @tc.require: issue#I9IFCJ
*/
export var strA : string = "(This is strA!)";
export var strB : string = "(This is strB!)";