Skip to content

Commit 9d9deaf

Browse files
committed
Add Proxy support for JSON.stringify
JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
1 parent 4be9ffd commit 9d9deaf

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

jerry-core/ecma/builtin-objects/ecma-builtin-json.c

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,12 @@ static ecma_value_t
10051005
ecma_builtin_json_serialize_array (ecma_json_stringify_context_t *context_p, /**< context*/
10061006
ecma_object_t *obj_p) /**< the array object*/
10071007
{
1008-
JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY);
1008+
#ifndef JERRY_NDEBUG
1009+
ecma_value_t obj_value = ecma_make_object_value (obj_p);
1010+
ecma_value_t is_array = ecma_is_value_array (obj_value);
1011+
1012+
JERRY_ASSERT (ecma_is_value_true (is_array));
1013+
#endif /* !JERRY_NDEBUG */
10091014

10101015
/* 1. */
10111016
if (ecma_json_has_object_in_stack (context_p->occurence_stack_last_p, obj_p))
@@ -1027,7 +1032,23 @@ ecma_builtin_json_serialize_array (ecma_json_stringify_context_t *context_p, /**
10271032
const bool has_gap = !ecma_compare_ecma_string_to_magic_id (context_p->gap_str_p, LIT_MAGIC_STRING__EMPTY);
10281033

10291034
/* 6. */
1030-
uint32_t array_length = ((ecma_extended_object_t *) obj_p)->u.array.length;
1035+
uint32_t array_length;
1036+
1037+
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
1038+
if (ECMA_OBJECT_IS_PROXY (obj_p))
1039+
{
1040+
ecma_value_t length_value = ecma_op_object_get_length (obj_p, &array_length);
1041+
1042+
if (ECMA_IS_VALUE_ERROR (length_value))
1043+
{
1044+
return length_value;
1045+
}
1046+
}
1047+
else
1048+
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
1049+
{
1050+
array_length = ((ecma_extended_object_t *) obj_p)->u.array.length;
1051+
}
10311052

10321053
ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_LEFT_SQUARE);
10331054

@@ -1260,11 +1281,21 @@ ecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p,
12601281
/* 11. */
12611282
if (ecma_is_value_object (value) && !ecma_op_is_callable (value))
12621283
{
1284+
ecma_value_t is_array = ecma_is_value_array (value);
1285+
1286+
#if ENABLED (JERRY_ES2015)
1287+
if (ECMA_IS_VALUE_ERROR (is_array))
1288+
{
1289+
ecma_free_value (value);
1290+
return is_array;
1291+
}
1292+
#endif /* ENABLED (JERRY_ES2015) */
1293+
12631294
ecma_object_t *obj_p = ecma_get_object_from_value (value);
12641295

12651296
ecma_value_t ret_value;
12661297
/* 10.a */
1267-
if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY)
1298+
if (ecma_is_value_true (is_array))
12681299
{
12691300
ret_value = ecma_builtin_json_serialize_array (context_p, obj_p);
12701301
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright JS Foundation and other contributors, http://js.foundation
2+
//
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+
// Test with proxy
16+
assert(JSON.stringify(new Proxy(['foo'], {})) === '["foo"]');
17+
assert(JSON.stringify(new Proxy({0:"foo"}, {})) === '{"0":"foo"}');
18+
19+
var target = [1,2,3];
20+
var handler = {
21+
get(target, prop) {
22+
if (prop == "length")
23+
{
24+
throw 42;
25+
}
26+
}
27+
}
28+
29+
try {
30+
JSON.stringify(new Proxy(target,handler));
31+
assert(false);
32+
} catch (e) {
33+
assert(e === 42);
34+
}
35+
36+
var revocable = Proxy.revocable (target, { get (t, p , r) {
37+
if (p == "toJSON") {
38+
revocable.revoke();
39+
}
40+
Reflect.get(...arguments)
41+
}});
42+
var proxy = revocable.proxy;
43+
44+
try {
45+
JSON.stringify(proxy);
46+
assert(false);
47+
} catch (e) {
48+
assert(e instanceof TypeError);
49+
}

0 commit comments

Comments
 (0)