1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "assembler/assembly-emitter.h"
17 #include "assembler/assembly-parser.h"
18 #include "libpandafile/class_data_accessor-inl.h"
19
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/js_function_kind.h"
22 #include "ecmascript/jspandafile/js_pandafile.h"
23 #include "ecmascript/jspandafile/js_pandafile_manager.h"
24 #include "ecmascript/jspandafile/method_literal.h"
25 #include "ecmascript/jspandafile/panda_file_translator.h"
26 #include "ecmascript/jspandafile/program_object.h"
27 #include "ecmascript/tests/test_helper.h"
28
29 using namespace panda::ecmascript;
30 using namespace panda::panda_file;
31 using namespace panda::pandasm;
32
33 namespace panda::test {
34 class PandaFileTranslatorTest : public testing::Test {
35 public:
SetUpTestCase()36 static void SetUpTestCase()
37 {
38 GTEST_LOG_(INFO) << "SetUpTestCase";
39 }
40
TearDownTestCase()41 static void TearDownTestCase()
42 {
43 GTEST_LOG_(INFO) << "TearDownCase";
44 }
45
SetUp()46 void SetUp() override
47 {
48 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
49 }
50
TearDown()51 void TearDown() override
52 {
53 TestHelper::DestroyEcmaVMWithScope(instance, scope);
54 }
55
56 EcmaVM *instance {nullptr};
57 EcmaHandleScope *scope {nullptr};
58 JSThread *thread {nullptr};
59 };
60
HWTEST_F_L0(PandaFileTranslatorTest,GenerateProgram)61 HWTEST_F_L0(PandaFileTranslatorTest, GenerateProgram)
62 {
63 Parser parser;
64 auto vm = thread->GetEcmaVM();
65 const char *filename = "__PandaFileTranslatorTest.pa";
66 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
67 const char *data = R"(
68 .function any func_main_0(any a0, any a1, any a2) {}
69 .function void func() {}
70 )";
71 auto res = parser.Parse(data);
72 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
73 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
74 JSPandaFile *pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(filename));
75 const File *file = pf->GetPandaFile();
76 File::EntityId class_id = file->GetClassId(typeDesc);
77 ClassDataAccessor cda(*file, class_id);
78 std::vector<File::EntityId> methodId {};
79 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
80 methodId.push_back(mda.GetMethodId());
81 });
82 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
83 MethodLiteral method1(pf, methodId[0]);
84 MethodLiteral method2(pf, methodId[1]);
85 pf->SetMethodLiteralToMap(&method1);
86 pf->SetMethodLiteralToMap(&method2);
87 pfManager->InsertJSPandaFile(pf);
88
89 JSHandle<ecmascript::Program> program1 =
90 PandaFileTranslator::GenerateProgram(vm, pf, std::string_view("func"));
91 JSHandle<JSFunction> mainFunc1(thread, program1->GetMainFunction());
92 JSHandle<JSTaggedValue> funcName1 = JSFunction::GetFunctionName(thread, JSHandle<JSFunctionBase>(mainFunc1));
93 EXPECT_STREQ(EcmaStringAccessor(JSHandle<EcmaString>::Cast(funcName1)).ToCString().c_str(), "func");
94
95 pf->UpdateMainMethodIndex(methodId[1].GetOffset());
96 JSHandle<ecmascript::Program> program2 =
97 PandaFileTranslator::GenerateProgram(vm, pf, JSPandaFile::ENTRY_FUNCTION_NAME);
98 JSHandle<JSFunction> mainFunc2(thread, program2->GetMainFunction());
99 JSHandle<JSTaggedValue> funcName2 = JSFunction::GetFunctionName(thread, JSHandle<JSFunctionBase>(mainFunc2));
100 EXPECT_STREQ(EcmaStringAccessor(JSHandle<EcmaString>::Cast(funcName2)).ToCString().c_str(), "func_main_0");
101
102 pfManager->RemoveJSPandaFile((void *)pf);
103 }
104
HWTEST_F_L0(PandaFileTranslatorTest,TranslateClasses)105 HWTEST_F_L0(PandaFileTranslatorTest, TranslateClasses)
106 {
107 Parser parser;
108 const char *filename = "__PandaFileTranslatorTest.pa";
109 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
110 const char *data = R"(
111 .function any func_main_0(any a0, any a1, any a2) {
112 ldai 1
113 return
114 }
115 )";
116 auto res = parser.Parse(data);
117 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
118 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
119 JSPandaFile *pf = pfManager->NewJSPandaFile(pfPtr.release(), CString(filename));
120 const File *file = pf->GetPandaFile();
121 File::EntityId class_id = file->GetClassId(typeDesc);
122 ClassDataAccessor cda(*file, class_id);
123 std::vector<File::EntityId> methodId {};
124 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
125 methodId.push_back(mda.GetMethodId());
126 });
127 pf->UpdateMainMethodIndex(methodId[0].GetOffset());
128 pfManager->InsertJSPandaFile(pf);
129 EXPECT_TRUE(pf->FindMethodLiteral(methodId[0].GetOffset()) == nullptr);
130
131 const char *methodName = MethodLiteral::GetMethodName(pf, methodId[0]);
132 PandaFileTranslator::TranslateClasses(pf, CString(methodName));
133 EXPECT_TRUE(pf->FindMethodLiteral(methodId[0].GetOffset()) != nullptr);
134 EXPECT_EQ(pf->FindMethodLiteral(methodId[0].GetOffset())->GetFunctionKind(),
135 ecmascript::FunctionKind::BASE_CONSTRUCTOR);
136 pfManager->RemoveJSPandaFile((void *)pf);
137 }
138 } // namespace panda::test
139