1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation 2425bb815Sopenharmony_ci * 3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License. 5425bb815Sopenharmony_ci * You may obtain a copy of the License at 6425bb815Sopenharmony_ci * 7425bb815Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8425bb815Sopenharmony_ci * 9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS 11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and 13425bb815Sopenharmony_ci * limitations under the License. 14425bb815Sopenharmony_ci */ 15425bb815Sopenharmony_ci 16425bb815Sopenharmony_ci#include "ecma-alloc.h" 17425bb815Sopenharmony_ci#include "ecma-array-object.h" 18425bb815Sopenharmony_ci#include "ecma-builtins.h" 19425bb815Sopenharmony_ci#include "ecma-conversion.h" 20425bb815Sopenharmony_ci#include "ecma-exceptions.h" 21425bb815Sopenharmony_ci#include "ecma-function-object.h" 22425bb815Sopenharmony_ci#include "ecma-gc.h" 23425bb815Sopenharmony_ci#include "ecma-globals.h" 24425bb815Sopenharmony_ci#include "ecma-helpers.h" 25425bb815Sopenharmony_ci#include "ecma-builtin-helpers.h" 26425bb815Sopenharmony_ci#include "ecma-objects.h" 27425bb815Sopenharmony_ci#include "ecma-objects-general.h" 28425bb815Sopenharmony_ci#include "jrt.h" 29425bb815Sopenharmony_ci#include "jrt-libc-includes.h" 30425bb815Sopenharmony_ci#include "lit-char-helpers.h" 31425bb815Sopenharmony_ci#include "lit-globals.h" 32425bb815Sopenharmony_ci 33425bb815Sopenharmony_ci#if ENABLED (JERRY_BUILTIN_JSON) 34425bb815Sopenharmony_ci 35425bb815Sopenharmony_ci#define ECMA_BUILTINS_INTERNAL 36425bb815Sopenharmony_ci#include "ecma-builtins-internal.h" 37425bb815Sopenharmony_ci 38425bb815Sopenharmony_ci#define BUILTIN_INC_HEADER_NAME "ecma-builtin-json.inc.h" 39425bb815Sopenharmony_ci#define BUILTIN_UNDERSCORED_ID json 40425bb815Sopenharmony_ci#include "ecma-builtin-internal-routines-template.inc.h" 41425bb815Sopenharmony_ci 42425bb815Sopenharmony_ci/** 43425bb815Sopenharmony_ci * The number of expected hexidecimal characters in a hex escape sequence 44425bb815Sopenharmony_ci */ 45425bb815Sopenharmony_ci#define ECMA_JSON_HEX_ESCAPE_SEQUENCE_LENGTH (4) 46425bb815Sopenharmony_ci 47425bb815Sopenharmony_ci/** \addtogroup ecma ECMA 48425bb815Sopenharmony_ci * @{ 49425bb815Sopenharmony_ci * 50425bb815Sopenharmony_ci * \addtogroup ecmabuiltins 51425bb815Sopenharmony_ci * @{ 52425bb815Sopenharmony_ci * 53425bb815Sopenharmony_ci * \addtogroup json ECMA JSON object built-in 54425bb815Sopenharmony_ci * @{ 55425bb815Sopenharmony_ci */ 56425bb815Sopenharmony_ci 57425bb815Sopenharmony_ci/** 58425bb815Sopenharmony_ci * JSON token type 59425bb815Sopenharmony_ci */ 60425bb815Sopenharmony_citypedef enum 61425bb815Sopenharmony_ci{ 62425bb815Sopenharmony_ci TOKEN_INVALID, /**< error token */ 63425bb815Sopenharmony_ci TOKEN_END, /**< end of stream reached */ 64425bb815Sopenharmony_ci TOKEN_NUMBER, /**< JSON number */ 65425bb815Sopenharmony_ci TOKEN_STRING, /**< JSON string */ 66425bb815Sopenharmony_ci TOKEN_NULL, /**< JSON null primitive value */ 67425bb815Sopenharmony_ci TOKEN_TRUE, /**< JSON true primitive value */ 68425bb815Sopenharmony_ci TOKEN_FALSE, /**< JSON false primitive value */ 69425bb815Sopenharmony_ci TOKEN_LEFT_BRACE, /**< JSON left brace */ 70425bb815Sopenharmony_ci TOKEN_RIGHT_BRACE, /**< JSON right brace */ 71425bb815Sopenharmony_ci TOKEN_LEFT_SQUARE, /**< JSON left square bracket */ 72425bb815Sopenharmony_ci TOKEN_RIGHT_SQUARE, /**< JSON right square bracket */ 73425bb815Sopenharmony_ci TOKEN_COMMA, /**< JSON comma */ 74425bb815Sopenharmony_ci TOKEN_COLON /**< JSON colon */ 75425bb815Sopenharmony_ci} ecma_json_token_type_t; 76425bb815Sopenharmony_ci 77425bb815Sopenharmony_ci/** 78425bb815Sopenharmony_ci * JSON token 79425bb815Sopenharmony_ci */ 80425bb815Sopenharmony_citypedef struct 81425bb815Sopenharmony_ci{ 82425bb815Sopenharmony_ci ecma_json_token_type_t type; /**< type of the current token */ 83425bb815Sopenharmony_ci const lit_utf8_byte_t *current_p; /**< current position of the string processed by the parser */ 84425bb815Sopenharmony_ci const lit_utf8_byte_t *end_p; /**< end of the string processed by the parser */ 85425bb815Sopenharmony_ci 86425bb815Sopenharmony_ci /** 87425bb815Sopenharmony_ci * Fields depending on type. 88425bb815Sopenharmony_ci */ 89425bb815Sopenharmony_ci union 90425bb815Sopenharmony_ci { 91425bb815Sopenharmony_ci ecma_string_t *string_p; /**< when type is string_token it contains the string */ 92425bb815Sopenharmony_ci ecma_number_t number; /**< when type is number_token, it contains the value of the number */ 93425bb815Sopenharmony_ci } u; 94425bb815Sopenharmony_ci} ecma_json_token_t; 95425bb815Sopenharmony_ci 96425bb815Sopenharmony_ci/** 97425bb815Sopenharmony_ci * Parse and extract string token. 98425bb815Sopenharmony_ci */ 99425bb815Sopenharmony_cistatic void 100425bb815Sopenharmony_ciecma_builtin_json_parse_string (ecma_json_token_t *token_p) /**< token argument */ 101425bb815Sopenharmony_ci{ 102425bb815Sopenharmony_ci const lit_utf8_byte_t *current_p = token_p->current_p; 103425bb815Sopenharmony_ci const lit_utf8_byte_t *end_p = token_p->end_p; 104425bb815Sopenharmony_ci 105425bb815Sopenharmony_ci ecma_stringbuilder_t result_builder = ecma_stringbuilder_create (); 106425bb815Sopenharmony_ci const lit_utf8_byte_t *unappended_p = current_p; 107425bb815Sopenharmony_ci 108425bb815Sopenharmony_ci while (true) 109425bb815Sopenharmony_ci { 110425bb815Sopenharmony_ci if (current_p >= end_p || *current_p <= 0x1f) 111425bb815Sopenharmony_ci { 112425bb815Sopenharmony_ci goto invalid_string; 113425bb815Sopenharmony_ci } 114425bb815Sopenharmony_ci 115425bb815Sopenharmony_ci if (*current_p == LIT_CHAR_DOUBLE_QUOTE) 116425bb815Sopenharmony_ci { 117425bb815Sopenharmony_ci break; 118425bb815Sopenharmony_ci } 119425bb815Sopenharmony_ci 120425bb815Sopenharmony_ci if (*current_p == LIT_CHAR_BACKSLASH) 121425bb815Sopenharmony_ci { 122425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&result_builder, 123425bb815Sopenharmony_ci unappended_p, 124425bb815Sopenharmony_ci (lit_utf8_size_t) (current_p - unappended_p)); 125425bb815Sopenharmony_ci 126425bb815Sopenharmony_ci current_p++; 127425bb815Sopenharmony_ci 128425bb815Sopenharmony_ci /* If there is an escape sequence but there's no escapable character just return */ 129425bb815Sopenharmony_ci if (current_p >= end_p) 130425bb815Sopenharmony_ci { 131425bb815Sopenharmony_ci goto invalid_string; 132425bb815Sopenharmony_ci } 133425bb815Sopenharmony_ci 134425bb815Sopenharmony_ci const lit_utf8_byte_t c = *current_p; 135425bb815Sopenharmony_ci switch (c) 136425bb815Sopenharmony_ci { 137425bb815Sopenharmony_ci case LIT_CHAR_DOUBLE_QUOTE: 138425bb815Sopenharmony_ci case LIT_CHAR_SLASH: 139425bb815Sopenharmony_ci case LIT_CHAR_BACKSLASH: 140425bb815Sopenharmony_ci { 141425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&result_builder, c); 142425bb815Sopenharmony_ci current_p++; 143425bb815Sopenharmony_ci break; 144425bb815Sopenharmony_ci } 145425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_B: 146425bb815Sopenharmony_ci { 147425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&result_builder, LIT_CHAR_BS); 148425bb815Sopenharmony_ci current_p++; 149425bb815Sopenharmony_ci break; 150425bb815Sopenharmony_ci } 151425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_F: 152425bb815Sopenharmony_ci { 153425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&result_builder, LIT_CHAR_FF); 154425bb815Sopenharmony_ci current_p++; 155425bb815Sopenharmony_ci break; 156425bb815Sopenharmony_ci } 157425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_N: 158425bb815Sopenharmony_ci { 159425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&result_builder, LIT_CHAR_LF); 160425bb815Sopenharmony_ci current_p++; 161425bb815Sopenharmony_ci break; 162425bb815Sopenharmony_ci } 163425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_R: 164425bb815Sopenharmony_ci { 165425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&result_builder, LIT_CHAR_CR); 166425bb815Sopenharmony_ci current_p++; 167425bb815Sopenharmony_ci break; 168425bb815Sopenharmony_ci } 169425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_T: 170425bb815Sopenharmony_ci { 171425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&result_builder, LIT_CHAR_TAB); 172425bb815Sopenharmony_ci current_p++; 173425bb815Sopenharmony_ci break; 174425bb815Sopenharmony_ci } 175425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_U: 176425bb815Sopenharmony_ci { 177425bb815Sopenharmony_ci uint32_t hex_value = lit_char_hex_lookup (current_p + 1, end_p, ECMA_JSON_HEX_ESCAPE_SEQUENCE_LENGTH); 178425bb815Sopenharmony_ci if (hex_value == UINT32_MAX) 179425bb815Sopenharmony_ci { 180425bb815Sopenharmony_ci goto invalid_string; 181425bb815Sopenharmony_ci } 182425bb815Sopenharmony_ci 183425bb815Sopenharmony_ci ecma_stringbuilder_append_char (&result_builder, (ecma_char_t) hex_value); 184425bb815Sopenharmony_ci current_p += ECMA_JSON_HEX_ESCAPE_SEQUENCE_LENGTH + 1; 185425bb815Sopenharmony_ci break; 186425bb815Sopenharmony_ci } 187425bb815Sopenharmony_ci default: 188425bb815Sopenharmony_ci { 189425bb815Sopenharmony_ci goto invalid_string; 190425bb815Sopenharmony_ci } 191425bb815Sopenharmony_ci } 192425bb815Sopenharmony_ci 193425bb815Sopenharmony_ci unappended_p = current_p; 194425bb815Sopenharmony_ci continue; 195425bb815Sopenharmony_ci } 196425bb815Sopenharmony_ci 197425bb815Sopenharmony_ci current_p++; 198425bb815Sopenharmony_ci } 199425bb815Sopenharmony_ci 200425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&result_builder, 201425bb815Sopenharmony_ci unappended_p, 202425bb815Sopenharmony_ci (lit_utf8_size_t) (current_p - unappended_p)); 203425bb815Sopenharmony_ci token_p->u.string_p = ecma_stringbuilder_finalize (&result_builder); 204425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 205425bb815Sopenharmony_ci token_p->type = TOKEN_STRING; 206425bb815Sopenharmony_ci return; 207425bb815Sopenharmony_ci 208425bb815Sopenharmony_ciinvalid_string: 209425bb815Sopenharmony_ci ecma_stringbuilder_destroy (&result_builder); 210425bb815Sopenharmony_ci} /* ecma_builtin_json_parse_string */ 211425bb815Sopenharmony_ci 212425bb815Sopenharmony_ci/** 213425bb815Sopenharmony_ci * Parse and extract string token. 214425bb815Sopenharmony_ci */ 215425bb815Sopenharmony_cistatic void 216425bb815Sopenharmony_ciecma_builtin_json_parse_number (ecma_json_token_t *token_p) /**< token argument */ 217425bb815Sopenharmony_ci{ 218425bb815Sopenharmony_ci const lit_utf8_byte_t *current_p = token_p->current_p; 219425bb815Sopenharmony_ci const lit_utf8_byte_t *end_p = token_p->end_p; 220425bb815Sopenharmony_ci const lit_utf8_byte_t *start_p = current_p; 221425bb815Sopenharmony_ci 222425bb815Sopenharmony_ci JERRY_ASSERT (current_p < end_p); 223425bb815Sopenharmony_ci 224425bb815Sopenharmony_ci if (*current_p == LIT_CHAR_MINUS) 225425bb815Sopenharmony_ci { 226425bb815Sopenharmony_ci current_p++; 227425bb815Sopenharmony_ci } 228425bb815Sopenharmony_ci 229425bb815Sopenharmony_ci if (current_p >= end_p) 230425bb815Sopenharmony_ci { 231425bb815Sopenharmony_ci return; 232425bb815Sopenharmony_ci } 233425bb815Sopenharmony_ci 234425bb815Sopenharmony_ci if (*current_p == LIT_CHAR_0) 235425bb815Sopenharmony_ci { 236425bb815Sopenharmony_ci current_p++; 237425bb815Sopenharmony_ci 238425bb815Sopenharmony_ci if (current_p < end_p && lit_char_is_decimal_digit (*current_p)) 239425bb815Sopenharmony_ci { 240425bb815Sopenharmony_ci return; 241425bb815Sopenharmony_ci } 242425bb815Sopenharmony_ci } 243425bb815Sopenharmony_ci else if (lit_char_is_decimal_digit (*current_p)) 244425bb815Sopenharmony_ci { 245425bb815Sopenharmony_ci do 246425bb815Sopenharmony_ci { 247425bb815Sopenharmony_ci current_p++; 248425bb815Sopenharmony_ci } 249425bb815Sopenharmony_ci while (current_p < end_p && lit_char_is_decimal_digit (*current_p)); 250425bb815Sopenharmony_ci } 251425bb815Sopenharmony_ci 252425bb815Sopenharmony_ci if (current_p < end_p && *current_p == LIT_CHAR_DOT) 253425bb815Sopenharmony_ci { 254425bb815Sopenharmony_ci current_p++; 255425bb815Sopenharmony_ci 256425bb815Sopenharmony_ci if (current_p >= end_p || !lit_char_is_decimal_digit (*current_p)) 257425bb815Sopenharmony_ci { 258425bb815Sopenharmony_ci return; 259425bb815Sopenharmony_ci } 260425bb815Sopenharmony_ci 261425bb815Sopenharmony_ci do 262425bb815Sopenharmony_ci { 263425bb815Sopenharmony_ci current_p++; 264425bb815Sopenharmony_ci } 265425bb815Sopenharmony_ci while (current_p < end_p && lit_char_is_decimal_digit (*current_p)); 266425bb815Sopenharmony_ci } 267425bb815Sopenharmony_ci 268425bb815Sopenharmony_ci if (current_p < end_p && (*current_p == LIT_CHAR_LOWERCASE_E || *current_p == LIT_CHAR_UPPERCASE_E)) 269425bb815Sopenharmony_ci { 270425bb815Sopenharmony_ci current_p++; 271425bb815Sopenharmony_ci 272425bb815Sopenharmony_ci if (current_p < end_p && (*current_p == LIT_CHAR_PLUS || *current_p == LIT_CHAR_MINUS)) 273425bb815Sopenharmony_ci { 274425bb815Sopenharmony_ci current_p++; 275425bb815Sopenharmony_ci } 276425bb815Sopenharmony_ci 277425bb815Sopenharmony_ci if (current_p >= end_p || !lit_char_is_decimal_digit (*current_p)) 278425bb815Sopenharmony_ci { 279425bb815Sopenharmony_ci return; 280425bb815Sopenharmony_ci } 281425bb815Sopenharmony_ci 282425bb815Sopenharmony_ci do 283425bb815Sopenharmony_ci { 284425bb815Sopenharmony_ci current_p++; 285425bb815Sopenharmony_ci } 286425bb815Sopenharmony_ci while (current_p < end_p && lit_char_is_decimal_digit (*current_p)); 287425bb815Sopenharmony_ci } 288425bb815Sopenharmony_ci 289425bb815Sopenharmony_ci token_p->type = TOKEN_NUMBER; 290425bb815Sopenharmony_ci token_p->u.number = ecma_utf8_string_to_number (start_p, (lit_utf8_size_t) (current_p - start_p)); 291425bb815Sopenharmony_ci 292425bb815Sopenharmony_ci token_p->current_p = current_p; 293425bb815Sopenharmony_ci} /* ecma_builtin_json_parse_number */ 294425bb815Sopenharmony_ci 295425bb815Sopenharmony_ci/** 296425bb815Sopenharmony_ci * Parse next token. 297425bb815Sopenharmony_ci * 298425bb815Sopenharmony_ci * The function fills the fields of the ecma_json_token_t 299425bb815Sopenharmony_ci * argument and advances the string pointer. 300425bb815Sopenharmony_ci */ 301425bb815Sopenharmony_cistatic void 302425bb815Sopenharmony_ciecma_builtin_json_parse_next_token (ecma_json_token_t *token_p, /**< token argument */ 303425bb815Sopenharmony_ci bool parse_string) /**< strings are allowed to parse */ 304425bb815Sopenharmony_ci{ 305425bb815Sopenharmony_ci const lit_utf8_byte_t *current_p = token_p->current_p; 306425bb815Sopenharmony_ci const lit_utf8_byte_t *end_p = token_p->end_p; 307425bb815Sopenharmony_ci token_p->type = TOKEN_INVALID; 308425bb815Sopenharmony_ci 309425bb815Sopenharmony_ci while (current_p < end_p 310425bb815Sopenharmony_ci && (*current_p == LIT_CHAR_SP 311425bb815Sopenharmony_ci || *current_p == LIT_CHAR_CR 312425bb815Sopenharmony_ci || *current_p == LIT_CHAR_LF 313425bb815Sopenharmony_ci || *current_p == LIT_CHAR_TAB)) 314425bb815Sopenharmony_ci { 315425bb815Sopenharmony_ci current_p++; 316425bb815Sopenharmony_ci } 317425bb815Sopenharmony_ci 318425bb815Sopenharmony_ci if (current_p == end_p) 319425bb815Sopenharmony_ci { 320425bb815Sopenharmony_ci token_p->type = TOKEN_END; 321425bb815Sopenharmony_ci return; 322425bb815Sopenharmony_ci } 323425bb815Sopenharmony_ci 324425bb815Sopenharmony_ci switch (*current_p) 325425bb815Sopenharmony_ci { 326425bb815Sopenharmony_ci case LIT_CHAR_LEFT_BRACE: 327425bb815Sopenharmony_ci { 328425bb815Sopenharmony_ci token_p->type = TOKEN_LEFT_BRACE; 329425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 330425bb815Sopenharmony_ci return; 331425bb815Sopenharmony_ci } 332425bb815Sopenharmony_ci case LIT_CHAR_RIGHT_BRACE: 333425bb815Sopenharmony_ci { 334425bb815Sopenharmony_ci token_p->type = TOKEN_RIGHT_BRACE; 335425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 336425bb815Sopenharmony_ci return; 337425bb815Sopenharmony_ci } 338425bb815Sopenharmony_ci case LIT_CHAR_LEFT_SQUARE: 339425bb815Sopenharmony_ci { 340425bb815Sopenharmony_ci token_p->type = TOKEN_LEFT_SQUARE; 341425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 342425bb815Sopenharmony_ci return; 343425bb815Sopenharmony_ci } 344425bb815Sopenharmony_ci case LIT_CHAR_RIGHT_SQUARE: 345425bb815Sopenharmony_ci { 346425bb815Sopenharmony_ci token_p->type = TOKEN_RIGHT_SQUARE; 347425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 348425bb815Sopenharmony_ci return; 349425bb815Sopenharmony_ci } 350425bb815Sopenharmony_ci case LIT_CHAR_COMMA: 351425bb815Sopenharmony_ci { 352425bb815Sopenharmony_ci token_p->type = TOKEN_COMMA; 353425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 354425bb815Sopenharmony_ci return; 355425bb815Sopenharmony_ci } 356425bb815Sopenharmony_ci case LIT_CHAR_COLON: 357425bb815Sopenharmony_ci { 358425bb815Sopenharmony_ci token_p->type = TOKEN_COLON; 359425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 360425bb815Sopenharmony_ci return; 361425bb815Sopenharmony_ci } 362425bb815Sopenharmony_ci case LIT_CHAR_DOUBLE_QUOTE: 363425bb815Sopenharmony_ci { 364425bb815Sopenharmony_ci if (parse_string) 365425bb815Sopenharmony_ci { 366425bb815Sopenharmony_ci token_p->current_p = current_p + 1; 367425bb815Sopenharmony_ci ecma_builtin_json_parse_string (token_p); 368425bb815Sopenharmony_ci } 369425bb815Sopenharmony_ci return; 370425bb815Sopenharmony_ci } 371425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_N: 372425bb815Sopenharmony_ci { 373425bb815Sopenharmony_ci lit_utf8_size_t size = lit_get_magic_string_size (LIT_MAGIC_STRING_NULL); 374425bb815Sopenharmony_ci if (current_p + size <= end_p) 375425bb815Sopenharmony_ci { 376425bb815Sopenharmony_ci if (!memcmp (lit_get_magic_string_utf8 (LIT_MAGIC_STRING_NULL), 377425bb815Sopenharmony_ci current_p, 378425bb815Sopenharmony_ci size)) 379425bb815Sopenharmony_ci { 380425bb815Sopenharmony_ci token_p->type = TOKEN_NULL; 381425bb815Sopenharmony_ci token_p->current_p = current_p + size; 382425bb815Sopenharmony_ci return; 383425bb815Sopenharmony_ci } 384425bb815Sopenharmony_ci } 385425bb815Sopenharmony_ci break; 386425bb815Sopenharmony_ci } 387425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_T: 388425bb815Sopenharmony_ci { 389425bb815Sopenharmony_ci lit_utf8_size_t size = lit_get_magic_string_size (LIT_MAGIC_STRING_TRUE); 390425bb815Sopenharmony_ci if (current_p + size <= end_p) 391425bb815Sopenharmony_ci { 392425bb815Sopenharmony_ci if (!memcmp (lit_get_magic_string_utf8 (LIT_MAGIC_STRING_TRUE), 393425bb815Sopenharmony_ci current_p, 394425bb815Sopenharmony_ci size)) 395425bb815Sopenharmony_ci { 396425bb815Sopenharmony_ci token_p->type = TOKEN_TRUE; 397425bb815Sopenharmony_ci token_p->current_p = current_p + size; 398425bb815Sopenharmony_ci return; 399425bb815Sopenharmony_ci } 400425bb815Sopenharmony_ci } 401425bb815Sopenharmony_ci break; 402425bb815Sopenharmony_ci } 403425bb815Sopenharmony_ci case LIT_CHAR_LOWERCASE_F: 404425bb815Sopenharmony_ci { 405425bb815Sopenharmony_ci lit_utf8_size_t size = lit_get_magic_string_size (LIT_MAGIC_STRING_FALSE); 406425bb815Sopenharmony_ci if (current_p + size <= end_p) 407425bb815Sopenharmony_ci { 408425bb815Sopenharmony_ci if (!memcmp (lit_get_magic_string_utf8 (LIT_MAGIC_STRING_FALSE), 409425bb815Sopenharmony_ci current_p, 410425bb815Sopenharmony_ci size)) 411425bb815Sopenharmony_ci { 412425bb815Sopenharmony_ci token_p->type = TOKEN_FALSE; 413425bb815Sopenharmony_ci token_p->current_p = current_p + size; 414425bb815Sopenharmony_ci return; 415425bb815Sopenharmony_ci } 416425bb815Sopenharmony_ci } 417425bb815Sopenharmony_ci break; 418425bb815Sopenharmony_ci } 419425bb815Sopenharmony_ci default: 420425bb815Sopenharmony_ci { 421425bb815Sopenharmony_ci if (*current_p == LIT_CHAR_MINUS || lit_char_is_decimal_digit (*current_p)) 422425bb815Sopenharmony_ci { 423425bb815Sopenharmony_ci token_p->current_p = current_p; 424425bb815Sopenharmony_ci ecma_builtin_json_parse_number (token_p); 425425bb815Sopenharmony_ci return; 426425bb815Sopenharmony_ci } 427425bb815Sopenharmony_ci break; 428425bb815Sopenharmony_ci } 429425bb815Sopenharmony_ci } 430425bb815Sopenharmony_ci} /* ecma_builtin_json_parse_next_token */ 431425bb815Sopenharmony_ci 432425bb815Sopenharmony_ci/** 433425bb815Sopenharmony_ci * Utility for defining properties. 434425bb815Sopenharmony_ci * 435425bb815Sopenharmony_ci * It silently ignores all errors. 436425bb815Sopenharmony_ci */ 437425bb815Sopenharmony_cistatic void 438425bb815Sopenharmony_ciecma_builtin_json_define_value_property (ecma_object_t *obj_p, /**< this object */ 439425bb815Sopenharmony_ci ecma_string_t *property_name_p, /**< property name */ 440425bb815Sopenharmony_ci ecma_value_t value) /**< value */ 441425bb815Sopenharmony_ci{ 442425bb815Sopenharmony_ci ecma_value_t completion_value = ecma_builtin_helper_def_prop (obj_p, 443425bb815Sopenharmony_ci property_name_p, 444425bb815Sopenharmony_ci value, 445425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); 446425bb815Sopenharmony_ci 447425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_boolean (completion_value)); 448425bb815Sopenharmony_ci} /* ecma_builtin_json_define_value_property */ 449425bb815Sopenharmony_ci 450425bb815Sopenharmony_ci/** 451425bb815Sopenharmony_ci * Parse next value. 452425bb815Sopenharmony_ci * 453425bb815Sopenharmony_ci * The function fills the fields of the ecma_json_token_t 454425bb815Sopenharmony_ci * argument and advances the string pointer. 455425bb815Sopenharmony_ci * 456425bb815Sopenharmony_ci * @return ecma_value with the property value 457425bb815Sopenharmony_ci */ 458425bb815Sopenharmony_cistatic ecma_value_t 459425bb815Sopenharmony_ciecma_builtin_json_parse_value (ecma_json_token_t *token_p) /**< token argument */ 460425bb815Sopenharmony_ci{ 461425bb815Sopenharmony_ci switch (token_p->type) 462425bb815Sopenharmony_ci { 463425bb815Sopenharmony_ci case TOKEN_NUMBER: 464425bb815Sopenharmony_ci { 465425bb815Sopenharmony_ci return ecma_make_number_value (token_p->u.number); 466425bb815Sopenharmony_ci } 467425bb815Sopenharmony_ci case TOKEN_STRING: 468425bb815Sopenharmony_ci { 469425bb815Sopenharmony_ci return ecma_make_string_value (token_p->u.string_p); 470425bb815Sopenharmony_ci } 471425bb815Sopenharmony_ci case TOKEN_NULL: 472425bb815Sopenharmony_ci { 473425bb815Sopenharmony_ci return ECMA_VALUE_NULL; 474425bb815Sopenharmony_ci } 475425bb815Sopenharmony_ci case TOKEN_TRUE: 476425bb815Sopenharmony_ci { 477425bb815Sopenharmony_ci return ECMA_VALUE_TRUE; 478425bb815Sopenharmony_ci } 479425bb815Sopenharmony_ci case TOKEN_FALSE: 480425bb815Sopenharmony_ci { 481425bb815Sopenharmony_ci return ECMA_VALUE_FALSE; 482425bb815Sopenharmony_ci } 483425bb815Sopenharmony_ci case TOKEN_LEFT_BRACE: 484425bb815Sopenharmony_ci { 485425bb815Sopenharmony_ci ecma_object_t *object_p = ecma_op_create_object_object_noarg (); 486425bb815Sopenharmony_ci 487425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, true); 488425bb815Sopenharmony_ci 489425bb815Sopenharmony_ci if (token_p->type == TOKEN_RIGHT_BRACE) 490425bb815Sopenharmony_ci { 491425bb815Sopenharmony_ci return ecma_make_object_value (object_p); 492425bb815Sopenharmony_ci } 493425bb815Sopenharmony_ci 494425bb815Sopenharmony_ci while (true) 495425bb815Sopenharmony_ci { 496425bb815Sopenharmony_ci if (token_p->type != TOKEN_STRING) 497425bb815Sopenharmony_ci { 498425bb815Sopenharmony_ci break; 499425bb815Sopenharmony_ci } 500425bb815Sopenharmony_ci 501425bb815Sopenharmony_ci ecma_string_t *name_p = token_p->u.string_p; 502425bb815Sopenharmony_ci 503425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, false); 504425bb815Sopenharmony_ci if (token_p->type != TOKEN_COLON) 505425bb815Sopenharmony_ci { 506425bb815Sopenharmony_ci ecma_deref_ecma_string (name_p); 507425bb815Sopenharmony_ci break; 508425bb815Sopenharmony_ci } 509425bb815Sopenharmony_ci 510425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, true); 511425bb815Sopenharmony_ci ecma_value_t value = ecma_builtin_json_parse_value (token_p); 512425bb815Sopenharmony_ci 513425bb815Sopenharmony_ci if (ecma_is_value_empty (value)) 514425bb815Sopenharmony_ci { 515425bb815Sopenharmony_ci ecma_deref_ecma_string (name_p); 516425bb815Sopenharmony_ci break; 517425bb815Sopenharmony_ci } 518425bb815Sopenharmony_ci 519425bb815Sopenharmony_ci ecma_builtin_json_define_value_property (object_p, name_p, value); 520425bb815Sopenharmony_ci ecma_deref_ecma_string (name_p); 521425bb815Sopenharmony_ci ecma_free_value (value); 522425bb815Sopenharmony_ci 523425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, false); 524425bb815Sopenharmony_ci if (token_p->type == TOKEN_RIGHT_BRACE) 525425bb815Sopenharmony_ci { 526425bb815Sopenharmony_ci return ecma_make_object_value (object_p); 527425bb815Sopenharmony_ci } 528425bb815Sopenharmony_ci 529425bb815Sopenharmony_ci if (token_p->type != TOKEN_COMMA) 530425bb815Sopenharmony_ci { 531425bb815Sopenharmony_ci break; 532425bb815Sopenharmony_ci } 533425bb815Sopenharmony_ci 534425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, true); 535425bb815Sopenharmony_ci } 536425bb815Sopenharmony_ci 537425bb815Sopenharmony_ci /* 538425bb815Sopenharmony_ci * Parse error occured. 539425bb815Sopenharmony_ci */ 540425bb815Sopenharmony_ci ecma_deref_object (object_p); 541425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 542425bb815Sopenharmony_ci } 543425bb815Sopenharmony_ci case TOKEN_LEFT_SQUARE: 544425bb815Sopenharmony_ci { 545425bb815Sopenharmony_ci uint32_t length = 0; 546425bb815Sopenharmony_ci 547425bb815Sopenharmony_ci ecma_value_t array_construction = ecma_op_create_array_object (NULL, 0, false); 548425bb815Sopenharmony_ci JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (array_construction)); 549425bb815Sopenharmony_ci 550425bb815Sopenharmony_ci ecma_object_t *array_p = ecma_get_object_from_value (array_construction); 551425bb815Sopenharmony_ci 552425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, true); 553425bb815Sopenharmony_ci 554425bb815Sopenharmony_ci if (token_p->type == TOKEN_RIGHT_SQUARE) 555425bb815Sopenharmony_ci { 556425bb815Sopenharmony_ci return ecma_make_object_value (array_p); 557425bb815Sopenharmony_ci } 558425bb815Sopenharmony_ci 559425bb815Sopenharmony_ci while (true) 560425bb815Sopenharmony_ci { 561425bb815Sopenharmony_ci ecma_value_t value = ecma_builtin_json_parse_value (token_p); 562425bb815Sopenharmony_ci 563425bb815Sopenharmony_ci if (ecma_is_value_empty (value)) 564425bb815Sopenharmony_ci { 565425bb815Sopenharmony_ci JERRY_ASSERT (token_p->type != TOKEN_STRING); 566425bb815Sopenharmony_ci break; 567425bb815Sopenharmony_ci } 568425bb815Sopenharmony_ci 569425bb815Sopenharmony_ci ecma_value_t completion; 570425bb815Sopenharmony_ci completion = ecma_builtin_helper_def_prop_by_index (array_p, 571425bb815Sopenharmony_ci length, 572425bb815Sopenharmony_ci value, 573425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); 574425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_true (completion)); 575425bb815Sopenharmony_ci ecma_free_value (value); 576425bb815Sopenharmony_ci 577425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, false); 578425bb815Sopenharmony_ci 579425bb815Sopenharmony_ci if (token_p->type == TOKEN_RIGHT_SQUARE) 580425bb815Sopenharmony_ci { 581425bb815Sopenharmony_ci return ecma_make_object_value (array_p); 582425bb815Sopenharmony_ci } 583425bb815Sopenharmony_ci 584425bb815Sopenharmony_ci if (token_p->type != TOKEN_COMMA) 585425bb815Sopenharmony_ci { 586425bb815Sopenharmony_ci JERRY_ASSERT (token_p->type != TOKEN_STRING); 587425bb815Sopenharmony_ci break; 588425bb815Sopenharmony_ci } 589425bb815Sopenharmony_ci 590425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (token_p, true); 591425bb815Sopenharmony_ci length++; 592425bb815Sopenharmony_ci } 593425bb815Sopenharmony_ci 594425bb815Sopenharmony_ci ecma_deref_object (array_p); 595425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 596425bb815Sopenharmony_ci } 597425bb815Sopenharmony_ci default: 598425bb815Sopenharmony_ci { 599425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 600425bb815Sopenharmony_ci } 601425bb815Sopenharmony_ci } 602425bb815Sopenharmony_ci} /* ecma_builtin_json_parse_value */ 603425bb815Sopenharmony_ci 604425bb815Sopenharmony_ci/** 605425bb815Sopenharmony_ci * Abstract operation InternalizeJSONProperty defined in 24.3.1.1 606425bb815Sopenharmony_ci * 607425bb815Sopenharmony_ci * @return ecma value 608425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 609425bb815Sopenharmony_ci */ 610425bb815Sopenharmony_cistatic ecma_value_t 611425bb815Sopenharmony_ciecma_builtin_json_internalize_property (ecma_object_t *reviver_p, /**< reviver function */ 612425bb815Sopenharmony_ci ecma_object_t *holder_p, /**< holder object */ 613425bb815Sopenharmony_ci ecma_string_t *name_p) /**< property name */ 614425bb815Sopenharmony_ci{ 615425bb815Sopenharmony_ci JERRY_ASSERT (reviver_p); 616425bb815Sopenharmony_ci JERRY_ASSERT (holder_p); 617425bb815Sopenharmony_ci JERRY_ASSERT (name_p); 618425bb815Sopenharmony_ci 619425bb815Sopenharmony_ci /* 1. */ 620425bb815Sopenharmony_ci ecma_value_t value = ecma_op_object_get (holder_p, name_p); 621425bb815Sopenharmony_ci 622425bb815Sopenharmony_ci /* 2. */ 623425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (value)) 624425bb815Sopenharmony_ci { 625425bb815Sopenharmony_ci return value; 626425bb815Sopenharmony_ci } 627425bb815Sopenharmony_ci 628425bb815Sopenharmony_ci /* 3. */ 629425bb815Sopenharmony_ci if (ecma_is_value_object (value)) 630425bb815Sopenharmony_ci { 631425bb815Sopenharmony_ci ecma_object_t *object_p = ecma_get_object_from_value (value); 632425bb815Sopenharmony_ci 633425bb815Sopenharmony_ci ecma_collection_t *props_p = ecma_op_object_get_property_names (object_p, ECMA_LIST_ENUMERABLE); 634425bb815Sopenharmony_ci 635425bb815Sopenharmony_ci ecma_value_t *buffer_p = props_p->buffer_p; 636425bb815Sopenharmony_ci 637425bb815Sopenharmony_ci /* 3.d.iii */ 638425bb815Sopenharmony_ci for (uint32_t i = 0; i < props_p->item_count; i++) 639425bb815Sopenharmony_ci { 640425bb815Sopenharmony_ci ecma_string_t *property_name_p = ecma_get_string_from_value (buffer_p[i]); 641425bb815Sopenharmony_ci 642425bb815Sopenharmony_ci /* 3.d.iii.1 */ 643425bb815Sopenharmony_ci ecma_value_t result = ecma_builtin_json_internalize_property (reviver_p, object_p, property_name_p); 644425bb815Sopenharmony_ci 645425bb815Sopenharmony_ci /* 3.d.iii.2 */ 646425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 647425bb815Sopenharmony_ci { 648425bb815Sopenharmony_ci ecma_collection_free (props_p); 649425bb815Sopenharmony_ci ecma_deref_object (object_p); 650425bb815Sopenharmony_ci 651425bb815Sopenharmony_ci return result; 652425bb815Sopenharmony_ci } 653425bb815Sopenharmony_ci 654425bb815Sopenharmony_ci /* 3.d.iii.3 */ 655425bb815Sopenharmony_ci if (ecma_is_value_undefined (result)) 656425bb815Sopenharmony_ci { 657425bb815Sopenharmony_ci ecma_value_t delete_val = ecma_op_general_object_delete (object_p, 658425bb815Sopenharmony_ci property_name_p, 659425bb815Sopenharmony_ci false); 660425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_boolean (delete_val)); 661425bb815Sopenharmony_ci } 662425bb815Sopenharmony_ci /* 3.d.iii.4 */ 663425bb815Sopenharmony_ci else 664425bb815Sopenharmony_ci { 665425bb815Sopenharmony_ci ecma_builtin_json_define_value_property (object_p, 666425bb815Sopenharmony_ci property_name_p, 667425bb815Sopenharmony_ci result); 668425bb815Sopenharmony_ci ecma_free_value (result); 669425bb815Sopenharmony_ci } 670425bb815Sopenharmony_ci } 671425bb815Sopenharmony_ci 672425bb815Sopenharmony_ci ecma_collection_free (props_p); 673425bb815Sopenharmony_ci } 674425bb815Sopenharmony_ci 675425bb815Sopenharmony_ci ecma_value_t arguments_list[2]; 676425bb815Sopenharmony_ci arguments_list[0] = ecma_make_string_value (name_p); 677425bb815Sopenharmony_ci arguments_list[1] = value; 678425bb815Sopenharmony_ci 679425bb815Sopenharmony_ci /* 4. */ 680425bb815Sopenharmony_ci ecma_value_t ret_value = ecma_op_function_call (reviver_p, 681425bb815Sopenharmony_ci ecma_make_object_value (holder_p), 682425bb815Sopenharmony_ci arguments_list, 683425bb815Sopenharmony_ci 2); 684425bb815Sopenharmony_ci ecma_free_value (value); 685425bb815Sopenharmony_ci return ret_value; 686425bb815Sopenharmony_ci} /* ecma_builtin_json_internalize_property */ 687425bb815Sopenharmony_ci 688425bb815Sopenharmony_ci/** 689425bb815Sopenharmony_ci * Function to set a string token from the given arguments, fills its fields and advances the string pointer. 690425bb815Sopenharmony_ci * 691425bb815Sopenharmony_ci * @return ecma_value_t containing an object or an error massage 692425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 693425bb815Sopenharmony_ci */ 694425bb815Sopenharmony_ciecma_value_t 695425bb815Sopenharmony_ciecma_builtin_json_parse_buffer (const lit_utf8_byte_t * str_start_p, /**< String to parse */ 696425bb815Sopenharmony_ci lit_utf8_size_t string_size) /**< size of the string */ 697425bb815Sopenharmony_ci{ 698425bb815Sopenharmony_ci ecma_json_token_t token; 699425bb815Sopenharmony_ci token.current_p = str_start_p; 700425bb815Sopenharmony_ci token.end_p = str_start_p + string_size; 701425bb815Sopenharmony_ci 702425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (&token, true); 703425bb815Sopenharmony_ci ecma_value_t result = ecma_builtin_json_parse_value (&token); 704425bb815Sopenharmony_ci 705425bb815Sopenharmony_ci if (!ecma_is_value_empty (result)) 706425bb815Sopenharmony_ci { 707425bb815Sopenharmony_ci ecma_builtin_json_parse_next_token (&token, false); 708425bb815Sopenharmony_ci if (token.type == TOKEN_END) 709425bb815Sopenharmony_ci { 710425bb815Sopenharmony_ci return result; 711425bb815Sopenharmony_ci } 712425bb815Sopenharmony_ci 713425bb815Sopenharmony_ci ecma_free_value (result); 714425bb815Sopenharmony_ci } 715425bb815Sopenharmony_ci 716425bb815Sopenharmony_ci return ecma_raise_syntax_error (ECMA_ERR_MSG ("Invalid JSON format.")); 717425bb815Sopenharmony_ci} /*ecma_builtin_json_parse_buffer*/ 718425bb815Sopenharmony_ci 719425bb815Sopenharmony_ci/** 720425bb815Sopenharmony_ci * The JSON object's 'parse' routine 721425bb815Sopenharmony_ci * 722425bb815Sopenharmony_ci * See also: 723425bb815Sopenharmony_ci * ECMA-262 v5, 15.12.2 724425bb815Sopenharmony_ci * 725425bb815Sopenharmony_ci * @return ecma value 726425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 727425bb815Sopenharmony_ci */ 728425bb815Sopenharmony_cistatic ecma_value_t 729425bb815Sopenharmony_ciecma_builtin_json_parse (ecma_value_t this_arg, /**< 'this' argument */ 730425bb815Sopenharmony_ci ecma_value_t arg1, /**< string argument */ 731425bb815Sopenharmony_ci ecma_value_t arg2) /**< reviver argument */ 732425bb815Sopenharmony_ci{ 733425bb815Sopenharmony_ci JERRY_UNUSED (this_arg); 734425bb815Sopenharmony_ci 735425bb815Sopenharmony_ci ecma_string_t *text_string_p = ecma_op_to_string (arg1); 736425bb815Sopenharmony_ci 737425bb815Sopenharmony_ci if (JERRY_UNLIKELY (text_string_p == NULL)) 738425bb815Sopenharmony_ci { 739425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 740425bb815Sopenharmony_ci } 741425bb815Sopenharmony_ci 742425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (text_string_p, str_start_p, string_size); 743425bb815Sopenharmony_ci ecma_value_t result = ecma_builtin_json_parse_buffer (str_start_p, string_size); 744425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (str_start_p, string_size); 745425bb815Sopenharmony_ci ecma_deref_ecma_string (text_string_p); 746425bb815Sopenharmony_ci 747425bb815Sopenharmony_ci if (!ECMA_IS_VALUE_ERROR (result) && ecma_op_is_callable (arg2)) 748425bb815Sopenharmony_ci { 749425bb815Sopenharmony_ci ecma_object_t *object_p = ecma_op_create_object_object_noarg (); 750425bb815Sopenharmony_ci 751425bb815Sopenharmony_ci ecma_property_value_t *prop_value_p; 752425bb815Sopenharmony_ci prop_value_p = ecma_create_named_data_property (object_p, 753425bb815Sopenharmony_ci ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY), 754425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE, 755425bb815Sopenharmony_ci NULL); 756425bb815Sopenharmony_ci 757425bb815Sopenharmony_ci ecma_named_data_property_assign_value (object_p, prop_value_p, result); 758425bb815Sopenharmony_ci 759425bb815Sopenharmony_ci ecma_free_value (result); 760425bb815Sopenharmony_ci result = ecma_builtin_json_internalize_property (ecma_get_object_from_value (arg2), 761425bb815Sopenharmony_ci object_p, 762425bb815Sopenharmony_ci ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY)); 763425bb815Sopenharmony_ci ecma_deref_object (object_p); 764425bb815Sopenharmony_ci } 765425bb815Sopenharmony_ci 766425bb815Sopenharmony_ci return result; 767425bb815Sopenharmony_ci} /* ecma_builtin_json_parse */ 768425bb815Sopenharmony_ci 769425bb815Sopenharmony_ci/** 770425bb815Sopenharmony_ci * Abstract operation 'QuoteJSONString' defined in 24.3.2.2 771425bb815Sopenharmony_ci */ 772425bb815Sopenharmony_cistatic void 773425bb815Sopenharmony_ciecma_builtin_json_quote (ecma_stringbuilder_t *builder_p, /**< builder for the result */ 774425bb815Sopenharmony_ci ecma_string_t *string_p) /**< string that should be quoted */ 775425bb815Sopenharmony_ci{ 776425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING (string_p, string_buff, string_buff_size); 777425bb815Sopenharmony_ci const lit_utf8_byte_t *str_p = string_buff; 778425bb815Sopenharmony_ci const lit_utf8_byte_t *regular_str_start_p = string_buff; 779425bb815Sopenharmony_ci const lit_utf8_byte_t *str_end_p = str_p + string_buff_size; 780425bb815Sopenharmony_ci 781425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_DOUBLE_QUOTE); 782425bb815Sopenharmony_ci 783425bb815Sopenharmony_ci while (str_p < str_end_p) 784425bb815Sopenharmony_ci { 785425bb815Sopenharmony_ci lit_utf8_byte_t c = *str_p++; 786425bb815Sopenharmony_ci 787425bb815Sopenharmony_ci if (c == LIT_CHAR_BACKSLASH || c == LIT_CHAR_DOUBLE_QUOTE) 788425bb815Sopenharmony_ci { 789425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (builder_p, 790425bb815Sopenharmony_ci regular_str_start_p, 791425bb815Sopenharmony_ci (lit_utf8_size_t) (str_p - regular_str_start_p - 1)); 792425bb815Sopenharmony_ci regular_str_start_p = str_p; 793425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_BACKSLASH); 794425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, c); 795425bb815Sopenharmony_ci } 796425bb815Sopenharmony_ci else if (c < LIT_CHAR_SP) 797425bb815Sopenharmony_ci { 798425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (builder_p, 799425bb815Sopenharmony_ci regular_str_start_p, 800425bb815Sopenharmony_ci (lit_utf8_size_t) (str_p - regular_str_start_p - 1)); 801425bb815Sopenharmony_ci regular_str_start_p = str_p; 802425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_BACKSLASH); 803425bb815Sopenharmony_ci switch (c) 804425bb815Sopenharmony_ci { 805425bb815Sopenharmony_ci case LIT_CHAR_BS: 806425bb815Sopenharmony_ci { 807425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_LOWERCASE_B); 808425bb815Sopenharmony_ci break; 809425bb815Sopenharmony_ci } 810425bb815Sopenharmony_ci case LIT_CHAR_FF: 811425bb815Sopenharmony_ci { 812425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_LOWERCASE_F); 813425bb815Sopenharmony_ci break; 814425bb815Sopenharmony_ci } 815425bb815Sopenharmony_ci case LIT_CHAR_LF: 816425bb815Sopenharmony_ci { 817425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_LOWERCASE_N); 818425bb815Sopenharmony_ci break; 819425bb815Sopenharmony_ci } 820425bb815Sopenharmony_ci case LIT_CHAR_CR: 821425bb815Sopenharmony_ci { 822425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_LOWERCASE_R); 823425bb815Sopenharmony_ci break; 824425bb815Sopenharmony_ci } 825425bb815Sopenharmony_ci case LIT_CHAR_TAB: 826425bb815Sopenharmony_ci { 827425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_LOWERCASE_T); 828425bb815Sopenharmony_ci break; 829425bb815Sopenharmony_ci } 830425bb815Sopenharmony_ci default: /* Hexadecimal. */ 831425bb815Sopenharmony_ci { 832425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_LOWERCASE_U); 833425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_0); 834425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_0); 835425bb815Sopenharmony_ci 836425bb815Sopenharmony_ci /* Max range 0-9, hex digits unnecessary. */ 837425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, (lit_utf8_byte_t) (LIT_CHAR_0 + (c >> 4))); 838425bb815Sopenharmony_ci 839425bb815Sopenharmony_ci lit_utf8_byte_t c2 = (c & 0xf); 840425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, 841425bb815Sopenharmony_ci (lit_utf8_byte_t) (c2 + ((c2 <= 9) 842425bb815Sopenharmony_ci ? LIT_CHAR_0 843425bb815Sopenharmony_ci : (LIT_CHAR_LOWERCASE_A - 10)))); 844425bb815Sopenharmony_ci break; 845425bb815Sopenharmony_ci } 846425bb815Sopenharmony_ci } 847425bb815Sopenharmony_ci } 848425bb815Sopenharmony_ci } 849425bb815Sopenharmony_ci 850425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (builder_p, 851425bb815Sopenharmony_ci regular_str_start_p, 852425bb815Sopenharmony_ci (lit_utf8_size_t) (str_end_p - regular_str_start_p)); 853425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (builder_p, LIT_CHAR_DOUBLE_QUOTE); 854425bb815Sopenharmony_ci 855425bb815Sopenharmony_ci ECMA_FINALIZE_UTF8_STRING (string_buff, string_buff_size); 856425bb815Sopenharmony_ci} /* ecma_builtin_json_quote */ 857425bb815Sopenharmony_ci 858425bb815Sopenharmony_cistatic ecma_value_t 859425bb815Sopenharmony_ciecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, 860425bb815Sopenharmony_ci ecma_object_t *holder_p, 861425bb815Sopenharmony_ci ecma_string_t *key_p); 862425bb815Sopenharmony_ci 863425bb815Sopenharmony_ci/** 864425bb815Sopenharmony_ci * Abstract operation 'SerializeJSONObject' defined in 24.3.2.3 865425bb815Sopenharmony_ci * 866425bb815Sopenharmony_ci * @return ecma value 867425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 868425bb815Sopenharmony_ci */ 869425bb815Sopenharmony_cistatic ecma_value_t 870425bb815Sopenharmony_ciecma_builtin_json_serialize_object (ecma_json_stringify_context_t *context_p, /**< context*/ 871425bb815Sopenharmony_ci ecma_object_t *obj_p) /**< the object*/ 872425bb815Sopenharmony_ci{ 873425bb815Sopenharmony_ci /* 1. */ 874425bb815Sopenharmony_ci if (ecma_json_has_object_in_stack (context_p->occurence_stack_last_p, obj_p)) 875425bb815Sopenharmony_ci { 876425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("The structure is cyclical.")); 877425bb815Sopenharmony_ci } 878425bb815Sopenharmony_ci 879425bb815Sopenharmony_ci /* 2. */ 880425bb815Sopenharmony_ci ecma_json_occurence_stack_item_t stack_item; 881425bb815Sopenharmony_ci stack_item.next_p = context_p->occurence_stack_last_p; 882425bb815Sopenharmony_ci stack_item.object_p = obj_p; 883425bb815Sopenharmony_ci context_p->occurence_stack_last_p = &stack_item; 884425bb815Sopenharmony_ci 885425bb815Sopenharmony_ci /* 3. - 4.*/ 886425bb815Sopenharmony_ci const lit_utf8_size_t stepback_size = ecma_stringbuilder_get_size (&context_p->indent_builder); 887425bb815Sopenharmony_ci ecma_stringbuilder_append (&context_p->indent_builder, context_p->gap_str_p); 888425bb815Sopenharmony_ci 889425bb815Sopenharmony_ci const bool has_gap = !ecma_compare_ecma_string_to_magic_id (context_p->gap_str_p, LIT_MAGIC_STRING__EMPTY); 890425bb815Sopenharmony_ci const lit_utf8_size_t separator_size = ecma_stringbuilder_get_size (&context_p->indent_builder); 891425bb815Sopenharmony_ci 892425bb815Sopenharmony_ci ecma_collection_t *property_keys_p; 893425bb815Sopenharmony_ci /* 5. */ 894425bb815Sopenharmony_ci if (context_p->property_list_p->item_count > 0) 895425bb815Sopenharmony_ci { 896425bb815Sopenharmony_ci property_keys_p = context_p->property_list_p; 897425bb815Sopenharmony_ci } 898425bb815Sopenharmony_ci /* 6. */ 899425bb815Sopenharmony_ci else 900425bb815Sopenharmony_ci { 901425bb815Sopenharmony_ci property_keys_p = ecma_op_object_get_property_names (obj_p, ECMA_LIST_ENUMERABLE); 902425bb815Sopenharmony_ci 903425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY) 904425bb815Sopenharmony_ci if (property_keys_p == NULL) 905425bb815Sopenharmony_ci { 906425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 907425bb815Sopenharmony_ci } 908425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */ 909425bb815Sopenharmony_ci } 910425bb815Sopenharmony_ci 911425bb815Sopenharmony_ci /* 8. */ 912425bb815Sopenharmony_ci ecma_value_t *buffer_p = property_keys_p->buffer_p; 913425bb815Sopenharmony_ci 914425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_LEFT_BRACE); 915425bb815Sopenharmony_ci const lit_utf8_size_t left_brace = ecma_stringbuilder_get_size (&context_p->result_builder); 916425bb815Sopenharmony_ci lit_utf8_size_t last_prop = left_brace; 917425bb815Sopenharmony_ci ecma_value_t result = ECMA_VALUE_EMPTY; 918425bb815Sopenharmony_ci 919425bb815Sopenharmony_ci for (uint32_t i = 0; i < property_keys_p->item_count; i++) 920425bb815Sopenharmony_ci { 921425bb815Sopenharmony_ci if (has_gap) 922425bb815Sopenharmony_ci { 923425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&context_p->result_builder, 924425bb815Sopenharmony_ci ecma_stringbuilder_get_data (&context_p->indent_builder), 925425bb815Sopenharmony_ci separator_size); 926425bb815Sopenharmony_ci } 927425bb815Sopenharmony_ci 928425bb815Sopenharmony_ci ecma_string_t *key_p = ecma_get_string_from_value (buffer_p[i]); 929425bb815Sopenharmony_ci ecma_builtin_json_quote (&context_p->result_builder, key_p); 930425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_COLON); 931425bb815Sopenharmony_ci 932425bb815Sopenharmony_ci /* 8.c.iii */ 933425bb815Sopenharmony_ci if (has_gap) 934425bb815Sopenharmony_ci { 935425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_SP); 936425bb815Sopenharmony_ci } 937425bb815Sopenharmony_ci 938425bb815Sopenharmony_ci result = ecma_builtin_json_serialize_property (context_p, obj_p, key_p); 939425bb815Sopenharmony_ci 940425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 941425bb815Sopenharmony_ci { 942425bb815Sopenharmony_ci goto cleanup; 943425bb815Sopenharmony_ci } 944425bb815Sopenharmony_ci 945425bb815Sopenharmony_ci /* 8.b */ 946425bb815Sopenharmony_ci if (!ecma_is_value_undefined (result)) 947425bb815Sopenharmony_ci { 948425bb815Sopenharmony_ci /* ecma_builtin_json_serialize_property already appended the result. */ 949425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_empty (result)); 950425bb815Sopenharmony_ci 951425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_COMMA); 952425bb815Sopenharmony_ci last_prop = ecma_stringbuilder_get_size (&context_p->result_builder); 953425bb815Sopenharmony_ci } 954425bb815Sopenharmony_ci else 955425bb815Sopenharmony_ci { 956425bb815Sopenharmony_ci /* The property should not be appended, we must backtrack. */ 957425bb815Sopenharmony_ci ecma_stringbuilder_revert (&context_p->result_builder, last_prop); 958425bb815Sopenharmony_ci } 959425bb815Sopenharmony_ci } 960425bb815Sopenharmony_ci 961425bb815Sopenharmony_ci if (last_prop != left_brace) 962425bb815Sopenharmony_ci { 963425bb815Sopenharmony_ci /* Remove the last comma. */ 964425bb815Sopenharmony_ci ecma_stringbuilder_revert (&context_p->result_builder, last_prop - 1); 965425bb815Sopenharmony_ci 966425bb815Sopenharmony_ci if (has_gap) 967425bb815Sopenharmony_ci { 968425bb815Sopenharmony_ci /* We appended at least one element, and have a separator, so must append the stepback. */ 969425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&context_p->result_builder, 970425bb815Sopenharmony_ci ecma_stringbuilder_get_data (&context_p->indent_builder), 971425bb815Sopenharmony_ci stepback_size); 972425bb815Sopenharmony_ci } 973425bb815Sopenharmony_ci } 974425bb815Sopenharmony_ci 975425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_RIGHT_BRACE); 976425bb815Sopenharmony_ci result = ECMA_VALUE_EMPTY; 977425bb815Sopenharmony_ci 978425bb815Sopenharmony_ci /* 11. */ 979425bb815Sopenharmony_ci context_p->occurence_stack_last_p = stack_item.next_p; 980425bb815Sopenharmony_ci 981425bb815Sopenharmony_ci /* 12. */ 982425bb815Sopenharmony_ci ecma_stringbuilder_revert (&context_p->indent_builder, stepback_size); 983425bb815Sopenharmony_ci 984425bb815Sopenharmony_cicleanup: 985425bb815Sopenharmony_ci if (context_p->property_list_p->item_count == 0) 986425bb815Sopenharmony_ci { 987425bb815Sopenharmony_ci ecma_collection_free (property_keys_p); 988425bb815Sopenharmony_ci } 989425bb815Sopenharmony_ci 990425bb815Sopenharmony_ci return result; 991425bb815Sopenharmony_ci} /* ecma_builtin_json_serialize_object */ 992425bb815Sopenharmony_ci 993425bb815Sopenharmony_ci/** 994425bb815Sopenharmony_ci * Abstract operation 'SerializeJSONArray' defined in 24.3.2.4 995425bb815Sopenharmony_ci * 996425bb815Sopenharmony_ci * @return ecma value 997425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 998425bb815Sopenharmony_ci */ 999425bb815Sopenharmony_cistatic ecma_value_t 1000425bb815Sopenharmony_ciecma_builtin_json_serialize_array (ecma_json_stringify_context_t *context_p, /**< context*/ 1001425bb815Sopenharmony_ci ecma_object_t *obj_p) /**< the array object*/ 1002425bb815Sopenharmony_ci{ 1003425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG 1004425bb815Sopenharmony_ci ecma_value_t obj_value = ecma_make_object_value (obj_p); 1005425bb815Sopenharmony_ci ecma_value_t is_array = ecma_is_value_array (obj_value); 1006425bb815Sopenharmony_ci 1007425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_true (is_array)); 1008425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */ 1009425bb815Sopenharmony_ci 1010425bb815Sopenharmony_ci /* 1. */ 1011425bb815Sopenharmony_ci if (ecma_json_has_object_in_stack (context_p->occurence_stack_last_p, obj_p)) 1012425bb815Sopenharmony_ci { 1013425bb815Sopenharmony_ci return ecma_raise_type_error (ECMA_ERR_MSG ("The structure is cyclical.")); 1014425bb815Sopenharmony_ci } 1015425bb815Sopenharmony_ci 1016425bb815Sopenharmony_ci /* 2. */ 1017425bb815Sopenharmony_ci ecma_json_occurence_stack_item_t stack_item; 1018425bb815Sopenharmony_ci stack_item.next_p = context_p->occurence_stack_last_p; 1019425bb815Sopenharmony_ci stack_item.object_p = obj_p; 1020425bb815Sopenharmony_ci context_p->occurence_stack_last_p = &stack_item; 1021425bb815Sopenharmony_ci 1022425bb815Sopenharmony_ci /* 3. - 4.*/ 1023425bb815Sopenharmony_ci const lit_utf8_size_t stepback_size = ecma_stringbuilder_get_size (&context_p->indent_builder); 1024425bb815Sopenharmony_ci ecma_stringbuilder_append (&context_p->indent_builder, context_p->gap_str_p); 1025425bb815Sopenharmony_ci const lit_utf8_size_t separator_size = ecma_stringbuilder_get_size (&context_p->indent_builder); 1026425bb815Sopenharmony_ci 1027425bb815Sopenharmony_ci const bool has_gap = !ecma_compare_ecma_string_to_magic_id (context_p->gap_str_p, LIT_MAGIC_STRING__EMPTY); 1028425bb815Sopenharmony_ci 1029425bb815Sopenharmony_ci /* 6. */ 1030425bb815Sopenharmony_ci uint32_t array_length; 1031425bb815Sopenharmony_ci 1032425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_BUILTIN_PROXY) 1033425bb815Sopenharmony_ci if (ECMA_OBJECT_IS_PROXY (obj_p)) 1034425bb815Sopenharmony_ci { 1035425bb815Sopenharmony_ci ecma_value_t length_value = ecma_op_object_get_length (obj_p, &array_length); 1036425bb815Sopenharmony_ci 1037425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (length_value)) 1038425bb815Sopenharmony_ci { 1039425bb815Sopenharmony_ci return length_value; 1040425bb815Sopenharmony_ci } 1041425bb815Sopenharmony_ci } 1042425bb815Sopenharmony_ci else 1043425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */ 1044425bb815Sopenharmony_ci { 1045425bb815Sopenharmony_ci array_length = ((ecma_extended_object_t *) obj_p)->u.array.length; 1046425bb815Sopenharmony_ci } 1047425bb815Sopenharmony_ci 1048425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_LEFT_SQUARE); 1049425bb815Sopenharmony_ci 1050425bb815Sopenharmony_ci const lit_utf8_size_t left_square = ecma_stringbuilder_get_size (&context_p->result_builder); 1051425bb815Sopenharmony_ci lit_utf8_size_t last_prop = left_square; 1052425bb815Sopenharmony_ci 1053425bb815Sopenharmony_ci /* 8. - 9. */ 1054425bb815Sopenharmony_ci for (uint32_t index = 0; index < array_length; index++) 1055425bb815Sopenharmony_ci { 1056425bb815Sopenharmony_ci /* 9.a */ 1057425bb815Sopenharmony_ci ecma_string_t *index_str_p = ecma_new_ecma_string_from_uint32 (index); 1058425bb815Sopenharmony_ci 1059425bb815Sopenharmony_ci if (has_gap) 1060425bb815Sopenharmony_ci { 1061425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&context_p->result_builder, 1062425bb815Sopenharmony_ci ecma_stringbuilder_get_data (&context_p->indent_builder), 1063425bb815Sopenharmony_ci separator_size); 1064425bb815Sopenharmony_ci } 1065425bb815Sopenharmony_ci 1066425bb815Sopenharmony_ci ecma_value_t result = ecma_builtin_json_serialize_property (context_p, obj_p, index_str_p); 1067425bb815Sopenharmony_ci ecma_deref_ecma_string (index_str_p); 1068425bb815Sopenharmony_ci 1069425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 1070425bb815Sopenharmony_ci { 1071425bb815Sopenharmony_ci return result; 1072425bb815Sopenharmony_ci } 1073425bb815Sopenharmony_ci 1074425bb815Sopenharmony_ci if (ecma_is_value_undefined (result)) 1075425bb815Sopenharmony_ci { 1076425bb815Sopenharmony_ci /* 9.c */ 1077425bb815Sopenharmony_ci ecma_stringbuilder_append_magic (&context_p->result_builder, LIT_MAGIC_STRING_NULL); 1078425bb815Sopenharmony_ci } 1079425bb815Sopenharmony_ci else 1080425bb815Sopenharmony_ci { 1081425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_empty (result)); 1082425bb815Sopenharmony_ci } 1083425bb815Sopenharmony_ci 1084425bb815Sopenharmony_ci last_prop = ecma_stringbuilder_get_size (&context_p->result_builder); 1085425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_COMMA); 1086425bb815Sopenharmony_ci } 1087425bb815Sopenharmony_ci 1088425bb815Sopenharmony_ci /* Remove the last comma. */ 1089425bb815Sopenharmony_ci ecma_stringbuilder_revert (&context_p->result_builder, last_prop); 1090425bb815Sopenharmony_ci 1091425bb815Sopenharmony_ci /* 11.b.iii */ 1092425bb815Sopenharmony_ci if (last_prop != left_square && has_gap) 1093425bb815Sopenharmony_ci { 1094425bb815Sopenharmony_ci /* We appended at least one element, and have a separator, so must append the stepback. */ 1095425bb815Sopenharmony_ci ecma_stringbuilder_append_raw (&context_p->result_builder, 1096425bb815Sopenharmony_ci ecma_stringbuilder_get_data (&context_p->indent_builder), 1097425bb815Sopenharmony_ci stepback_size); 1098425bb815Sopenharmony_ci } 1099425bb815Sopenharmony_ci 1100425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->result_builder, LIT_CHAR_RIGHT_SQUARE); 1101425bb815Sopenharmony_ci 1102425bb815Sopenharmony_ci /* 12. */ 1103425bb815Sopenharmony_ci context_p->occurence_stack_last_p = stack_item.next_p; 1104425bb815Sopenharmony_ci 1105425bb815Sopenharmony_ci /* 13. */ 1106425bb815Sopenharmony_ci ecma_stringbuilder_revert (&context_p->indent_builder, stepback_size); 1107425bb815Sopenharmony_ci 1108425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 1109425bb815Sopenharmony_ci} /* ecma_builtin_json_serialize_array */ 1110425bb815Sopenharmony_ci 1111425bb815Sopenharmony_ci/** 1112425bb815Sopenharmony_ci * Abstract operation 'SerializeJSONProperty' defined in 24.3.2.1 1113425bb815Sopenharmony_ci * 1114425bb815Sopenharmony_ci * @return ecma value 1115425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 1116425bb815Sopenharmony_ci */ 1117425bb815Sopenharmony_cistatic ecma_value_t 1118425bb815Sopenharmony_ciecma_builtin_json_serialize_property (ecma_json_stringify_context_t *context_p, /**< context*/ 1119425bb815Sopenharmony_ci ecma_object_t *holder_p, /**< the object*/ 1120425bb815Sopenharmony_ci ecma_string_t *key_p) /**< property key*/ 1121425bb815Sopenharmony_ci{ 1122425bb815Sopenharmony_ci /* 1. */ 1123425bb815Sopenharmony_ci ecma_value_t value = ecma_op_object_get (holder_p, key_p); 1124425bb815Sopenharmony_ci 1125425bb815Sopenharmony_ci /* 2. */ 1126425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (value)) 1127425bb815Sopenharmony_ci { 1128425bb815Sopenharmony_ci return value; 1129425bb815Sopenharmony_ci } 1130425bb815Sopenharmony_ci 1131425bb815Sopenharmony_ci /* 3. */ 1132425bb815Sopenharmony_ci if (ecma_is_value_object (value)) 1133425bb815Sopenharmony_ci { 1134425bb815Sopenharmony_ci ecma_object_t *value_obj_p = ecma_get_object_from_value (value); 1135425bb815Sopenharmony_ci 1136425bb815Sopenharmony_ci ecma_value_t to_json = ecma_op_object_get_by_magic_id (value_obj_p, LIT_MAGIC_STRING_TO_JSON_UL); 1137425bb815Sopenharmony_ci 1138425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (to_json)) 1139425bb815Sopenharmony_ci { 1140425bb815Sopenharmony_ci ecma_deref_object (value_obj_p); 1141425bb815Sopenharmony_ci return to_json; 1142425bb815Sopenharmony_ci } 1143425bb815Sopenharmony_ci 1144425bb815Sopenharmony_ci /* 3.c */ 1145425bb815Sopenharmony_ci if (ecma_op_is_callable (to_json)) 1146425bb815Sopenharmony_ci { 1147425bb815Sopenharmony_ci ecma_value_t key_value = ecma_make_string_value (key_p); 1148425bb815Sopenharmony_ci ecma_value_t call_args[] = { key_value }; 1149425bb815Sopenharmony_ci ecma_object_t *to_json_obj_p = ecma_get_object_from_value (to_json); 1150425bb815Sopenharmony_ci 1151425bb815Sopenharmony_ci ecma_value_t result = ecma_op_function_call (to_json_obj_p, value, call_args, 1); 1152425bb815Sopenharmony_ci ecma_deref_object (value_obj_p); 1153425bb815Sopenharmony_ci 1154425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 1155425bb815Sopenharmony_ci { 1156425bb815Sopenharmony_ci ecma_deref_object (to_json_obj_p); 1157425bb815Sopenharmony_ci return result; 1158425bb815Sopenharmony_ci } 1159425bb815Sopenharmony_ci 1160425bb815Sopenharmony_ci value = result; 1161425bb815Sopenharmony_ci } 1162425bb815Sopenharmony_ci ecma_free_value (to_json); 1163425bb815Sopenharmony_ci } 1164425bb815Sopenharmony_ci 1165425bb815Sopenharmony_ci /* 4. */ 1166425bb815Sopenharmony_ci if (context_p->replacer_function_p) 1167425bb815Sopenharmony_ci { 1168425bb815Sopenharmony_ci ecma_value_t holder_value = ecma_make_object_value (holder_p); 1169425bb815Sopenharmony_ci ecma_value_t key_value = ecma_make_string_value (key_p); 1170425bb815Sopenharmony_ci ecma_value_t call_args[] = { key_value, value }; 1171425bb815Sopenharmony_ci 1172425bb815Sopenharmony_ci ecma_value_t result = ecma_op_function_call (context_p->replacer_function_p, holder_value, call_args, 2); 1173425bb815Sopenharmony_ci ecma_free_value (value); 1174425bb815Sopenharmony_ci 1175425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (result)) 1176425bb815Sopenharmony_ci { 1177425bb815Sopenharmony_ci return result; 1178425bb815Sopenharmony_ci } 1179425bb815Sopenharmony_ci 1180425bb815Sopenharmony_ci value = result; 1181425bb815Sopenharmony_ci } 1182425bb815Sopenharmony_ci 1183425bb815Sopenharmony_ci /* 5. */ 1184425bb815Sopenharmony_ci if (ecma_is_value_object (value)) 1185425bb815Sopenharmony_ci { 1186425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (value); 1187425bb815Sopenharmony_ci lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); 1188425bb815Sopenharmony_ci 1189425bb815Sopenharmony_ci /* 5.a */ 1190425bb815Sopenharmony_ci if (class_name == LIT_MAGIC_STRING_NUMBER_UL) 1191425bb815Sopenharmony_ci { 1192425bb815Sopenharmony_ci value = ecma_op_to_number (value); 1193425bb815Sopenharmony_ci ecma_deref_object (obj_p); 1194425bb815Sopenharmony_ci 1195425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (value)) 1196425bb815Sopenharmony_ci { 1197425bb815Sopenharmony_ci return value; 1198425bb815Sopenharmony_ci } 1199425bb815Sopenharmony_ci } 1200425bb815Sopenharmony_ci /* 5.b */ 1201425bb815Sopenharmony_ci else if (class_name == LIT_MAGIC_STRING_STRING_UL) 1202425bb815Sopenharmony_ci { 1203425bb815Sopenharmony_ci ecma_string_t *str_p = ecma_op_to_string (value); 1204425bb815Sopenharmony_ci ecma_deref_object (obj_p); 1205425bb815Sopenharmony_ci 1206425bb815Sopenharmony_ci if (JERRY_UNLIKELY (str_p == NULL)) 1207425bb815Sopenharmony_ci { 1208425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 1209425bb815Sopenharmony_ci } 1210425bb815Sopenharmony_ci 1211425bb815Sopenharmony_ci value = ecma_make_string_value (str_p); 1212425bb815Sopenharmony_ci } 1213425bb815Sopenharmony_ci /* 5.c */ 1214425bb815Sopenharmony_ci else if (class_name == LIT_MAGIC_STRING_BOOLEAN_UL) 1215425bb815Sopenharmony_ci { 1216425bb815Sopenharmony_ci ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p; 1217425bb815Sopenharmony_ci value = ext_object_p->u.class_prop.u.value; 1218425bb815Sopenharmony_ci ecma_deref_object (obj_p); 1219425bb815Sopenharmony_ci } 1220425bb815Sopenharmony_ci } 1221425bb815Sopenharmony_ci 1222425bb815Sopenharmony_ci /* 6. - 8. */ 1223425bb815Sopenharmony_ci if (ecma_is_value_null (value)) 1224425bb815Sopenharmony_ci { 1225425bb815Sopenharmony_ci ecma_stringbuilder_append_magic (&context_p->result_builder, LIT_MAGIC_STRING_NULL); 1226425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 1227425bb815Sopenharmony_ci } 1228425bb815Sopenharmony_ci 1229425bb815Sopenharmony_ci if (ecma_is_value_true (value)) 1230425bb815Sopenharmony_ci { 1231425bb815Sopenharmony_ci ecma_stringbuilder_append_magic (&context_p->result_builder, LIT_MAGIC_STRING_TRUE); 1232425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 1233425bb815Sopenharmony_ci } 1234425bb815Sopenharmony_ci 1235425bb815Sopenharmony_ci if (ecma_is_value_false (value)) 1236425bb815Sopenharmony_ci { 1237425bb815Sopenharmony_ci ecma_stringbuilder_append_magic (&context_p->result_builder, LIT_MAGIC_STRING_FALSE); 1238425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 1239425bb815Sopenharmony_ci } 1240425bb815Sopenharmony_ci 1241425bb815Sopenharmony_ci /* 9. */ 1242425bb815Sopenharmony_ci if (ecma_is_value_string (value)) 1243425bb815Sopenharmony_ci { 1244425bb815Sopenharmony_ci ecma_string_t *value_str_p = ecma_get_string_from_value (value); 1245425bb815Sopenharmony_ci /* Quote will append the result. */ 1246425bb815Sopenharmony_ci ecma_builtin_json_quote (&context_p->result_builder, value_str_p); 1247425bb815Sopenharmony_ci ecma_deref_ecma_string (value_str_p); 1248425bb815Sopenharmony_ci 1249425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 1250425bb815Sopenharmony_ci } 1251425bb815Sopenharmony_ci 1252425bb815Sopenharmony_ci /* 10. */ 1253425bb815Sopenharmony_ci if (ecma_is_value_number (value)) 1254425bb815Sopenharmony_ci { 1255425bb815Sopenharmony_ci ecma_number_t num_value = ecma_get_number_from_value (value); 1256425bb815Sopenharmony_ci 1257425bb815Sopenharmony_ci /* 10.a */ 1258425bb815Sopenharmony_ci if (!ecma_number_is_nan (num_value) && !ecma_number_is_infinity (num_value)) 1259425bb815Sopenharmony_ci { 1260425bb815Sopenharmony_ci ecma_string_t *result_string_p = ecma_op_to_string (value); 1261425bb815Sopenharmony_ci JERRY_ASSERT (result_string_p != NULL); 1262425bb815Sopenharmony_ci 1263425bb815Sopenharmony_ci ecma_stringbuilder_append (&context_p->result_builder, result_string_p); 1264425bb815Sopenharmony_ci ecma_deref_ecma_string (result_string_p); 1265425bb815Sopenharmony_ci } 1266425bb815Sopenharmony_ci else 1267425bb815Sopenharmony_ci { 1268425bb815Sopenharmony_ci /* 10.b */ 1269425bb815Sopenharmony_ci ecma_stringbuilder_append_magic (&context_p->result_builder, LIT_MAGIC_STRING_NULL); 1270425bb815Sopenharmony_ci } 1271425bb815Sopenharmony_ci 1272425bb815Sopenharmony_ci ecma_free_value (value); 1273425bb815Sopenharmony_ci return ECMA_VALUE_EMPTY; 1274425bb815Sopenharmony_ci } 1275425bb815Sopenharmony_ci 1276425bb815Sopenharmony_ci /* 11. */ 1277425bb815Sopenharmony_ci if (ecma_is_value_object (value) && !ecma_op_is_callable (value)) 1278425bb815Sopenharmony_ci { 1279425bb815Sopenharmony_ci ecma_value_t is_array = ecma_is_value_array (value); 1280425bb815Sopenharmony_ci 1281425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015) 1282425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (is_array)) 1283425bb815Sopenharmony_ci { 1284425bb815Sopenharmony_ci ecma_free_value (value); 1285425bb815Sopenharmony_ci return is_array; 1286425bb815Sopenharmony_ci } 1287425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */ 1288425bb815Sopenharmony_ci 1289425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (value); 1290425bb815Sopenharmony_ci 1291425bb815Sopenharmony_ci ecma_value_t ret_value; 1292425bb815Sopenharmony_ci /* 10.a */ 1293425bb815Sopenharmony_ci if (ecma_is_value_true (is_array)) 1294425bb815Sopenharmony_ci { 1295425bb815Sopenharmony_ci ret_value = ecma_builtin_json_serialize_array (context_p, obj_p); 1296425bb815Sopenharmony_ci } 1297425bb815Sopenharmony_ci /* 10.b */ 1298425bb815Sopenharmony_ci else 1299425bb815Sopenharmony_ci { 1300425bb815Sopenharmony_ci ret_value = ecma_builtin_json_serialize_object (context_p, obj_p); 1301425bb815Sopenharmony_ci } 1302425bb815Sopenharmony_ci 1303425bb815Sopenharmony_ci ecma_deref_object (obj_p); 1304425bb815Sopenharmony_ci return ret_value; 1305425bb815Sopenharmony_ci } 1306425bb815Sopenharmony_ci 1307425bb815Sopenharmony_ci /* 12. */ 1308425bb815Sopenharmony_ci ecma_free_value (value); 1309425bb815Sopenharmony_ci return ECMA_VALUE_UNDEFINED; 1310425bb815Sopenharmony_ci} /* ecma_builtin_json_serialize_property */ 1311425bb815Sopenharmony_ci 1312425bb815Sopenharmony_ci/** 1313425bb815Sopenharmony_ci * Helper function to stringify an object in JSON format representing an ecma_value. 1314425bb815Sopenharmony_ci * 1315425bb815Sopenharmony_ci * @return ecma_value_t string created from an abject formating by a given context 1316425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 1317425bb815Sopenharmony_ci * 1318425bb815Sopenharmony_ci */ 1319425bb815Sopenharmony_cistatic ecma_value_t ecma_builtin_json_str_helper (ecma_json_stringify_context_t *context_p, /**< context argument */ 1320425bb815Sopenharmony_ci const ecma_value_t arg1) /**< object argument */ 1321425bb815Sopenharmony_ci{ 1322425bb815Sopenharmony_ci ecma_value_t ret_value = ECMA_VALUE_EMPTY; 1323425bb815Sopenharmony_ci ecma_object_t *obj_wrapper_p = ecma_op_create_object_object_noarg (); 1324425bb815Sopenharmony_ci ecma_string_t *empty_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); 1325425bb815Sopenharmony_ci ecma_value_t put_comp_val = ecma_builtin_helper_def_prop (obj_wrapper_p, 1326425bb815Sopenharmony_ci empty_str_p, 1327425bb815Sopenharmony_ci arg1, 1328425bb815Sopenharmony_ci ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE); 1329425bb815Sopenharmony_ci 1330425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_true (put_comp_val)); 1331425bb815Sopenharmony_ci 1332425bb815Sopenharmony_ci context_p->result_builder = ecma_stringbuilder_create (); 1333425bb815Sopenharmony_ci 1334425bb815Sopenharmony_ci if (!ecma_compare_ecma_string_to_magic_id (context_p->gap_str_p, LIT_MAGIC_STRING__EMPTY)) 1335425bb815Sopenharmony_ci { 1336425bb815Sopenharmony_ci ecma_stringbuilder_append_byte (&context_p->indent_builder, LIT_CHAR_LF); 1337425bb815Sopenharmony_ci } 1338425bb815Sopenharmony_ci 1339425bb815Sopenharmony_ci ret_value = ecma_builtin_json_serialize_property (context_p, obj_wrapper_p, empty_str_p); 1340425bb815Sopenharmony_ci ecma_deref_object (obj_wrapper_p); 1341425bb815Sopenharmony_ci 1342425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (ret_value) || ecma_is_value_undefined (ret_value)) 1343425bb815Sopenharmony_ci { 1344425bb815Sopenharmony_ci ecma_stringbuilder_destroy (&context_p->result_builder); 1345425bb815Sopenharmony_ci return ret_value; 1346425bb815Sopenharmony_ci } 1347425bb815Sopenharmony_ci 1348425bb815Sopenharmony_ci return ecma_make_string_value (ecma_stringbuilder_finalize (&context_p->result_builder)); 1349425bb815Sopenharmony_ci} /* ecma_builtin_json_str_helper */ 1350425bb815Sopenharmony_ci 1351425bb815Sopenharmony_ci/** 1352425bb815Sopenharmony_ci * Function to create a json formated string from an object 1353425bb815Sopenharmony_ci * 1354425bb815Sopenharmony_ci * @return ecma_value_t containing a json string 1355425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 1356425bb815Sopenharmony_ci */ 1357425bb815Sopenharmony_ciecma_value_t 1358425bb815Sopenharmony_ciecma_builtin_json_string_from_object (const ecma_value_t arg1) /**< object argument */ 1359425bb815Sopenharmony_ci{ 1360425bb815Sopenharmony_ci ecma_json_stringify_context_t context; 1361425bb815Sopenharmony_ci context.occurence_stack_last_p = NULL; 1362425bb815Sopenharmony_ci context.indent_builder = ecma_stringbuilder_create (); 1363425bb815Sopenharmony_ci context.property_list_p = ecma_new_collection (); 1364425bb815Sopenharmony_ci context.replacer_function_p = NULL; 1365425bb815Sopenharmony_ci context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); 1366425bb815Sopenharmony_ci 1367425bb815Sopenharmony_ci ecma_value_t ret_value = ecma_builtin_json_str_helper (&context, arg1); 1368425bb815Sopenharmony_ci 1369425bb815Sopenharmony_ci ecma_deref_ecma_string (context.gap_str_p); 1370425bb815Sopenharmony_ci ecma_stringbuilder_destroy (&context.indent_builder); 1371425bb815Sopenharmony_ci ecma_collection_free (context.property_list_p); 1372425bb815Sopenharmony_ci return ret_value; 1373425bb815Sopenharmony_ci} /*ecma_builtin_json_string_from_object*/ 1374425bb815Sopenharmony_ci 1375425bb815Sopenharmony_ci/** 1376425bb815Sopenharmony_ci * The JSON object's 'stringify' routine 1377425bb815Sopenharmony_ci * 1378425bb815Sopenharmony_ci * See also: 1379425bb815Sopenharmony_ci * ECMA-262 v5, 15.12.3 1380425bb815Sopenharmony_ci * 1381425bb815Sopenharmony_ci * @return ecma value 1382425bb815Sopenharmony_ci * Returned value must be freed with ecma_free_value. 1383425bb815Sopenharmony_ci */ 1384425bb815Sopenharmony_cistatic ecma_value_t 1385425bb815Sopenharmony_ciecma_builtin_json_stringify (ecma_value_t this_arg, /**< 'this' argument */ 1386425bb815Sopenharmony_ci ecma_value_t arg1, /**< value */ 1387425bb815Sopenharmony_ci ecma_value_t arg2, /**< replacer */ 1388425bb815Sopenharmony_ci ecma_value_t arg3) /**< space */ 1389425bb815Sopenharmony_ci{ 1390425bb815Sopenharmony_ci JERRY_UNUSED (this_arg); 1391425bb815Sopenharmony_ci 1392425bb815Sopenharmony_ci ecma_json_stringify_context_t context; 1393425bb815Sopenharmony_ci context.replacer_function_p = NULL; 1394425bb815Sopenharmony_ci context.property_list_p = ecma_new_collection (); 1395425bb815Sopenharmony_ci 1396425bb815Sopenharmony_ci /* 4. */ 1397425bb815Sopenharmony_ci if (ecma_is_value_object (arg2)) 1398425bb815Sopenharmony_ci { 1399425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (arg2); 1400425bb815Sopenharmony_ci 1401425bb815Sopenharmony_ci /* 4.a */ 1402425bb815Sopenharmony_ci if (ecma_op_is_callable (arg2)) 1403425bb815Sopenharmony_ci { 1404425bb815Sopenharmony_ci context.replacer_function_p = obj_p; 1405425bb815Sopenharmony_ci } 1406425bb815Sopenharmony_ci /* 4.b */ 1407425bb815Sopenharmony_ci else if (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_ARRAY) 1408425bb815Sopenharmony_ci { 1409425bb815Sopenharmony_ci ecma_extended_object_t *array_object_p = (ecma_extended_object_t *) obj_p; 1410425bb815Sopenharmony_ci uint32_t array_length = array_object_p->u.array.length; 1411425bb815Sopenharmony_ci uint32_t index = 0; 1412425bb815Sopenharmony_ci 1413425bb815Sopenharmony_ci /* 4.b.iii.5 */ 1414425bb815Sopenharmony_ci while (index < array_length) 1415425bb815Sopenharmony_ci { 1416425bb815Sopenharmony_ci ecma_value_t value = ecma_op_object_get_by_uint32_index (obj_p, index); 1417425bb815Sopenharmony_ci 1418425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (value)) 1419425bb815Sopenharmony_ci { 1420425bb815Sopenharmony_ci ecma_collection_free (context.property_list_p); 1421425bb815Sopenharmony_ci return value; 1422425bb815Sopenharmony_ci } 1423425bb815Sopenharmony_ci 1424425bb815Sopenharmony_ci /* 4.b.iii.5.c */ 1425425bb815Sopenharmony_ci ecma_value_t item = ECMA_VALUE_UNDEFINED; 1426425bb815Sopenharmony_ci 1427425bb815Sopenharmony_ci /* 4.b.iii.5.d */ 1428425bb815Sopenharmony_ci if (ecma_is_value_string (value)) 1429425bb815Sopenharmony_ci { 1430425bb815Sopenharmony_ci ecma_ref_ecma_string (ecma_get_string_from_value (value)); 1431425bb815Sopenharmony_ci item = value; 1432425bb815Sopenharmony_ci } 1433425bb815Sopenharmony_ci /* 4.b.iii.5.e */ 1434425bb815Sopenharmony_ci else if (ecma_is_value_number (value)) 1435425bb815Sopenharmony_ci { 1436425bb815Sopenharmony_ci ecma_string_t *number_str_p = ecma_op_to_string (value); 1437425bb815Sopenharmony_ci JERRY_ASSERT (number_str_p != NULL); 1438425bb815Sopenharmony_ci item = ecma_make_string_value (number_str_p); 1439425bb815Sopenharmony_ci } 1440425bb815Sopenharmony_ci /* 4.b.iii.5.f */ 1441425bb815Sopenharmony_ci else if (ecma_is_value_object (value)) 1442425bb815Sopenharmony_ci { 1443425bb815Sopenharmony_ci ecma_object_t *value_obj_p = ecma_get_object_from_value (value); 1444425bb815Sopenharmony_ci lit_magic_string_id_t class_id = ecma_object_get_class_name (value_obj_p); 1445425bb815Sopenharmony_ci 1446425bb815Sopenharmony_ci if (class_id == LIT_MAGIC_STRING_NUMBER_UL || class_id == LIT_MAGIC_STRING_STRING_UL) 1447425bb815Sopenharmony_ci { 1448425bb815Sopenharmony_ci ecma_string_t *str_p = ecma_op_to_string (value); 1449425bb815Sopenharmony_ci 1450425bb815Sopenharmony_ci if (JERRY_UNLIKELY (str_p == NULL)) 1451425bb815Sopenharmony_ci { 1452425bb815Sopenharmony_ci ecma_collection_free (context.property_list_p); 1453425bb815Sopenharmony_ci ecma_free_value (value); 1454425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 1455425bb815Sopenharmony_ci } 1456425bb815Sopenharmony_ci 1457425bb815Sopenharmony_ci item = ecma_make_string_value (str_p); 1458425bb815Sopenharmony_ci } 1459425bb815Sopenharmony_ci } 1460425bb815Sopenharmony_ci 1461425bb815Sopenharmony_ci ecma_free_value (value); 1462425bb815Sopenharmony_ci 1463425bb815Sopenharmony_ci /* 4.b.iii.5.g */ 1464425bb815Sopenharmony_ci if (!ecma_is_value_undefined (item)) 1465425bb815Sopenharmony_ci { 1466425bb815Sopenharmony_ci JERRY_ASSERT (ecma_is_value_string (item)); 1467425bb815Sopenharmony_ci ecma_string_t *string_p = ecma_get_string_from_value (item); 1468425bb815Sopenharmony_ci 1469425bb815Sopenharmony_ci if (!ecma_has_string_value_in_collection (context.property_list_p, string_p)) 1470425bb815Sopenharmony_ci { 1471425bb815Sopenharmony_ci ecma_collection_push_back (context.property_list_p, item); 1472425bb815Sopenharmony_ci } 1473425bb815Sopenharmony_ci else 1474425bb815Sopenharmony_ci { 1475425bb815Sopenharmony_ci ecma_deref_ecma_string (string_p); 1476425bb815Sopenharmony_ci } 1477425bb815Sopenharmony_ci } 1478425bb815Sopenharmony_ci 1479425bb815Sopenharmony_ci index++; 1480425bb815Sopenharmony_ci } 1481425bb815Sopenharmony_ci } 1482425bb815Sopenharmony_ci } 1483425bb815Sopenharmony_ci 1484425bb815Sopenharmony_ci ecma_value_t space; 1485425bb815Sopenharmony_ci 1486425bb815Sopenharmony_ci /* 5. */ 1487425bb815Sopenharmony_ci if (ecma_is_value_object (arg3)) 1488425bb815Sopenharmony_ci { 1489425bb815Sopenharmony_ci ecma_object_t *obj_p = ecma_get_object_from_value (arg3); 1490425bb815Sopenharmony_ci lit_magic_string_id_t class_name = ecma_object_get_class_name (obj_p); 1491425bb815Sopenharmony_ci 1492425bb815Sopenharmony_ci /* 5.a */ 1493425bb815Sopenharmony_ci if (class_name == LIT_MAGIC_STRING_NUMBER_UL) 1494425bb815Sopenharmony_ci { 1495425bb815Sopenharmony_ci ecma_value_t value = ecma_op_to_number (arg3); 1496425bb815Sopenharmony_ci 1497425bb815Sopenharmony_ci if (ECMA_IS_VALUE_ERROR (value)) 1498425bb815Sopenharmony_ci { 1499425bb815Sopenharmony_ci ecma_collection_free (context.property_list_p); 1500425bb815Sopenharmony_ci return value; 1501425bb815Sopenharmony_ci } 1502425bb815Sopenharmony_ci 1503425bb815Sopenharmony_ci space = value; 1504425bb815Sopenharmony_ci } 1505425bb815Sopenharmony_ci /* 5.b */ 1506425bb815Sopenharmony_ci else if (class_name == LIT_MAGIC_STRING_STRING_UL) 1507425bb815Sopenharmony_ci { 1508425bb815Sopenharmony_ci ecma_string_t *value_str_p = ecma_op_to_string (arg3); 1509425bb815Sopenharmony_ci 1510425bb815Sopenharmony_ci if (JERRY_UNLIKELY (value_str_p == NULL)) 1511425bb815Sopenharmony_ci { 1512425bb815Sopenharmony_ci ecma_collection_free (context.property_list_p); 1513425bb815Sopenharmony_ci return ECMA_VALUE_ERROR; 1514425bb815Sopenharmony_ci } 1515425bb815Sopenharmony_ci 1516425bb815Sopenharmony_ci space = ecma_make_string_value (value_str_p); 1517425bb815Sopenharmony_ci } 1518425bb815Sopenharmony_ci else 1519425bb815Sopenharmony_ci { 1520425bb815Sopenharmony_ci space = ecma_copy_value (arg3); 1521425bb815Sopenharmony_ci } 1522425bb815Sopenharmony_ci } 1523425bb815Sopenharmony_ci else 1524425bb815Sopenharmony_ci { 1525425bb815Sopenharmony_ci space = ecma_copy_value (arg3); 1526425bb815Sopenharmony_ci } 1527425bb815Sopenharmony_ci 1528425bb815Sopenharmony_ci /* 6. */ 1529425bb815Sopenharmony_ci if (ecma_is_value_number (space)) 1530425bb815Sopenharmony_ci { 1531425bb815Sopenharmony_ci /* 6.a */ 1532425bb815Sopenharmony_ci ecma_number_t num_of_spaces; 1533425bb815Sopenharmony_ci ecma_op_to_integer (space, &num_of_spaces); 1534425bb815Sopenharmony_ci 1535425bb815Sopenharmony_ci num_of_spaces = JERRY_MIN (10, num_of_spaces); 1536425bb815Sopenharmony_ci 1537425bb815Sopenharmony_ci /* 6.b */ 1538425bb815Sopenharmony_ci if (num_of_spaces < 1) 1539425bb815Sopenharmony_ci { 1540425bb815Sopenharmony_ci context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); 1541425bb815Sopenharmony_ci } 1542425bb815Sopenharmony_ci else 1543425bb815Sopenharmony_ci { 1544425bb815Sopenharmony_ci JMEM_DEFINE_LOCAL_ARRAY (space_buff, num_of_spaces, char); 1545425bb815Sopenharmony_ci 1546425bb815Sopenharmony_ci memset (space_buff, LIT_CHAR_SP, (size_t) num_of_spaces); 1547425bb815Sopenharmony_ci context.gap_str_p = ecma_new_ecma_string_from_utf8 ((lit_utf8_byte_t *) space_buff, 1548425bb815Sopenharmony_ci (lit_utf8_size_t) num_of_spaces); 1549425bb815Sopenharmony_ci 1550425bb815Sopenharmony_ci JMEM_FINALIZE_LOCAL_ARRAY (space_buff); 1551425bb815Sopenharmony_ci } 1552425bb815Sopenharmony_ci } 1553425bb815Sopenharmony_ci /* 7. */ 1554425bb815Sopenharmony_ci else if (ecma_is_value_string (space)) 1555425bb815Sopenharmony_ci { 1556425bb815Sopenharmony_ci ecma_string_t *space_str_p = ecma_get_string_from_value (space); 1557425bb815Sopenharmony_ci ecma_length_t num_of_chars = ecma_string_get_length (space_str_p); 1558425bb815Sopenharmony_ci 1559425bb815Sopenharmony_ci if (num_of_chars < 10) 1560425bb815Sopenharmony_ci { 1561425bb815Sopenharmony_ci ecma_ref_ecma_string (space_str_p); 1562425bb815Sopenharmony_ci context.gap_str_p = space_str_p; 1563425bb815Sopenharmony_ci } 1564425bb815Sopenharmony_ci else 1565425bb815Sopenharmony_ci { 1566425bb815Sopenharmony_ci context.gap_str_p = ecma_string_substr (space_str_p, 0, 10); 1567425bb815Sopenharmony_ci } 1568425bb815Sopenharmony_ci } 1569425bb815Sopenharmony_ci /* 8. */ 1570425bb815Sopenharmony_ci else 1571425bb815Sopenharmony_ci { 1572425bb815Sopenharmony_ci context.gap_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY); 1573425bb815Sopenharmony_ci } 1574425bb815Sopenharmony_ci 1575425bb815Sopenharmony_ci ecma_free_value (space); 1576425bb815Sopenharmony_ci 1577425bb815Sopenharmony_ci /* 1., 2., 3. */ 1578425bb815Sopenharmony_ci context.occurence_stack_last_p = NULL; 1579425bb815Sopenharmony_ci context.indent_builder = ecma_stringbuilder_create (); 1580425bb815Sopenharmony_ci 1581425bb815Sopenharmony_ci /* 9. */ 1582425bb815Sopenharmony_ci ecma_value_t ret_value = ecma_builtin_json_str_helper (&context, arg1); 1583425bb815Sopenharmony_ci 1584425bb815Sopenharmony_ci ecma_deref_ecma_string (context.gap_str_p); 1585425bb815Sopenharmony_ci ecma_stringbuilder_destroy (&context.indent_builder); 1586425bb815Sopenharmony_ci ecma_collection_free (context.property_list_p); 1587425bb815Sopenharmony_ci 1588425bb815Sopenharmony_ci return ret_value; 1589425bb815Sopenharmony_ci} /* ecma_builtin_json_stringify */ 1590425bb815Sopenharmony_ci 1591425bb815Sopenharmony_ci/** 1592425bb815Sopenharmony_ci * @} 1593425bb815Sopenharmony_ci * @} 1594425bb815Sopenharmony_ci * @} 1595425bb815Sopenharmony_ci */ 1596425bb815Sopenharmony_ci 1597425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_BUILTIN_JSON) */ 1598