• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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