@@ -1329,6 +1329,122 @@ ecma_builtin_global_object_escape (ecma_value_t this_arg __attr_unused___, /**<
13291329 return ret_value;
13301330} /* ecma_builtin_global_object_escape */
13311331
1332+ /* *
1333+ * The Global object's 'unescape' routine
1334+ *
1335+ * See also:
1336+ * ECMA-262 v5, B.2.2
1337+ *
1338+ * @return completion value
1339+ * Returned value must be freed with ecma_free_completion_value.
1340+ */
1341+ static ecma_completion_value_t
1342+ ecma_builtin_global_object_unescape (ecma_value_t this_arg __attr_unused___, /* *< this argument */
1343+ ecma_value_t arg) /* *< routine's first argument */
1344+ {
1345+ ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
1346+
1347+ /* 1. */
1348+ ECMA_TRY_CATCH (string, ecma_op_to_string (arg), ret_value);
1349+ ecma_string_t *input_string_p = ecma_get_string_from_value (string);
1350+ /* 2. */
1351+ lit_utf8_size_t input_size = ecma_string_get_size (input_string_p);
1352+
1353+ /* 3. */
1354+ MEM_DEFINE_LOCAL_ARRAY (input_start_p, input_size, lit_utf8_byte_t );
1355+ ssize_t sz = ecma_string_to_utf8_string (input_string_p, input_start_p, (ssize_t ) (input_size));
1356+ JERRY_ASSERT (sz >= 0 );
1357+
1358+ lit_utf8_iterator_t iterator = lit_utf8_iterator_create (input_start_p, input_size);
1359+ /* 4. */
1360+ /* The length of input string is always greater than output string
1361+ * so we re-use the input string buffer.
1362+ * E.g. %xx is 3 byte long, and the maximum is 0xff, which encoded
1363+ * as 2 bytes in UTF8. Etc. */
1364+ lit_utf8_byte_t *output_char_p = input_start_p;
1365+
1366+ /* The state of parsing that tells us where we are in an escape pattern.
1367+ * 0 we are outside of pattern,
1368+ * 1 found '%', start of pattern,
1369+ * 2 found first hex digit of '%xy' pattern
1370+ * 3 found valid '%xy' pattern
1371+ * 4 found 'u', start of '%uwxyz' pattern
1372+ * 5-7 found hex digits of '%uwxyz' pattern
1373+ * 8 found valid '%uwxyz' pattern
1374+ */
1375+ uint8_t status = 0 ;
1376+ lit_code_point_t high_surrogate = 0 ;
1377+ lit_code_point_t hex_digits = 0 ;
1378+ /* 5. */
1379+ while (!lit_utf8_iterator_is_eos (&iterator))
1380+ {
1381+ /* 6. */
1382+ lit_code_point_t code_point = lit_utf8_iterator_read_next (&iterator);
1383+
1384+ /* 7-8. */
1385+ if (status == 0 && code_point == LIT_CHAR_PERCENT)
1386+ {
1387+ /* Found '%' char, start of escape sequence. */
1388+ status = 1 ;
1389+ }
1390+ /* 9-10. */
1391+ else if (status == 1 && code_point == LIT_CHAR_LOWERCASE_U)
1392+ {
1393+ /* Found 'u' char after '%'. */
1394+ status = 4 ;
1395+ }
1396+ else if (status > 0 && lit_char_is_hex_digit ((ecma_char_t ) code_point))
1397+ {
1398+ /* Found hexadecimal digit in escape sequence. */
1399+ hex_digits = hex_digits * 16 + lit_char_hex_to_int ((ecma_char_t ) code_point);
1400+ status++;
1401+ }
1402+
1403+ /* 11-17. Found valid '%uwxyz' or '%xy' escape. */
1404+ if (status == 8 || status == 3 )
1405+ {
1406+ output_char_p -= (status == 3 ) ? 2 : 5 ;
1407+ status = 0 ;
1408+ code_point = (ecma_char_t ) hex_digits;
1409+ hex_digits = 0 ;
1410+ }
1411+
1412+ /* Handle surrogate pairs. */
1413+ bool is_non_bmp_middle = iterator.buf_pos .is_non_bmp_middle ;
1414+ if (!high_surrogate && lit_is_code_unit_high_surrogate ((ecma_char_t ) code_point))
1415+ {
1416+ high_surrogate = code_point;
1417+
1418+ if (is_non_bmp_middle)
1419+ {
1420+ code_point = lit_utf8_iterator_read_next (&iterator);
1421+ }
1422+ }
1423+
1424+ if (high_surrogate && lit_is_code_unit_low_surrogate ((ecma_char_t ) code_point))
1425+ {
1426+ output_char_p -= is_non_bmp_middle ? 0 : 3 ;
1427+ code_point = lit_convert_surrogate_pair_to_code_point ((ecma_char_t ) high_surrogate,
1428+ (ecma_char_t ) code_point);
1429+ high_surrogate = 0 ;
1430+ }
1431+
1432+ /* Copying character. */
1433+ lit_utf8_size_t lit_size = lit_code_point_to_utf8 (code_point, output_char_p);
1434+ output_char_p += lit_size;
1435+ JERRY_ASSERT (output_char_p - input_start_p <= iterator.buf_pos .offset );
1436+ }
1437+
1438+ lit_utf8_size_t output_length = (lit_utf8_size_t ) (output_char_p - input_start_p);
1439+ ecma_string_t *output_string_p = ecma_new_ecma_string_from_utf8 (input_start_p, output_length);
1440+ ret_value = ecma_make_normal_completion_value (ecma_make_string_value (output_string_p));
1441+
1442+ MEM_FINALIZE_LOCAL_ARRAY (input_start_p);
1443+
1444+ ECMA_FINALIZE (string);
1445+ return ret_value;
1446+ } /* ecma_builtin_global_object_unescape */
1447+
13321448#endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_ANNEXB_BUILTIN */
13331449
13341450/* *
0 commit comments