OLD | NEW |
| (Empty) |
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "platform/JSONParser.h" | |
6 | |
7 #include "platform/JSONValues.h" | |
8 #include "testing/gtest/include/gtest/gtest.h" | |
9 #include "wtf/text/StringBuilder.h" | |
10 | |
11 namespace blink { | |
12 | |
13 TEST(JSONParserTest, Reading) | |
14 { | |
15 JSONValue* tmpValue; | |
16 std::unique_ptr<JSONValue> root; | |
17 std::unique_ptr<JSONValue> root2; | |
18 String strVal; | |
19 int intVal = 0; | |
20 | |
21 // some whitespace checking | |
22 root = parseJSON(" null "); | |
23 ASSERT_TRUE(root.get()); | |
24 EXPECT_EQ(JSONValue::TypeNull, root->getType()); | |
25 | |
26 // Invalid JSON string | |
27 root = parseJSON("nu"); | |
28 EXPECT_FALSE(root.get()); | |
29 | |
30 // Simple bool | |
31 root = parseJSON("true "); | |
32 ASSERT_TRUE(root.get()); | |
33 EXPECT_EQ(JSONValue::TypeBoolean, root->getType()); | |
34 | |
35 // Embedded comment | |
36 root = parseJSON("40 /*/"); | |
37 EXPECT_FALSE(root.get()); | |
38 root = parseJSON("/* comment */null"); | |
39 ASSERT_TRUE(root.get()); | |
40 EXPECT_EQ(JSONValue::TypeNull, root->getType()); | |
41 root = parseJSON("40 /* comment */"); | |
42 ASSERT_TRUE(root.get()); | |
43 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
44 EXPECT_TRUE(root->asInteger(&intVal)); | |
45 EXPECT_EQ(40, intVal); | |
46 root = parseJSON("/**/ 40 /* multi-line\n comment */ // more comment"); | |
47 ASSERT_TRUE(root.get()); | |
48 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
49 EXPECT_TRUE(root->asInteger(&intVal)); | |
50 EXPECT_EQ(40, intVal); | |
51 root = parseJSON("true // comment"); | |
52 ASSERT_TRUE(root.get()); | |
53 EXPECT_EQ(JSONValue::TypeBoolean, root->getType()); | |
54 root = parseJSON("/* comment */\"sample string\""); | |
55 ASSERT_TRUE(root.get()); | |
56 EXPECT_TRUE(root->asString(&strVal)); | |
57 EXPECT_EQ("sample string", strVal); | |
58 root = parseJSON("[1, /* comment, 2 ] */ \n 3]"); | |
59 ASSERT_TRUE(root.get()); | |
60 JSONArray* list = JSONArray::cast(root.get()); | |
61 ASSERT_TRUE(list); | |
62 EXPECT_EQ(2u, list->size()); | |
63 tmpValue = list->at(0); | |
64 ASSERT_TRUE(tmpValue); | |
65 EXPECT_TRUE(tmpValue->asInteger(&intVal)); | |
66 EXPECT_EQ(1, intVal); | |
67 tmpValue = list->at(1); | |
68 ASSERT_TRUE(tmpValue); | |
69 EXPECT_TRUE(tmpValue->asInteger(&intVal)); | |
70 EXPECT_EQ(3, intVal); | |
71 root = parseJSON("[1, /*a*/2, 3]"); | |
72 ASSERT_TRUE(root.get()); | |
73 list = JSONArray::cast(root.get()); | |
74 ASSERT_TRUE(list); | |
75 EXPECT_EQ(3u, list->size()); | |
76 root = parseJSON("/* comment **/42"); | |
77 ASSERT_TRUE(root.get()); | |
78 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
79 EXPECT_TRUE(root->asInteger(&intVal)); | |
80 EXPECT_EQ(42, intVal); | |
81 root = parseJSON( | |
82 "/* comment **/\n" | |
83 "// */ 43\n" | |
84 "44"); | |
85 ASSERT_TRUE(root.get()); | |
86 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
87 EXPECT_TRUE(root->asInteger(&intVal)); | |
88 EXPECT_EQ(44, intVal); | |
89 | |
90 // Test number formats | |
91 root = parseJSON("43"); | |
92 ASSERT_TRUE(root.get()); | |
93 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
94 EXPECT_TRUE(root->asInteger(&intVal)); | |
95 EXPECT_EQ(43, intVal); | |
96 | |
97 // According to RFC4627, oct, hex, and leading zeros are invalid JSON. | |
98 root = parseJSON("043"); | |
99 EXPECT_FALSE(root.get()); | |
100 root = parseJSON("0x43"); | |
101 EXPECT_FALSE(root.get()); | |
102 root = parseJSON("00"); | |
103 EXPECT_FALSE(root.get()); | |
104 | |
105 // Test 0 (which needs to be special cased because of the leading zero | |
106 // clause). | |
107 root = parseJSON("0"); | |
108 ASSERT_TRUE(root.get()); | |
109 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
110 intVal = 1; | |
111 EXPECT_TRUE(root->asInteger(&intVal)); | |
112 EXPECT_EQ(0, intVal); | |
113 | |
114 // Numbers that overflow ints should succeed, being internally promoted to | |
115 // storage as doubles | |
116 root = parseJSON("2147483648"); | |
117 ASSERT_TRUE(root.get()); | |
118 double doubleVal; | |
119 EXPECT_EQ(JSONValue::TypeDouble, root->getType()); | |
120 doubleVal = 0.0; | |
121 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
122 EXPECT_DOUBLE_EQ(2147483648.0, doubleVal); | |
123 root = parseJSON("-2147483649"); | |
124 ASSERT_TRUE(root.get()); | |
125 EXPECT_EQ(JSONValue::TypeDouble, root->getType()); | |
126 doubleVal = 0.0; | |
127 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
128 EXPECT_DOUBLE_EQ(-2147483649.0, doubleVal); | |
129 | |
130 // Parse a double | |
131 root = parseJSON("43.1"); | |
132 ASSERT_TRUE(root.get()); | |
133 EXPECT_EQ(JSONValue::TypeDouble, root->getType()); | |
134 doubleVal = 0.0; | |
135 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
136 EXPECT_DOUBLE_EQ(43.1, doubleVal); | |
137 | |
138 root = parseJSON("4.3e-1"); | |
139 ASSERT_TRUE(root.get()); | |
140 EXPECT_EQ(JSONValue::TypeDouble, root->getType()); | |
141 doubleVal = 0.0; | |
142 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
143 EXPECT_DOUBLE_EQ(.43, doubleVal); | |
144 | |
145 root = parseJSON("2.1e0"); | |
146 ASSERT_TRUE(root.get()); | |
147 EXPECT_EQ(JSONValue::TypeDouble, root->getType()); | |
148 doubleVal = 0.0; | |
149 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
150 EXPECT_DOUBLE_EQ(2.1, doubleVal); | |
151 | |
152 root = parseJSON("2.1e+0001"); | |
153 ASSERT_TRUE(root.get()); | |
154 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
155 doubleVal = 0.0; | |
156 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
157 EXPECT_DOUBLE_EQ(21.0, doubleVal); | |
158 | |
159 root = parseJSON("0.01"); | |
160 ASSERT_TRUE(root.get()); | |
161 EXPECT_EQ(JSONValue::TypeDouble, root->getType()); | |
162 doubleVal = 0.0; | |
163 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
164 EXPECT_DOUBLE_EQ(0.01, doubleVal); | |
165 | |
166 root = parseJSON("1.00"); | |
167 ASSERT_TRUE(root.get()); | |
168 EXPECT_EQ(JSONValue::TypeInteger, root->getType()); | |
169 doubleVal = 0.0; | |
170 EXPECT_TRUE(root->asDouble(&doubleVal)); | |
171 EXPECT_DOUBLE_EQ(1.0, doubleVal); | |
172 | |
173 // Fractional parts must have a digit before and after the decimal point. | |
174 root = parseJSON("1."); | |
175 EXPECT_FALSE(root.get()); | |
176 root = parseJSON(".1"); | |
177 EXPECT_FALSE(root.get()); | |
178 root = parseJSON("1.e10"); | |
179 EXPECT_FALSE(root.get()); | |
180 | |
181 // Exponent must have a digit following the 'e'. | |
182 root = parseJSON("1e"); | |
183 EXPECT_FALSE(root.get()); | |
184 root = parseJSON("1E"); | |
185 EXPECT_FALSE(root.get()); | |
186 root = parseJSON("1e1."); | |
187 EXPECT_FALSE(root.get()); | |
188 root = parseJSON("1e1.0"); | |
189 EXPECT_FALSE(root.get()); | |
190 | |
191 // INF/-INF/NaN are not valid | |
192 root = parseJSON("NaN"); | |
193 EXPECT_FALSE(root.get()); | |
194 root = parseJSON("nan"); | |
195 EXPECT_FALSE(root.get()); | |
196 root = parseJSON("inf"); | |
197 EXPECT_FALSE(root.get()); | |
198 | |
199 // Invalid number formats | |
200 root = parseJSON("4.3.1"); | |
201 EXPECT_FALSE(root.get()); | |
202 root = parseJSON("4e3.1"); | |
203 EXPECT_FALSE(root.get()); | |
204 | |
205 // Test string parser | |
206 root = parseJSON("\"hello world\""); | |
207 ASSERT_TRUE(root.get()); | |
208 EXPECT_EQ(JSONValue::TypeString, root->getType()); | |
209 EXPECT_TRUE(root->asString(&strVal)); | |
210 EXPECT_EQ("hello world", strVal); | |
211 | |
212 // Empty string | |
213 root = parseJSON("\"\""); | |
214 ASSERT_TRUE(root.get()); | |
215 EXPECT_EQ(JSONValue::TypeString, root->getType()); | |
216 EXPECT_TRUE(root->asString(&strVal)); | |
217 EXPECT_EQ("", strVal); | |
218 | |
219 // Test basic string escapes | |
220 root = parseJSON("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\""); | |
221 ASSERT_TRUE(root.get()); | |
222 EXPECT_EQ(JSONValue::TypeString, root->getType()); | |
223 EXPECT_TRUE(root->asString(&strVal)); | |
224 EXPECT_EQ(" \"\\/\b\f\n\r\t\v", strVal); | |
225 | |
226 // Test hex and unicode escapes including the null character. | |
227 root = parseJSON("\"\\x41\\x00\\u1234\""); | |
228 EXPECT_FALSE(root.get()); | |
229 | |
230 // Test invalid strings | |
231 root = parseJSON("\"no closing quote"); | |
232 EXPECT_FALSE(root.get()); | |
233 root = parseJSON("\"\\z invalid escape char\""); | |
234 EXPECT_FALSE(root.get()); | |
235 root = parseJSON("\"not enough escape chars\\u123\""); | |
236 EXPECT_FALSE(root.get()); | |
237 root = parseJSON("\"extra backslash at end of input\\\""); | |
238 EXPECT_FALSE(root.get()); | |
239 | |
240 // Basic array | |
241 root = parseJSON("[true, false, null]"); | |
242 ASSERT_TRUE(root.get()); | |
243 EXPECT_EQ(JSONValue::TypeArray, root->getType()); | |
244 list = JSONArray::cast(root.get()); | |
245 ASSERT_TRUE(list); | |
246 EXPECT_EQ(3U, list->size()); | |
247 | |
248 // Empty array | |
249 root = parseJSON("[]"); | |
250 ASSERT_TRUE(root.get()); | |
251 EXPECT_EQ(JSONValue::TypeArray, root->getType()); | |
252 list = JSONArray::cast(root.get()); | |
253 ASSERT_TRUE(list); | |
254 EXPECT_EQ(0U, list->size()); | |
255 | |
256 // Nested arrays | |
257 root = parseJSON("[[true], [], [false, [], [null]], null]"); | |
258 ASSERT_TRUE(root.get()); | |
259 EXPECT_EQ(JSONValue::TypeArray, root->getType()); | |
260 list = JSONArray::cast(root.get()); | |
261 ASSERT_TRUE(list); | |
262 EXPECT_EQ(4U, list->size()); | |
263 | |
264 // Invalid, missing close brace. | |
265 root = parseJSON("[[true], [], [false, [], [null]], null"); | |
266 EXPECT_FALSE(root.get()); | |
267 | |
268 // Invalid, too many commas | |
269 root = parseJSON("[true,, null]"); | |
270 EXPECT_FALSE(root.get()); | |
271 | |
272 // Invalid, no commas | |
273 root = parseJSON("[true null]"); | |
274 EXPECT_FALSE(root.get()); | |
275 | |
276 // Invalid, trailing comma | |
277 root = parseJSON("[true,]"); | |
278 EXPECT_FALSE(root.get()); | |
279 | |
280 root = parseJSON("[true]"); | |
281 ASSERT_TRUE(root.get()); | |
282 EXPECT_EQ(JSONValue::TypeArray, root->getType()); | |
283 list = JSONArray::cast(root.get()); | |
284 ASSERT_TRUE(list); | |
285 EXPECT_EQ(1U, list->size()); | |
286 tmpValue = list->at(0); | |
287 ASSERT_TRUE(tmpValue); | |
288 EXPECT_EQ(JSONValue::TypeBoolean, tmpValue->getType()); | |
289 bool boolValue = false; | |
290 EXPECT_TRUE(tmpValue->asBoolean(&boolValue)); | |
291 EXPECT_TRUE(boolValue); | |
292 | |
293 // Don't allow empty elements. | |
294 root = parseJSON("[,]"); | |
295 EXPECT_FALSE(root.get()); | |
296 root = parseJSON("[true,,]"); | |
297 EXPECT_FALSE(root.get()); | |
298 root = parseJSON("[,true,]"); | |
299 EXPECT_FALSE(root.get()); | |
300 root = parseJSON("[true,,false]"); | |
301 EXPECT_FALSE(root.get()); | |
302 | |
303 // Test objects | |
304 root = parseJSON("{}"); | |
305 ASSERT_TRUE(root.get()); | |
306 EXPECT_EQ(JSONValue::TypeObject, root->getType()); | |
307 | |
308 root = parseJSON("{\"number\":9.87654321, \"null\":null , \"S\" : \"str\" }"
); | |
309 ASSERT_TRUE(root.get()); | |
310 EXPECT_EQ(JSONValue::TypeObject, root->getType()); | |
311 JSONObject* objectVal = JSONObject::cast(root.get()); | |
312 ASSERT_TRUE(objectVal); | |
313 doubleVal = 0.0; | |
314 EXPECT_TRUE(objectVal->getDouble("number", &doubleVal)); | |
315 EXPECT_DOUBLE_EQ(9.87654321, doubleVal); | |
316 JSONValue* nullVal = objectVal->get("null"); | |
317 ASSERT_TRUE(nullVal); | |
318 EXPECT_EQ(JSONValue::TypeNull, nullVal->getType()); | |
319 EXPECT_TRUE(objectVal->getString("S", &strVal)); | |
320 EXPECT_EQ("str", strVal); | |
321 | |
322 // Test newline equivalence. | |
323 root2 = parseJSON( | |
324 "{\n" | |
325 " \"number\":9.87654321,\n" | |
326 " \"null\":null,\n" | |
327 " \"S\":\"str\"\n" | |
328 "}\n"); | |
329 ASSERT_TRUE(root2.get()); | |
330 EXPECT_EQ(root->toJSONString(), root2->toJSONString()); | |
331 | |
332 root2 = parseJSON( | |
333 "{\r\n" | |
334 " \"number\":9.87654321,\r\n" | |
335 " \"null\":null,\r\n" | |
336 " \"S\":\"str\"\r\n" | |
337 "}\r\n"); | |
338 ASSERT_TRUE(root2.get()); | |
339 EXPECT_EQ(root->toJSONString(), root2->toJSONString()); | |
340 | |
341 // Test nesting | |
342 root = parseJSON("{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}"); | |
343 ASSERT_TRUE(root.get()); | |
344 EXPECT_EQ(JSONValue::TypeObject, root->getType()); | |
345 objectVal = JSONObject::cast(root.get()); | |
346 ASSERT_TRUE(objectVal); | |
347 JSONObject* innerObject = objectVal->getObject("inner"); | |
348 ASSERT_TRUE(innerObject); | |
349 JSONArray* innerArray = innerObject->getArray("array"); | |
350 ASSERT_TRUE(innerArray); | |
351 EXPECT_EQ(1U, innerArray->size()); | |
352 boolValue = true; | |
353 EXPECT_TRUE(objectVal->getBoolean("false", &boolValue)); | |
354 EXPECT_FALSE(boolValue); | |
355 innerObject = objectVal->getObject("d"); | |
356 EXPECT_TRUE(innerObject); | |
357 | |
358 // Test keys with periods | |
359 root = parseJSON("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}"); | |
360 ASSERT_TRUE(root.get()); | |
361 EXPECT_EQ(JSONValue::TypeObject, root->getType()); | |
362 objectVal = JSONObject::cast(root.get()); | |
363 ASSERT_TRUE(objectVal); | |
364 int integerValue = 0; | |
365 EXPECT_TRUE(objectVal->getInteger("a.b", &integerValue)); | |
366 EXPECT_EQ(3, integerValue); | |
367 EXPECT_TRUE(objectVal->getInteger("c", &integerValue)); | |
368 EXPECT_EQ(2, integerValue); | |
369 innerObject = objectVal->getObject("d.e.f"); | |
370 ASSERT_TRUE(innerObject); | |
371 EXPECT_EQ(1U, innerObject->size()); | |
372 EXPECT_TRUE(innerObject->getInteger("g.h.i.j", &integerValue)); | |
373 EXPECT_EQ(1, integerValue); | |
374 | |
375 root = parseJSON("{\"a\":{\"b\":2},\"a.b\":1}"); | |
376 ASSERT_TRUE(root.get()); | |
377 EXPECT_EQ(JSONValue::TypeObject, root->getType()); | |
378 objectVal = JSONObject::cast(root.get()); | |
379 ASSERT_TRUE(objectVal); | |
380 innerObject = objectVal->getObject("a"); | |
381 ASSERT_TRUE(innerObject); | |
382 EXPECT_TRUE(innerObject->getInteger("b", &integerValue)); | |
383 EXPECT_EQ(2, integerValue); | |
384 EXPECT_TRUE(objectVal->getInteger("a.b", &integerValue)); | |
385 EXPECT_EQ(1, integerValue); | |
386 | |
387 // Invalid, no closing brace | |
388 root = parseJSON("{\"a\": true"); | |
389 EXPECT_FALSE(root.get()); | |
390 | |
391 // Invalid, keys must be quoted | |
392 root = parseJSON("{foo:true}"); | |
393 EXPECT_FALSE(root.get()); | |
394 | |
395 // Invalid, trailing comma | |
396 root = parseJSON("{\"a\":true,}"); | |
397 EXPECT_FALSE(root.get()); | |
398 | |
399 // Invalid, too many commas | |
400 root = parseJSON("{\"a\":true,,\"b\":false}"); | |
401 EXPECT_FALSE(root.get()); | |
402 | |
403 // Invalid, no separator | |
404 root = parseJSON("{\"a\" \"b\"}"); | |
405 EXPECT_FALSE(root.get()); | |
406 | |
407 // Invalid, lone comma. | |
408 root = parseJSON("{,}"); | |
409 EXPECT_FALSE(root.get()); | |
410 root = parseJSON("{\"a\":true,,}"); | |
411 EXPECT_FALSE(root.get()); | |
412 root = parseJSON("{,\"a\":true}"); | |
413 EXPECT_FALSE(root.get()); | |
414 root = parseJSON("{\"a\":true,,\"b\":false}"); | |
415 EXPECT_FALSE(root.get()); | |
416 | |
417 // Test stack overflow | |
418 StringBuilder evil; | |
419 evil.reserveCapacity(2000000); | |
420 for (int i = 0; i < 1000000; ++i) | |
421 evil.append('['); | |
422 for (int i = 0; i < 1000000; ++i) | |
423 evil.append(']'); | |
424 root = parseJSON(evil.toString()); | |
425 EXPECT_FALSE(root.get()); | |
426 | |
427 // A few thousand adjacent lists is fine. | |
428 StringBuilder notEvil; | |
429 notEvil.reserveCapacity(15010); | |
430 notEvil.append('['); | |
431 for (int i = 0; i < 5000; ++i) | |
432 notEvil.append("[],"); | |
433 notEvil.append("[]]"); | |
434 root = parseJSON(notEvil.toString()); | |
435 ASSERT_TRUE(root.get()); | |
436 EXPECT_EQ(JSONValue::TypeArray, root->getType()); | |
437 list = JSONArray::cast(root.get()); | |
438 ASSERT_TRUE(list); | |
439 EXPECT_EQ(5001U, list->size()); | |
440 | |
441 // Test utf8 encoded input | |
442 root = parseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\""); | |
443 ASSERT_FALSE(root.get()); | |
444 | |
445 // Test utf16 encoded strings. | |
446 root = parseJSON("\"\\u20ac3,14\""); | |
447 ASSERT_TRUE(root.get()); | |
448 EXPECT_EQ(JSONValue::TypeString, root->getType()); | |
449 EXPECT_TRUE(root->asString(&strVal)); | |
450 UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34}; | |
451 EXPECT_EQ(String(tmp2, WTF_ARRAY_LENGTH(tmp2)), strVal); | |
452 | |
453 root = parseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\""); | |
454 ASSERT_TRUE(root.get()); | |
455 EXPECT_EQ(JSONValue::TypeString, root->getType()); | |
456 EXPECT_TRUE(root->asString(&strVal)); | |
457 UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c}; | |
458 EXPECT_EQ(String(tmp3, WTF_ARRAY_LENGTH(tmp3)), strVal); | |
459 | |
460 // Test literal root objects. | |
461 root = parseJSON("null"); | |
462 EXPECT_EQ(JSONValue::TypeNull, root->getType()); | |
463 | |
464 root = parseJSON("true"); | |
465 ASSERT_TRUE(root.get()); | |
466 EXPECT_TRUE(root->asBoolean(&boolValue)); | |
467 EXPECT_TRUE(boolValue); | |
468 | |
469 root = parseJSON("10"); | |
470 ASSERT_TRUE(root.get()); | |
471 EXPECT_TRUE(root->asInteger(&integerValue)); | |
472 EXPECT_EQ(10, integerValue); | |
473 | |
474 root = parseJSON("\"root\""); | |
475 ASSERT_TRUE(root.get()); | |
476 EXPECT_TRUE(root->asString(&strVal)); | |
477 EXPECT_EQ("root", strVal); | |
478 } | |
479 | |
480 TEST(JSONParserTest, InvalidSanity) | |
481 { | |
482 const char* const invalidJson[] = { | |
483 "/* test *", | |
484 "{\"foo\"", | |
485 "{\"foo\":", | |
486 " [", | |
487 "\"\\u123g\"", | |
488 "{\n\"eh:\n}", | |
489 "////", | |
490 "*/**/", | |
491 "/**/", | |
492 "/*/", | |
493 "//**/" | |
494 }; | |
495 | |
496 for (size_t i = 0; i < WTF_ARRAY_LENGTH(invalidJson); ++i) { | |
497 std::unique_ptr<JSONValue> result = parseJSON(invalidJson[i]); | |
498 EXPECT_FALSE(result.get()); | |
499 } | |
500 } | |
501 | |
502 } // namespace blink | |
OLD | NEW |