1 /*
2 * Copyright (c) 2021 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 "literal_data_extractor.h"
17 #include "ecmascript/base/string_helper.h"
18 #include "ecmascript/ecma_string.h"
19
20 #include "ecmascript/js_thread.h"
21 #include "ecmascript/tagged_array-inl.h"
22 #include "libpandafile/literal_data_accessor-inl.h"
23
24 namespace panda::ecmascript {
25 using LiteralTag = panda_file::LiteralTag;
26 using StringData = panda_file::StringData;
27 using LiteralValue = panda_file::LiteralDataAccessor::LiteralValue;
28
ExtractObjectDatas(JSThread * thread,const panda_file::File * pf,size_t index,JSMutableHandle<TaggedArray> elements,JSMutableHandle<TaggedArray> properties,PandaFileTranslator * pft)29 void LiteralDataExtractor::ExtractObjectDatas(JSThread *thread, const panda_file::File *pf, size_t index,
30 JSMutableHandle<TaggedArray> elements,
31 JSMutableHandle<TaggedArray> properties, PandaFileTranslator *pft)
32 {
33 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
34
35 LOG_ECMA(DEBUG) << "Panda File" << pf->GetFilename();
36 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
37 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
38
39 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
40 elements.Update(factory->NewTaggedArray(num).GetTaggedValue());
41 properties.Update(factory->NewTaggedArray(num).GetTaggedValue());
42 uint32_t epos = 0;
43 uint32_t ppos = 0;
44 const uint8_t pairSize = 2;
45 uint32_t methodId;
46 FunctionKind kind;
47 lda.EnumerateLiteralVals(
48 index, [elements, properties, &epos, &ppos, factory, thread, pft, pf, &methodId, &kind]
49 (const LiteralValue &value, const LiteralTag &tag) {
50 JSTaggedValue jt = JSTaggedValue::Null();
51 bool flag = false;
52 switch (tag) {
53 case LiteralTag::INTEGER: {
54 jt = JSTaggedValue(std::get<uint32_t>(value));
55 break;
56 }
57 case LiteralTag::DOUBLE: {
58 jt = JSTaggedValue(std::get<double>(value));
59 break;
60 }
61 case LiteralTag::BOOL: {
62 jt = JSTaggedValue(std::get<bool>(value));
63 break;
64 }
65 case LiteralTag::STRING: {
66 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
67 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii);
68 jt = JSTaggedValue(str);
69 uint32_t index = 0;
70 if (JSTaggedValue::ToElementIndex(jt, &index) && ppos % pairSize == 0) {
71 flag = true;
72 }
73 break;
74 }
75 case LiteralTag::METHOD: {
76 ASSERT(pft != nullptr);
77 methodId = std::get<uint32_t>(value);
78 kind = FunctionKind::NORMAL_FUNCTION;
79 break;
80 }
81 case LiteralTag::GENERATORMETHOD: {
82 ASSERT(pft != nullptr);
83 methodId = std::get<uint32_t>(value);
84 kind = FunctionKind::GENERATOR_FUNCTION;
85 break;
86 }
87 case LiteralTag::METHODAFFILIATE: {
88 ASSERT(pft != nullptr);
89 uint16_t length = std::get<uint16_t>(value);
90 JSHandle<JSFunction> jsFunc = pft->DefineMethodInLiteral(thread, methodId, kind, length);
91 jt = jsFunc.GetTaggedValue();
92 break;
93 }
94 case LiteralTag::ACCESSOR: {
95 JSHandle<AccessorData> accessor = factory->NewAccessorData();
96 jt = JSTaggedValue(accessor.GetTaggedValue());
97 break;
98 }
99 case LiteralTag::NULLVALUE: {
100 break;
101 }
102 default: {
103 UNREACHABLE();
104 break;
105 }
106 }
107 if (tag != LiteralTag::METHOD && tag != LiteralTag::GENERATORMETHOD) {
108 if (epos % pairSize == 0 && !flag) {
109 properties->Set(thread, ppos++, jt);
110 } else {
111 elements->Set(thread, epos++, jt);
112 }
113 }
114 });
115 }
116
GetDatasIgnoreType(JSThread * thread,const panda_file::File * pf,size_t index,PandaFileTranslator * pft)117 JSHandle<TaggedArray> LiteralDataExtractor::GetDatasIgnoreType(JSThread *thread, const panda_file::File *pf,
118 size_t index, PandaFileTranslator *pft)
119 {
120 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
121
122 LOG_ECMA(DEBUG) << "Panda File" << pf->GetFilename();
123 panda_file::File::EntityId literalArraysId = pf->GetLiteralArraysId();
124 panda_file::LiteralDataAccessor lda(*pf, literalArraysId);
125
126 uint32_t num = lda.GetLiteralValsNum(index) / 2; // 2: half
127 JSHandle<TaggedArray> literals = factory->NewTaggedArray(num);
128 uint32_t pos = 0;
129 uint32_t methodId;
130 FunctionKind kind;
131 lda.EnumerateLiteralVals(
132 index, [literals, &pos, factory, thread, pft, pf, &methodId, &kind]
133 (const panda_file::LiteralDataAccessor::LiteralValue &value, const LiteralTag &tag) {
134 JSTaggedValue jt = JSTaggedValue::Null();
135 switch (tag) {
136 case LiteralTag::INTEGER: {
137 jt = JSTaggedValue(std::get<uint32_t>(value));
138 break;
139 }
140 case LiteralTag::DOUBLE: {
141 jt = JSTaggedValue(std::get<double>(value));
142 break;
143 }
144 case LiteralTag::BOOL: {
145 jt = JSTaggedValue(std::get<bool>(value));
146 break;
147 }
148 case LiteralTag::STRING: {
149 StringData sd = pf->GetStringData(panda_file::File::EntityId(std::get<uint32_t>(value)));
150 EcmaString *str = factory->GetRawStringFromStringTable(sd.data, sd.utf16_length, sd.is_ascii);
151 jt = JSTaggedValue(str);
152 break;
153 }
154 case LiteralTag::METHOD: {
155 ASSERT(pft != nullptr);
156 methodId = std::get<uint32_t>(value);
157 kind = FunctionKind::NORMAL_FUNCTION;
158 break;
159 }
160 case LiteralTag::GENERATORMETHOD: {
161 ASSERT(pft != nullptr);
162 methodId = std::get<uint32_t>(value);
163 kind = FunctionKind::GENERATOR_FUNCTION;
164 break;
165 }
166 case LiteralTag::METHODAFFILIATE: {
167 ASSERT(pft != nullptr);
168 uint16_t length = std::get<uint16_t>(value);
169 JSHandle<JSFunction> jsFunc = pft->DefineMethodInLiteral(thread, methodId, kind, length);
170 jt = jsFunc.GetTaggedValue();
171 break;
172 }
173 case LiteralTag::ACCESSOR: {
174 JSHandle<AccessorData> accessor = factory->NewAccessorData();
175 jt = accessor.GetTaggedValue();
176 break;
177 }
178 case LiteralTag::NULLVALUE: {
179 break;
180 }
181 default: {
182 UNREACHABLE();
183 break;
184 }
185 }
186 if (tag != LiteralTag::METHOD && tag != LiteralTag::GENERATORMETHOD) {
187 literals->Set(thread, pos++, jt);
188 } else {
189 uint32_t oldLength = literals->GetLength();
190 literals->Trim(thread, oldLength - 1);
191 }
192 });
193 return literals;
194 }
195 } // namespace panda::ecmascript
196