• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "ecmascript/base/json_parser.h"
17 #include "ecmascript/base/json_helper.h"
18 #include "ecmascript/ecma_string.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using namespace panda::ecmascript;
22 using namespace panda::ecmascript::base;
23 
24 namespace panda::test {
25 class AsonParserTest : public BaseTestWithScope<false> {
26 public:
27     using TransformType = base::JsonHelper::TransformType;
28 
CheckSendableConstraint(JSTaggedValue value) const29     bool CheckSendableConstraint(JSTaggedValue value) const
30     {
31         if (!value.IsHeapObject()) {
32             // tagged value always follow sendable constraint.
33             return true;
34         }
35         TaggedObject *obj = value.IsWeak() ? value.GetTaggedWeakRef() : value.GetTaggedObject();
36         auto *jsHClass = obj->GetClass();
37         if (!jsHClass->IsJSShared()) {
38             return false;
39         }
40         if (jsHClass->IsExtensible()) {
41             LOG_ECMA(ERROR) << "sendable check failed. obj is extensible";
42             value.D();
43             return false;
44         }
45         if (!CheckSendableProps(value, obj)) {
46             return false;
47         }
48         // trace proto chain
49         auto proto = jsHClass->GetPrototype();
50         if (!proto.IsNull() && !proto.IsJSShared()) {
51             LOG_ECMA(ERROR) << "sendable check failed. proto is not sendable.";
52             value.D();
53             return false;
54         }
55         return true;
56     }
57 
CheckSendableProps(JSTaggedValue value,TaggedObject * obj) const58     bool CheckSendableProps(JSTaggedValue value, TaggedObject *obj) const
59     {
60         auto *jsHClass = obj->GetClass();
61         auto layoutValue = jsHClass->GetLayout();
62         if (layoutValue.IsNull()) {
63             return true;
64         }
65         auto *layoutInfo = LayoutInfo::Cast(layoutValue.GetTaggedObject());
66         auto *jsObj = JSObject::Cast(obj);
67         auto *propsValue = TaggedArray::Cast(jsObj->GetProperties());
68         if (propsValue->IsDictionaryMode()) {
69             for (int idx = 0; idx < static_cast<int>(jsHClass->NumberOfProps()); idx++) {
70                 auto attr = layoutInfo->GetAttr(idx);
71                 if (attr.IsInlinedProps()) {
72                     // Do not check inline props
73                     continue;
74                 }
75                 if (attr.IsWritable()) {
76                     LOG_ECMA(ERROR) << "sendable check failed. supposed to be un-writable. idx: " << idx;
77                     value.D();
78                     return false;
79                 }
80                 auto val = propsValue->Get(thread, idx - jsHClass->GetInlinedProperties());
81                 if (!CheckSendableConstraint(val)) {
82                     LOG_ECMA(ERROR) << "sendable check failed. supposed to be sendable. idx: " << idx;
83                     value.D();
84                     return false;
85                 }
86             }
87         }
88         return true;
89     }
90 };
91 
HWTEST_F_L0(AsonParserTest,Parser_001)92 HWTEST_F_L0(AsonParserTest, Parser_001)
93 {
94     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
95     Utf8JsonParser parser(thread, TransformType::SENDABLE);
96     // JSON Number
97     JSHandle<JSTaggedValue> handleMsg2(factory->NewFromASCII("1234"));
98     JSHandle<EcmaString> handleStr2(JSTaggedValue::ToString(thread, handleMsg2));
99     JSHandle<JSTaggedValue> result2 = parser.Parse(handleStr2);
100     EXPECT_EQ(result2->GetNumber(), 1234);
101     // JSON Literal
102     JSHandle<JSTaggedValue> handleMsg3(factory->NewFromASCII("true"));
103     JSHandle<EcmaString> handleStr3(JSTaggedValue::ToString(thread, handleMsg3));
104     JSHandle<JSTaggedValue> result3 = parser.Parse(handleStr3);
105     EXPECT_EQ(result3.GetTaggedValue(), JSTaggedValue::True());
106     // JSON LiteraF
107     JSHandle<JSTaggedValue> handleMsg4(factory->NewFromASCII("false"));
108     JSHandle<EcmaString> handleStr4(JSTaggedValue::ToString(thread, handleMsg4));
109     JSHandle<JSTaggedValue> result4 = parser.Parse(handleStr4);
110     EXPECT_EQ(result4.GetTaggedValue(), JSTaggedValue::False());
111     // JSON Unexpected
112     JSHandle<JSTaggedValue> handleMsg5(factory->NewFromASCII("trus"));
113     JSHandle<EcmaString> handleStr5(JSTaggedValue::ToString(thread, handleMsg5));
114     JSHandle<JSTaggedValue> result5 = parser.Parse(handleStr5);
115     EXPECT_EQ(result5.GetTaggedValue(), JSTaggedValue::Exception());
116 }
117 
HWTEST_F_L0(AsonParserTest,Parser_002)118 HWTEST_F_L0(AsonParserTest, Parser_002)
119 {
120     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
121     Utf16JsonParser parser(thread, TransformType::SENDABLE);
122 
123     // JSON Number
124     uint16_t array1Utf16[] = {0x31, 0x32, 0x33, 0x34}; // "1234"
125     uint32_t array1Utf16Len = sizeof(array1Utf16) / sizeof(array1Utf16[0]);
126     JSHandle<JSTaggedValue> handleMsg2(factory->NewFromUtf16(&array1Utf16[0], array1Utf16Len));
127     JSHandle<EcmaString> handleStr2(JSTaggedValue::ToString(thread, handleMsg2));
128     JSHandle<JSTaggedValue> result2 = parser.Parse(*handleStr2);
129     EXPECT_EQ(result2->GetNumber(), 1234);
130     // JSON Literal
131     uint16_t array2Utf16[] = {0x74, 0x72, 0x75, 0x65}; // "true"
132     uint32_t array2Utf16Len = sizeof(array2Utf16) / sizeof(array2Utf16[0]);
133     JSHandle<JSTaggedValue> handleMsg3(factory->NewFromUtf16(&array2Utf16[0], array2Utf16Len));
134     JSHandle<EcmaString> handleStr3(JSTaggedValue::ToString(thread, handleMsg3));
135     JSHandle<JSTaggedValue> result3 = parser.Parse(*handleStr3);
136     EXPECT_EQ(result3.GetTaggedValue(), JSTaggedValue::True());
137     // JSON String
138     uint16_t array3Utf16[] = {0x22, 0x73, 0x74, 0x72, 0x69, 0x6E, 0X67, 0x22}; // "string"
139     uint32_t array3Utf16Len = sizeof(array3Utf16) / sizeof(array3Utf16[0]);
140     JSHandle<JSTaggedValue> handleMsg4(factory->NewFromUtf16(&array3Utf16[0], array3Utf16Len));
141     JSHandle<EcmaString> handleStr4(JSTaggedValue::ToString(thread, handleMsg4));
142     JSHandle<JSTaggedValue> result4 = parser.Parse(*handleStr4);
143     JSHandle<EcmaString> handleEcmaStr(result4);
144     EXPECT_STREQ("string", EcmaStringAccessor(handleEcmaStr).ToCString().c_str());
145 }
146 
HWTEST_F_L0(AsonParserTest,Parser_003)147 HWTEST_F_L0(AsonParserTest, Parser_003)
148 {
149     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
150     Utf8JsonParser parser(thread, TransformType::SENDABLE);
151     JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII(
152         "\t\r \n{\t\r \n \"json\"\t\r\n:\t\r \n{\t\r \n}\t\r \n,\t\r \n \"prop2\"\t\r \n:\t\r \n [\t\r \nfalse\t\r"
153         "\n,\t\r \nnull\t\r, \ntrue\t\r,123.456\t\r \n]\t\r \n}\t\r \n"));
154     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); // JSON Object
155     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
156     result->D();
157     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
158 }
159 
HWTEST_F_L0(AsonParserTest,Parser_004)160 HWTEST_F_L0(AsonParserTest, Parser_004)
161 {
162     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
163     Utf8JsonParser parser(thread, TransformType::SENDABLE);
164     JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("[100,2.5,\"abc\"]"));
165     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); // JSON Array
166     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
167     result->D();
168     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
169 }
170 
HWTEST_F_L0(AsonParserTest,Parser_005)171 HWTEST_F_L0(AsonParserTest, Parser_005)
172 {
173     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
174     Utf8JsonParser parser(thread, TransformType::SENDABLE);
175     JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("{\"epf\":100,\"key1\":400}"));
176     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg));
177     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
178     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
179 }
180 
HWTEST_F_L0(AsonParserTest,Parser_006)181 HWTEST_F_L0(AsonParserTest, Parser_006)
182 {
183     Utf8JsonParser parser(thread, TransformType::SENDABLE);
184     JSHandle<EcmaString> emptyString(thread->GlobalConstants()->GetHandledEmptyString());
185     JSHandle<JSTaggedValue> result = parser.Parse(emptyString);
186     EXPECT_TRUE(result->IsException());
187 }
188 
HWTEST_F_L0(AsonParserTest,Parser_007)189 HWTEST_F_L0(AsonParserTest, Parser_007)
190 {
191     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
192     Utf8JsonParser parser(thread, TransformType::SENDABLE);
193 
194     JSHandle<EcmaString> handleStr(factory->NewFromASCII("\"\""));
195     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
196     EXPECT_FALSE(result->IsException());
197 }
198 
HWTEST_F_L0(AsonParserTest,Parser_008)199 HWTEST_F_L0(AsonParserTest, Parser_008)
200 {
201     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
202     Utf8JsonParser parser(thread, TransformType::SENDABLE);
203     JSHandle<JSTaggedValue> handleMsg(
204         factory->NewFromASCII(R"({"innerEntry": {"x":1, "y":"abc", "str": "innerStr"}, "x": 1, "str": "outerStr"})"));
205     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg));
206     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
207     result->D();
208     EXPECT_FALSE(result->IsException());
209     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
210 }
211 
HWTEST_F_L0(AsonParserTest,Parser_009)212 HWTEST_F_L0(AsonParserTest, Parser_009)
213 {
214     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
215     Utf8JsonParser parser(thread, TransformType::SENDABLE);
216     JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII(R"({})"));
217     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg));
218     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
219     result->D();
220     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
221 }
222 
HWTEST_F_L0(AsonParserTest,Parser_010)223 HWTEST_F_L0(AsonParserTest, Parser_010)
224 {
225     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
226     Utf8JsonParser parser(thread, TransformType::SENDABLE);
227     JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII(R"([])"));
228     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg));
229     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
230     result->D();
231     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
232 }
233 
HWTEST_F_L0(AsonParserTest,Parser_011)234 HWTEST_F_L0(AsonParserTest, Parser_011)
235 {
236     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
237     Utf8JsonParser parser(thread, TransformType::SENDABLE);
238     JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII(R"([1, 2, 3])"));
239     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg));
240     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
241     result->D();
242     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
243 }
244 
HWTEST_F_L0(AsonParserTest,Parser_012)245 HWTEST_F_L0(AsonParserTest, Parser_012)
246 {
247     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
248     Utf8JsonParser parser(thread, TransformType::SENDABLE);
249     JSHandle<JSTaggedValue> handleMsg(
250         factory->NewFromASCII(R"({"innerEntry": {"array": [1, 2, 3]}, "x": 1, "str": "outerStr"})"));
251     JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg));
252     JSHandle<JSTaggedValue> result = parser.Parse(handleStr);
253     result->D();
254     EXPECT_TRUE(CheckSendableConstraint(result.GetTaggedValue()));
255 }
256 
HWTEST_F_L0(AsonParserTest,Parser_013)257 HWTEST_F_L0(AsonParserTest, Parser_013)
258 {
259     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
260     JSMutableHandle<JSFunction> constructor(thread, JSTaggedValue::Undefined());
261     constructor.Update(env->GetSObjectFunction());
262     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
263     JSHandle<JSObject> root = factory->NewJSObjectByConstructor(constructor);
264     JSHandle<JSTaggedValue> rootName(factory->GetEmptyString());
265     JSHandle<JSTaggedValue> result;
266     JSHandle<JSTaggedValue> undefined = JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined());
267     result = Internalize::InternalizeJsonProperty(thread, root, rootName, undefined, TransformType::SENDABLE);
268     ASSERT_TRUE(!result->IsUndefined());
269 }
270 } // namespace panda::test
271