mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 04:00:37 +00:00
add module UT
Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IAIHFD Signed-off-by: zhangyouyou <zhangyouyou2@huawei.com>
This commit is contained in:
parent
1062c46eeb
commit
21adf38105
1
BUILD.gn
1
BUILD.gn
@ -867,7 +867,6 @@ ecma_source = [
|
||||
"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",
|
||||
"ecmascript/module/js_module_deregister.cpp",
|
||||
"ecmascript/module/js_shared_module.cpp",
|
||||
|
@ -53,8 +53,6 @@ JSHandle<ModuleNamespace> ModuleNamespace::ModuleNamespaceCreate(JSThread *threa
|
||||
}
|
||||
|
||||
// 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.
|
||||
@ -75,7 +73,9 @@ JSHandle<ModuleNamespace> ModuleNamespace::ModuleNamespaceCreate(JSThread *threa
|
||||
JSObject::DefineOwnProperty(thread, mNpObj, toStringTag, des);
|
||||
// 10. Set module.[[Namespace]] to M.
|
||||
SetModuleDeregisterProcession(thread, mNp, ModuleDeregister::FreeModuleRecord);
|
||||
ModuleRecord::SetNamespace(thread, moduleRecord.GetTaggedValue(), mNp.GetTaggedValue());
|
||||
JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
|
||||
SourceTextModule::Cast(moduleRecord.GetTaggedValue().GetTaggedObject())->SetNamespace(thread,
|
||||
mNp.GetTaggedValue());
|
||||
mNp->GetJSHClass()->SetExtensible(false);
|
||||
return mNp;
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/module/js_module_record.h"
|
||||
#include "ecmascript/module/js_module_source_text.h"
|
||||
#include "ecmascript/object_factory-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
int32_t ModuleRecord::Instantiate(JSThread *thread, const JSHandle<JSTaggedValue> &module)
|
||||
{
|
||||
STACK_LIMIT_CHECK(thread, SourceTextModule::UNDEFINED_INDEX);
|
||||
if (module->IsSourceTextModule()) {
|
||||
return SourceTextModule::Instantiate(thread, module);
|
||||
}
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
JSTaggedValue ModuleRecord::Evaluate(JSThread *thread, const JSHandle<JSTaggedValue> &module)
|
||||
{
|
||||
if (module->IsSourceTextModule()) {
|
||||
JSHandle<SourceTextModule> moduleRecord = JSHandle<SourceTextModule>::Cast(module);
|
||||
return SourceTextModule::Evaluate(thread, moduleRecord);
|
||||
}
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
JSTaggedValue ModuleRecord::GetNamespace(JSTaggedValue module)
|
||||
{
|
||||
if (module.IsSourceTextModule()) {
|
||||
return SourceTextModule::Cast(module.GetTaggedObject())->GetNamespace();
|
||||
}
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void ModuleRecord::SetNamespace(JSThread *thread, JSTaggedValue module, JSTaggedValue value)
|
||||
{
|
||||
if (module.IsSourceTextModule()) {
|
||||
SourceTextModule::Cast(module.GetTaggedObject())->SetNamespace(thread, value);
|
||||
} else {
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -23,14 +23,6 @@ namespace panda::ecmascript {
|
||||
class ModuleRecord : public Record {
|
||||
public:
|
||||
CAST_CHECK(ModuleRecord, IsModuleRecord);
|
||||
|
||||
// 15.2.1.16.4 Instantiate()
|
||||
static int Instantiate(JSThread *thread, const JSHandle<JSTaggedValue> &module);
|
||||
// 15.2.1.16.5 Evaluate()
|
||||
static JSTaggedValue Evaluate(JSThread *thread, const JSHandle<JSTaggedValue> &module);
|
||||
|
||||
static JSTaggedValue GetNamespace(JSTaggedValue module);
|
||||
static void SetNamespace(JSThread *thread, JSTaggedValue module, JSTaggedValue value);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_MODULE_JS_MODULE_RECORD_H
|
||||
|
@ -643,8 +643,9 @@ int SourceTextModule::InnerModuleInstantiation(JSThread *thread, const JSHandle<
|
||||
{
|
||||
// 1. If module is not a Source Text Module Record, then
|
||||
if (!moduleRecord.GetTaggedValue().IsSourceTextModule()) {
|
||||
STACK_LIMIT_CHECK(thread, SourceTextModule::UNDEFINED_INDEX);
|
||||
SourceTextModule::Instantiate(thread, JSHandle<JSTaggedValue>::Cast(moduleRecord));
|
||||
// a. Perform ? module.Instantiate().
|
||||
ModuleRecord::Instantiate(thread, JSHandle<JSTaggedValue>::Cast(moduleRecord));
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
|
||||
// b. Return index.
|
||||
return index;
|
||||
@ -1012,9 +1013,9 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand
|
||||
{
|
||||
STACK_LIMIT_CHECK(thread, index);
|
||||
if (!moduleRecord.GetTaggedValue().IsSourceTextModule()) {
|
||||
JSTaggedValue promise = ModuleRecord::Evaluate(thread, JSHandle<JSTaggedValue>::Cast(moduleRecord));
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, index);
|
||||
PromiseState state = JSPromise::Cast(promise.GetTaggedObject())->GetPromiseState();
|
||||
JSTaggedValue promise = SourceTextModule::Evaluate(thread, JSHandle<SourceTextModule>::Cast(moduleRecord));
|
||||
PromiseState state = JSPromise::Cast(moduleRecord.GetTaggedValue().GetTaggedObject())->GetPromiseState();
|
||||
ASSERT(state != PromiseState::PENDING);
|
||||
if (state == PromiseState::REJECTED) {
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
@ -1025,7 +1026,6 @@ int SourceTextModule::InnerModuleEvaluationUnsafe(JSThread *thread, const JSHand
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
JSHandle<SourceTextModule> module = JSHandle<SourceTextModule>::Cast(moduleRecord);
|
||||
ModuleStatus status = module->GetStatus();
|
||||
if (status == ModuleStatus::EVALUATING_ASYNC || status == ModuleStatus::EVALUATED) {
|
||||
|
@ -186,8 +186,6 @@ JSHandle<ModuleNamespace> JSSharedModule::SModuleNamespaceCreate(JSThread *threa
|
||||
{
|
||||
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.
|
||||
@ -206,8 +204,10 @@ JSHandle<ModuleNamespace> JSSharedModule::SModuleNamespaceCreate(JSThread *threa
|
||||
PropertyDescriptor des(thread, moduleString, false, false, false);
|
||||
JSHandle<JSObject> mNpObj = JSHandle<JSObject>::Cast(mNp);
|
||||
JSObject::DefineOwnProperty(thread, mNpObj, toStringTag, des);
|
||||
JSHandle<ModuleRecord> moduleRecord = JSHandle<ModuleRecord>::Cast(module);
|
||||
SourceTextModule::Cast(moduleRecord.GetTaggedValue().GetTaggedObject())->SetNamespace(thread,
|
||||
mNp.GetTaggedValue());
|
||||
// 10. Set module.[[Namespace]] to M.
|
||||
ModuleRecord::SetNamespace(thread, moduleRecord.GetTaggedValue(), mNp.GetTaggedValue());
|
||||
mNp->GetJSHClass()->SetExtensible(false);
|
||||
return mNp;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
int32_t index);
|
||||
void InsertParentModule(JSHandle<SourceTextModule> currentModule, JSHandle<SourceTextModule> requiredModule);
|
||||
void InsertEntryPointModule(JSHandle<SourceTextModule> currentModule);
|
||||
void PrintModuleLoadInfo();
|
||||
|
||||
private:
|
||||
static constexpr const int MILLISECONDS_PER_SEC = 1000;
|
||||
@ -62,13 +63,12 @@ private:
|
||||
bool CreateResultFile(std::string &path) const; // first time
|
||||
bool OpenResultFile(std::string &path) const;
|
||||
ModuleLoadInfo *GetModuleLoadInfo(const CString &recordName);
|
||||
void PrintModuleLoadInfo();
|
||||
|
||||
void PrintSummary() const;
|
||||
void PrintUsedFileInfo() const;
|
||||
void PrintUnusedFileInfo() const;
|
||||
void ProcessModuleExecuteTime();
|
||||
static std::string ToStringWithPrecision(const double num, const uint8_t n);
|
||||
|
||||
EcmaVM *vm_ {nullptr};
|
||||
CUnorderedMap<CString, ModuleLoadInfo*> jsModuleLoadInfo_ {};
|
||||
uint32_t totalFileNumber_ {0};
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "ecmascript/module/js_module_manager.h"
|
||||
#include "ecmascript/module/js_module_source_text.h"
|
||||
#include "ecmascript/module/module_data_extractor.h"
|
||||
#include "ecmascript/module/module_logger.h"
|
||||
#include "ecmascript/module/module_path_helper.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
#include "ecmascript/linked_hash_table.h"
|
||||
@ -327,24 +328,6 @@ HWTEST_F_L0(EcmaModuleTest, PreventExtensions_IsExtensible)
|
||||
EXPECT_TRUE(ModuleNamespace::PreventExtensions());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(EcmaModuleTest, Instantiate_Evaluate_GetNamespace_SetNamespace)
|
||||
{
|
||||
std::string baseFileName = MODULE_ABC_PATH "module_test_module_test_C.abc";
|
||||
|
||||
JSNApi::EnableUserUncaughtErrorHandler(instance);
|
||||
|
||||
bool result = JSNApi::Execute(instance, baseFileName, "module_test_module_test_C");
|
||||
EXPECT_TRUE(result);
|
||||
ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
|
||||
JSHandle<SourceTextModule> module = moduleManager->HostGetImportedModule("module_test_module_test_C");
|
||||
module->SetStatus(ModuleStatus::UNINSTANTIATED);
|
||||
ModuleRecord::Instantiate(thread, JSHandle<JSTaggedValue>(module));
|
||||
JSTaggedValue res = ModuleRecord::Evaluate(thread, JSHandle<JSTaggedValue>(module));
|
||||
ModuleRecord::GetNamespace(module.GetTaggedValue());
|
||||
ModuleRecord::SetNamespace(thread, module.GetTaggedValue(), JSTaggedValue::Undefined());
|
||||
EXPECT_TRUE(res.IsJSPromise());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(EcmaModuleTest, ConcatFileNameWithMerge1)
|
||||
{
|
||||
CString baseFilename = "merge.abc";
|
||||
@ -907,4 +890,122 @@ HWTEST_F_L0(EcmaModuleTest, NeedTranslateToNormalized)
|
||||
res = ModulePathHelper::NeedTranslateToNormalized(requestName);
|
||||
EXPECT_EQ(res, true);
|
||||
}
|
||||
} // namespace panda::test
|
||||
|
||||
HWTEST_F_L0(EcmaModuleTest, ModuleLogger) {
|
||||
ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<SourceTextModule> module1 = objectFactory->NewSourceTextModule();
|
||||
CString baseFileName = "modules.abc";
|
||||
module1->SetEcmaModuleFilenameString(baseFileName);
|
||||
CString recordName1 = "a";
|
||||
module1->SetEcmaModuleRecordNameString(recordName1);
|
||||
JSHandle<SourceTextModule> module2 = objectFactory->NewSourceTextModule();
|
||||
module2->SetEcmaModuleFilenameString(baseFileName);
|
||||
CString recordName2 = "b";
|
||||
module2->SetEcmaModuleRecordNameString(recordName2);
|
||||
JSHandle<JSTaggedValue> moduleRequest = JSHandle<JSTaggedValue>::Cast(objectFactory->NewFromUtf8("c"));
|
||||
JSHandle<JSTaggedValue> importName = JSHandle<JSTaggedValue>::Cast(objectFactory->NewFromUtf8("ccc"));
|
||||
JSHandle<JSTaggedValue> localName = JSHandle<JSTaggedValue>::Cast(objectFactory->NewFromUtf8("ccc"));
|
||||
JSHandle<ImportEntry> importEntry = objectFactory->NewImportEntry(moduleRequest, importName,
|
||||
localName, SharedTypes::UNSENDABLE_MODULE);
|
||||
SourceTextModule::AddImportEntry(thread, module2, importEntry, 0, 1);
|
||||
JSHandle<SourceTextModule> module3 = objectFactory->NewSourceTextModule();
|
||||
module2->SetEcmaModuleFilenameString(baseFileName);
|
||||
CString recordName3 = "c";
|
||||
module2->SetEcmaModuleRecordNameString(recordName3);
|
||||
ModuleLogger *moduleLogger = new ModuleLogger(thread->GetEcmaVM());
|
||||
moduleLogger->SetStartTime(recordName1);
|
||||
moduleLogger->SetEndTime(recordName1);
|
||||
moduleLogger->SetStartTime(recordName2);
|
||||
moduleLogger->SetEndTime(recordName2);
|
||||
moduleLogger->SetStartTime(recordName3);
|
||||
moduleLogger->InsertEntryPointModule(module1);
|
||||
moduleLogger->InsertParentModule(module1, module2);
|
||||
moduleLogger->InsertModuleLoadInfo(module2, module3, -1);
|
||||
moduleLogger->InsertModuleLoadInfo(module2, module3, 0);
|
||||
moduleLogger->PrintModuleLoadInfo();
|
||||
Local<JSValueRef> nativeFunc = SourceTextModule::GetRequireNativeModuleFunc(thread->GetEcmaVM(),
|
||||
module3->GetTypes());
|
||||
bool isFunc = nativeFunc->IsFunction(thread->GetEcmaVM());
|
||||
EXPECT_EQ(isFunc, false);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(EcmaModuleTest, GetRequireNativeModuleFunc) {
|
||||
ObjectFactory *objectFactory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
|
||||
uint16_t registerNum = module->GetRegisterCounts();
|
||||
module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED);
|
||||
module->SetRegisterCounts(registerNum);
|
||||
Local<JSValueRef> nativeFunc = SourceTextModule::GetRequireNativeModuleFunc(thread->GetEcmaVM(),
|
||||
module->GetTypes());
|
||||
bool isFunc = nativeFunc->IsFunction(thread->GetEcmaVM());
|
||||
EXPECT_EQ(isFunc, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Feature: Module
|
||||
* Function: StoreModuleValue
|
||||
* SubFunction: StoreModuleValue/GetModuleValue
|
||||
* FunctionPoints: store a module export item in module
|
||||
* CaseDescription: Simulated implementation of "export foo as bar", set foo as "hello world",
|
||||
* use "import bar" in same js file
|
||||
*/
|
||||
HWTEST_F_L0(EcmaModuleTest, StoreModuleValue2)
|
||||
{
|
||||
ObjectFactory* objFactory = thread->GetEcmaVM()->GetFactory();
|
||||
CString localName = "foo";
|
||||
CString exportName = "bar";
|
||||
CString value = "hello world";
|
||||
CString value2 = "hello world1";
|
||||
int32_t index = 1;
|
||||
|
||||
JSHandle<JSTaggedValue> localNameHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(localName));
|
||||
JSHandle<JSTaggedValue> exportNameHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(exportName));
|
||||
JSHandle<LocalExportEntry> localExportEntry =
|
||||
objFactory->NewLocalExportEntry(exportNameHandle, localNameHandle, LocalExportEntry::LOCAL_DEFAULT_INDEX,
|
||||
SharedTypes::UNSENDABLE_MODULE);
|
||||
JSHandle<SourceTextModule> module = objFactory->NewSourceTextModule();
|
||||
SourceTextModule::AddLocalExportEntry(thread, module, localExportEntry, 0, 1);
|
||||
|
||||
JSHandle<JSTaggedValue> storeKey = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(localName));
|
||||
JSHandle<JSTaggedValue> valueHandle = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(value));
|
||||
JSHandle<JSTaggedValue> valueHandle1 = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(value2));
|
||||
module->StoreModuleValue(thread, storeKey, valueHandle);
|
||||
module->StoreModuleValue(thread, index, valueHandle1);
|
||||
JSHandle<JSTaggedValue> loadKey = JSHandle<JSTaggedValue>::Cast(objFactory->NewFromUtf8(localName));
|
||||
JSTaggedValue loadValue = module->GetModuleValue(thread, loadKey.GetTaggedValue(), false);
|
||||
JSTaggedValue loadValue1 = module->GetModuleValue(thread, index, false);
|
||||
EXPECT_EQ(valueHandle.GetTaggedValue(), loadValue);
|
||||
EXPECT_EQ(valueHandle1.GetTaggedValue(), loadValue1);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(EcmaModuleTest, MakeAppArgs1) {
|
||||
std::vector<Local<JSValueRef>> arguments;
|
||||
CString soPath = "@normalized:Y&&&libentry.so&";
|
||||
CString moduleName = "entry";
|
||||
CString requestName = "@normalized:";
|
||||
arguments.emplace_back(StringRef::NewFromUtf8(thread->GetEcmaVM(), soPath.c_str()));
|
||||
SourceTextModule::MakeAppArgs(thread->GetEcmaVM(), arguments, soPath, moduleName, requestName);
|
||||
std::string res1 = arguments[0]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM());
|
||||
std::string res2 = arguments[1]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM());
|
||||
std::string res3 = arguments[2]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM());
|
||||
EXPECT_TRUE(res1 == "entry");
|
||||
EXPECT_TRUE(res2 == "true");
|
||||
EXPECT_TRUE(res3 == "/entry");
|
||||
}
|
||||
|
||||
HWTEST_F_L0(EcmaModuleTest, MakeAppArgs2) {
|
||||
std::vector<Local<JSValueRef>> arguments;
|
||||
CString soPath = "@app:com.example.myapplication/entry";
|
||||
CString moduleName = "entry";
|
||||
CString requestName = "@app:";
|
||||
arguments.emplace_back(StringRef::NewFromUtf8(thread->GetEcmaVM(), soPath.c_str()));
|
||||
SourceTextModule::MakeAppArgs(thread->GetEcmaVM(), arguments, soPath, moduleName, requestName);
|
||||
std::string res1 = arguments[0]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM());
|
||||
std::string res2 = arguments[1]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM());
|
||||
std::string res3 = arguments[2]->ToString(thread->GetEcmaVM())->ToString(thread->GetEcmaVM());
|
||||
EXPECT_TRUE(res1 == "entry");
|
||||
EXPECT_TRUE(res2 == "true");
|
||||
EXPECT_TRUE(res3 == "@app:com.example.myapplication");
|
||||
}
|
||||
|
||||
} // namespace panda::test
|
@ -60,10 +60,17 @@ import('./1.json').then(m => {
|
||||
print(m.default.name);
|
||||
}).then().catch();
|
||||
|
||||
import('@native:system.app').then(m => {
|
||||
print("native module");
|
||||
}).then().catch();
|
||||
|
||||
import('@native:system.app').then(m => {
|
||||
print("native module");
|
||||
}).then().catch();
|
||||
// Dynamic Loading Reload Test
|
||||
import('./aaa.js').then(m => {
|
||||
print("dynamic import aaa.js 1st time");
|
||||
})
|
||||
import('./aaa.js').then(m => {
|
||||
print("dynamic import aaa.js 2nd time");
|
||||
})
|
||||
})
|
||||
|
@ -20,5 +20,7 @@ undefined
|
||||
{}
|
||||
TypeError
|
||||
dynamicImport Json
|
||||
native module
|
||||
native module
|
||||
dynamic import aaa.js 1st time
|
||||
dynamic import aaa.js 2nd time
|
||||
|
Loading…
Reference in New Issue
Block a user