Implement function.toString operation (#4752)

May increase the memory consumtpion heavily.

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg 2021-08-31 13:37:25 +02:00 committed by GitHub
parent 1c6b18ecdf
commit 6649940ea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1002 additions and 192 deletions

View File

@ -175,6 +175,8 @@ Possible compile time enabled feature types:
- JERRY_FEATURE_GLOBAL_THIS - GlobalThisValue support
- JERRY_FEATURE_PROMISE_CALLBACK - Promise callback support
- JERRY_FEATURE_MODULE - Module support
- JERRY_FEATURE_WEAKREF - WeakRef support
- JERRY_FEATURE_FUNCTION_TO_STRING - function toString support
*New in version 2.0*.
@ -183,7 +185,8 @@ Possible compile time enabled feature types:
*Changed in version 2.4*: Added `JERRY_FEATURE_BIGINT`, `JERRY_FEATURE_REALM` values.
*Changed in version [[NEXT_RELEASE]]*: Added `JERRY_FEATURE_VM_THROW`, `JERRY_FEATURE_GLOBAL_THIS`,
`JERRY_FEATURE_PROMISE_CALLBACK`, and `JERRY_FEATURE_MODULE` values.
`JERRY_FEATURE_PROMISE_CALLBACK`, and `JERRY_FEATURE_MODULE`,
`JERRY_FEATURE_WEAKREF`, and `JERRY_FEATURE_FUNCTION_TO_STRING` values.
## jerry_container_type_t

View File

@ -24,6 +24,7 @@ set(JERRY_DEBUGGER OFF CACHE BOOL "Enable JerryScrip
set(JERRY_ERROR_MESSAGES OFF CACHE BOOL "Enable error messages?")
set(JERRY_EXTERNAL_CONTEXT OFF CACHE BOOL "Enable external context?")
set(JERRY_PARSER ON CACHE BOOL "Enable javascript-parser?")
set(JERRY_FUNCTION_TO_STRING OFF CACHE BOOL "Enable function toString operation?")
set(JERRY_LINE_INFO OFF CACHE BOOL "Enable line info?")
set(JERRY_LOGGING OFF CACHE BOOL "Enable logging?")
set(JERRY_MEM_STATS OFF CACHE BOOL "Enable memory statistics?")
@ -83,6 +84,7 @@ message(STATUS "JERRY_DEBUGGER " ${JERRY_DEBUGGER})
message(STATUS "JERRY_ERROR_MESSAGES " ${JERRY_ERROR_MESSAGES})
message(STATUS "JERRY_EXTERNAL_CONTEXT " ${JERRY_EXTERNAL_CONTEXT})
message(STATUS "JERRY_PARSER " ${JERRY_PARSER})
message(STATUS "JERRY_FUNCTION_TO_STRING " ${JERRY_FUNCTION_TO_STRING})
message(STATUS "JERRY_LINE_INFO " ${JERRY_LINE_INFO})
message(STATUS "JERRY_LOGGING " ${JERRY_LOGGING} ${JERRY_LOGGING_MESSAGE})
message(STATUS "JERRY_MEM_STATS " ${JERRY_MEM_STATS})
@ -135,6 +137,7 @@ set(SOURCE_CORE_FILES
ecma/base/ecma-alloc.c
ecma/base/ecma-gc.c
ecma/base/ecma-errors.c
ecma/base/ecma-extended-info.c
ecma/base/ecma-helpers-collection.c
ecma/base/ecma-helpers-conversion.c
ecma/base/ecma-helpers-errol.c
@ -559,6 +562,9 @@ jerry_add_define01(JERRY_EXTERNAL_CONTEXT)
# JS-Parser
jerry_add_define01(JERRY_PARSER)
# JS function toString
jerry_add_define01(JERRY_FUNCTION_TO_STRING)
# JS line info
jerry_add_define01(JERRY_LINE_INFO)

View File

@ -979,8 +979,13 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
user_value = option_values_p->user_value;
}
uint32_t script_size = (user_value != ECMA_VALUE_EMPTY ? sizeof (cbc_script_user_t)
: sizeof (cbc_script_t));
size_t script_size = sizeof (cbc_script_t);
if (user_value != ECMA_VALUE_EMPTY)
{
script_size += sizeof (ecma_value_t);
}
cbc_script_t *script_p = jmem_heap_alloc_block (script_size);
CBC_SCRIPT_SET_TYPE (script_p, user_value, CBC_SCRIPT_REF_ONE);
@ -1003,6 +1008,10 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
script_p->resource_name = resource_name;
#endif /* JERRY_RESOURCE_NAME */
#if JERRY_FUNCTION_TO_STRING
script_p->source_code = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
#endif /* JERRY_FUNCTION_TO_STRING */
const uint8_t *literal_base_p = snapshot_data_p + header_p->lit_table_offset;
bytecode_p = snapshot_load_compiled_code ((const uint8_t *) bytecode_p,
@ -1021,7 +1030,7 @@ jerry_exec_snapshot (const uint32_t *snapshot_p, /**< snapshot */
if (user_value != ECMA_VALUE_EMPTY)
{
((cbc_script_user_t *) script_p)->user_value = ecma_copy_value_if_not_object (user_value);
CBC_SCRIPT_GET_USER_VALUE (script_p) = ecma_copy_value_if_not_object (user_value);
}
}

View File

@ -1841,6 +1841,9 @@ jerry_is_feature_enabled (const jerry_feature_t feature) /**< feature to check *
#if JERRY_MODULE_SYSTEM
|| feature == JERRY_FEATURE_MODULE
#endif /* JERRY_MODULE_SYSTEM */
#if JERRY_FUNCTION_TO_STRING
|| feature == JERRY_FEATURE_FUNCTION_TO_STRING
#endif /* JERRY_FUNCTION_TO_STRING */
);
} /* jerry_is_feature_enabled */
@ -2801,7 +2804,7 @@ jerry_create_regexp_sz (const jerry_char_t *pattern_p, /**< zero-terminated UTF-
jerry_assert_api_available ();
#if JERRY_BUILTIN_REGEXP
if (!lit_is_valid_utf8_string (pattern_p, pattern_size))
if (!lit_is_valid_utf8_string (pattern_p, pattern_size, true))
{
return jerry_throw (ecma_raise_common_error (ECMA_ERR_MSG ("Input must be a valid utf8 string")));
}
@ -5130,7 +5133,8 @@ jerry_is_valid_utf8_string (const jerry_char_t *utf8_buf_p, /**< UTF-8 string */
jerry_size_t buf_size) /**< string size */
{
return lit_is_valid_utf8_string ((lit_utf8_byte_t *) utf8_buf_p,
(lit_utf8_size_t) buf_size);
(lit_utf8_size_t) buf_size,
true);
} /* jerry_is_valid_utf8_string */
/**
@ -5490,7 +5494,7 @@ jerry_get_user_value (const jerry_value_t value) /**< jerry api value */
return ECMA_VALUE_UNDEFINED;
}
return ecma_copy_value (((cbc_script_user_t *) script_p)->user_value);
return ecma_copy_value (CBC_SCRIPT_GET_USER_VALUE (script_p));
} /* jerry_get_user_value */
/**

View File

@ -231,6 +231,19 @@
# define JERRY_LCACHE 1
#endif /* !defined (JERRY_LCACHE) */
/**
* Enable/Disable function toString operation.
*
* Allowed values:
* 0: Disable function toString operation.
* 1: Enable function toString operation.
*
* Default value: 0
*/
#ifndef JERRY_FUNCTION_TO_STRING
# define JERRY_FUNCTION_TO_STRING 0
#endif /* !defined (JERRY_FUNCTION_TO_STRING) */
/**
* Enable/Disable line-info management inside the engine.
*
@ -634,6 +647,10 @@
|| ((JERRY_LCACHE != 0) && (JERRY_LCACHE != 1))
# error "Invalid value for 'JERRY_LCACHE' macro."
#endif
#if !defined (JERRY_FUNCTION_TO_STRING) \
|| ((JERRY_FUNCTION_TO_STRING != 0) && (JERRY_FUNCTION_TO_STRING != 1))
# error "Invalid value for 'JERRY_FUNCTION_TO_STRING' macro."
#endif
#if !defined (JERRY_LINE_INFO) \
|| ((JERRY_LINE_INFO != 0) && (JERRY_LINE_INFO != 1))
# error "Invalid value for 'JERRY_LINE_INFO' macro."

View File

@ -0,0 +1,152 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "byte-code.h"
#include "ecma-helpers.h"
#include "ecma-extended-info.h"
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmaextendedinfo Extended info
* @{
*/
/**
* Decodes an uint32_t number, and updates the buffer position.
*
* @return the decoded value
*/
uint32_t
ecma_extended_info_decode_vlq (uint8_t **buffer_p) /**< [in/out] target buffer */
{
uint8_t *source_p = *buffer_p;
uint32_t value = 0;
do
{
source_p--;
value = (value << ECMA_EXTENDED_INFO_VLQ_SHIFT) | (*source_p & ECMA_EXTENDED_INFO_VLQ_MASK);
}
while (*source_p & ECMA_EXTENDED_INFO_VLQ_CONTINUE);
*buffer_p = source_p;
return value;
} /* ecma_extended_info_decode_vlq */
/**
* Encodes an uint32_t number into a buffer.
*/
void
ecma_extended_info_encode_vlq (uint8_t **buffer_p, /**< target buffer */
uint32_t value) /**< encoded value */
{
uint8_t *destination_p = *buffer_p - 1;
if (value <= ECMA_EXTENDED_INFO_VLQ_MASK)
{
*destination_p = (uint8_t) value;
*buffer_p = destination_p;
return;
}
uint32_t length = 0;
uint32_t current_value = value >> ECMA_EXTENDED_INFO_VLQ_SHIFT;
do
{
current_value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT;
length++;
}
while (current_value > 0);
destination_p -= length;
*buffer_p = destination_p;
do
{
*destination_p++ = (uint8_t) (value | ECMA_EXTENDED_INFO_VLQ_CONTINUE);
value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT;
}
while (value > 0);
**buffer_p &= ECMA_EXTENDED_INFO_VLQ_MASK;
} /* ecma_extended_info_encode_vlq */
/**
* Gets the encoded length of a number.
*
* @return encoded length
*/
uint32_t
ecma_extended_info_get_encoded_length (uint32_t value) /**< encoded value */
{
uint32_t length = 0;
do
{
value >>= ECMA_EXTENDED_INFO_VLQ_SHIFT;
length++;
}
while (value > 0);
return length;
} /* ecma_extended_info_get_encoded_length */
/**
* Get the extended info from a byte code
*
* @return pointer to the extended info
*/
uint8_t *
ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
{
JERRY_ASSERT (bytecode_header_p != NULL);
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO);
ecma_value_t *base_p = ecma_compiled_code_resolve_arguments_start (bytecode_header_p);
#if JERRY_ESNEXT
if (CBC_FUNCTION_GET_TYPE (bytecode_header_p->status_flags) != CBC_FUNCTION_CONSTRUCTOR)
{
base_p--;
}
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS)
{
base_p--;
}
#endif /* JERRY_ESNEXT */
#if JERRY_LINE_INFO
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_LINE_INFO)
{
base_p--;
}
#endif /* JERRY_LINE_INFO */
JERRY_ASSERT (((uint8_t *) base_p)[-1] != 0);
return ((uint8_t *) base_p) - 1;
} /* ecma_compiled_code_resolve_extended_info */
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
/**
* @}
* @}
*/

View File

@ -0,0 +1,58 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMA_EXTENDED_INFO_H
#define ECMA_EXTENDED_INFO_H
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmaextendedinfo Extended info
* @{
*/
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
#include "ecma-globals.h"
/**
* Vlq encoding: flag which is set for all bytes except the last one.
*/
#define ECMA_EXTENDED_INFO_VLQ_CONTINUE 0x80
/**
* Vlq encoding: mask to decode the number fragment.
*/
#define ECMA_EXTENDED_INFO_VLQ_MASK 0x7f
/**
* Vlq encoding: number of bits stored in a byte.
*/
#define ECMA_EXTENDED_INFO_VLQ_SHIFT 7
uint32_t ecma_extended_info_decode_vlq (uint8_t **buffer_p);
void ecma_extended_info_encode_vlq (uint8_t **buffer_p, uint32_t value);
uint32_t ecma_extended_info_get_encoded_length (uint32_t value);
uint8_t *ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p);
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
/**
* @}
* @}
*/
#endif /* !ECMA_EXTENDED_INFO_H */

View File

@ -430,10 +430,10 @@ ecma_gc_mark_compiled_code (const ecma_compiled_code_t *compiled_code_p) /**< co
if (CBC_SCRIPT_GET_TYPE (script_p) == CBC_SCRIPT_USER_OBJECT)
{
cbc_script_user_t *script_user_p = (cbc_script_user_t *) script_p;
ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p);
JERRY_ASSERT (ecma_is_value_object (script_user_p->user_value));
ecma_gc_set_object_visited (ecma_get_object_from_value (script_user_p->user_value));
JERRY_ASSERT (ecma_is_value_object (user_value));
ecma_gc_set_object_visited (ecma_get_object_from_value (user_value));
}
#if JERRY_BUILTIN_REALMS

View File

@ -130,6 +130,9 @@ typedef enum
#if JERRY_ESNEXT
ECMA_PARSE_INTERNAL_PRE_SCANNING = (1u << 16), /**< the parser is in pre-scanning mode */
#endif /* JERRY_ESNEXT */
#if JERRY_FUNCTION_TO_STRING
ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER = (1u << 17), /**< source has 4 byte marker */
#endif /* JERRY_FUNCTION_TO_STRING */
#ifndef JERRY_NDEBUG
/**
* This flag represents an error in for in/of statements, which cannot be set

View File

@ -443,7 +443,7 @@ ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string
converted_string_size += string_size;
JERRY_ASSERT (lit_is_valid_utf8_string (string_p, string_size));
JERRY_ASSERT (lit_is_valid_utf8_string (string_p, string_size, false));
lit_utf8_byte_t *data_p;
ecma_string_t *string_desc_p = ecma_new_ecma_string_from_utf8_buffer (converted_string_length,

View File

@ -1527,14 +1527,14 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
if (type != CBC_SCRIPT_GENERIC)
{
script_size = sizeof (cbc_script_user_t);
script_size += sizeof (ecma_value_t);
if (type == CBC_SCRIPT_USER_VALUE)
{
cbc_script_user_t *script_user_p = (cbc_script_user_t *) script_p;
ecma_value_t user_value = CBC_SCRIPT_GET_USER_VALUE (script_p);
JERRY_ASSERT (!ecma_is_value_object (script_user_p->user_value));
ecma_free_value (script_user_p->user_value);
JERRY_ASSERT (!ecma_is_value_object (user_value));
ecma_free_value (user_value);
}
}
@ -1542,6 +1542,16 @@ ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
ecma_deref_ecma_string (ecma_get_string_from_value (script_p->resource_name));
#endif /* JERRY_RESOURCE_NAME */
#if JERRY_FUNCTION_TO_STRING
ecma_deref_ecma_string (ecma_get_string_from_value (script_p->source_code));
if (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS)
{
ecma_deref_ecma_string (ecma_get_string_from_value (CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, type)));
script_size += sizeof (ecma_value_t);
}
#endif /* JERRY_FUNCTION_TO_STRING */
jmem_heap_free_block (script_p, script_size);
}
@ -1728,21 +1738,6 @@ ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_h
return base_p;
} /* ecma_compiled_code_resolve_function_name */
/**
* Get the extended info from a byte code
*
* @return extended info value
*/
uint32_t
ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
{
JERRY_ASSERT (bytecode_header_p != NULL);
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO);
ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p);
return base_p[-1];
} /* ecma_compiled_code_resolve_extended_info */
/**
* Get the tagged template collection of the compiled code
*
@ -1755,9 +1750,7 @@ ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *b
JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS);
ecma_value_t *base_p = ecma_compiled_code_resolve_function_name (bytecode_header_p);
int offset = (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO) ? -2 : -1;
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[offset]);
return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, base_p[-1]);
} /* ecma_compiled_code_get_tagged_template_collection */
#endif /* JERRY_ESNEXT */
@ -1783,11 +1776,6 @@ ecma_compiled_code_get_line_info (const ecma_compiled_code_t *bytecode_header_p)
base_p--;
}
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO)
{
base_p--;
}
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_HAS_TAGGED_LITERALS)
{
base_p--;

View File

@ -539,7 +539,6 @@ const ecma_compiled_code_t *ecma_bytecode_get_from_value (ecma_value_t value);
ecma_value_t *ecma_compiled_code_resolve_arguments_start (const ecma_compiled_code_t *bytecode_header_p);
#if JERRY_ESNEXT
ecma_value_t *ecma_compiled_code_resolve_function_name (const ecma_compiled_code_t *bytecode_header_p);
uint32_t ecma_compiled_code_resolve_extended_info (const ecma_compiled_code_t *bytecode_header_p);
ecma_collection_t *ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p);
#endif /* JERRY_ESNEXT */
#if JERRY_LINE_INFO

View File

@ -18,6 +18,7 @@
#include "ecma-builtins.h"
#include "ecma-conversion.h"
#include "ecma-exceptions.h"
#include "ecma-extended-info.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
@ -79,9 +80,116 @@ enum
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_function_prototype_object_to_string (void)
ecma_builtin_function_prototype_object_to_string (ecma_object_t *func_obj_p) /**< this argument object */
{
return ecma_make_magic_string_value (LIT_MAGIC_STRING__FUNCTION_TO_STRING);
if (ecma_get_object_type (func_obj_p) != ECMA_OBJECT_TYPE_FUNCTION)
{
return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE);
}
#if JERRY_FUNCTION_TO_STRING
const ecma_compiled_code_t *bytecode_p;
bytecode_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) func_obj_p);
ecma_value_t script_value = ((cbc_uint8_arguments_t *) bytecode_p)->script_value;
cbc_script_t *script_p = ECMA_GET_INTERNAL_VALUE_POINTER (cbc_script_t, script_value);
if (bytecode_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO)
{
uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_p);
uint8_t extended_info = *extended_info_p;
if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE)
{
#if JERRY_ESNEXT
if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH)
{
ecma_extended_info_decode_vlq (&extended_info_p);
}
#endif /* JERRY_ESNEXT */
uint32_t range_start = ecma_extended_info_decode_vlq (&extended_info_p);
uint32_t range_size = ecma_extended_info_decode_vlq (&extended_info_p);
ecma_value_t source_code;
if (!(extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS))
{
source_code = script_p->source_code;
#if JERRY_SNAPSHOT_EXEC
if (ecma_is_value_magic_string (source_code, LIT_MAGIC_STRING__EMPTY))
{
return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA);
}
#endif /* JERRY_SNAPSHOT_EXEC */
}
else
{
#if JERRY_SNAPSHOT_EXEC
if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS))
{
return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA);
}
#else /* !JERRY_SNAPSHOT_EXEC */
JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS);
#endif /* JERRY_SNAPSHOT_EXEC */
source_code = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, CBC_SCRIPT_GET_TYPE (script_p));
}
ecma_string_t *result_string_p;
ECMA_STRING_TO_UTF8_STRING (ecma_get_string_from_value (source_code), source_p, source_size);
result_string_p = ecma_new_ecma_string_from_utf8 (source_p + range_start, range_size);
ECMA_FINALIZE_UTF8_STRING (source_p, source_size);
return ecma_make_string_value (result_string_p);
}
}
#if JERRY_SNAPSHOT_EXEC
if (!(script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS))
{
return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA);
}
#else /* !JERRY_SNAPSHOT_EXEC */
JERRY_ASSERT (script_p->refs_and_type & CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS);
#endif /* JERRY_SNAPSHOT_EXEC */
lit_magic_string_id_t header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON;
#if JERRY_ESNEXT
switch (CBC_FUNCTION_GET_TYPE (bytecode_p->status_flags))
{
case CBC_FUNCTION_GENERATOR:
{
header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR;
break;
}
case CBC_FUNCTION_ASYNC_GENERATOR:
{
header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR;
break;
}
case CBC_FUNCTION_ASYNC:
{
header_id = LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC;
break;
}
}
#endif /* JERRY_ESNEXT */
ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (ecma_get_magic_string (header_id));
ecma_value_t function_arguments = CBC_SCRIPT_GET_FUNCTION_ARGUMENTS (script_p, CBC_SCRIPT_GET_TYPE (script_p));
ecma_stringbuilder_append (&builder, ecma_get_string_from_value (function_arguments));
ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n) {\n", 5);
ecma_stringbuilder_append (&builder, ecma_get_string_from_value (script_p->source_code));
ecma_stringbuilder_append_raw (&builder, (const lit_utf8_byte_t *) "\n}", 2);
return ecma_make_string_value (ecma_stringbuilder_finalize (&builder));
#else /* !JERRY_FUNCTION_TO_STRING */
return ecma_make_magic_string_value (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA);
#endif /* JERRY_FUNCTION_TO_STRING */
} /* ecma_builtin_function_prototype_object_to_string */
/**
@ -440,7 +548,7 @@ ecma_builtin_function_prototype_dispatch_routine (uint8_t builtin_routine_id, /*
{
case ECMA_FUNCTION_PROTOTYPE_TO_STRING:
{
return ecma_builtin_function_prototype_object_to_string ();
return ecma_builtin_function_prototype_object_to_string (func_obj_p);
}
case ECMA_FUNCTION_PROTOTYPE_APPLY:
{

View File

@ -284,7 +284,7 @@ ecma_builtin_global_object_decode_uri_helper (lit_utf8_byte_t *input_start_p, /*
}
if (!is_valid
|| !lit_is_valid_utf8_string (octets, bytes_count))
|| !lit_is_valid_utf8_string (octets, bytes_count, true))
{
ecma_stringbuilder_destroy (&builder);
return ecma_raise_uri_error (ECMA_ERR_MSG ("Invalid UTF8 string"));

View File

@ -17,6 +17,7 @@
#include "ecma-builtin-helpers.h"
#include "ecma-builtin-handlers.h"
#include "ecma-exceptions.h"
#include "ecma-extended-info.h"
#include "ecma-function-object.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
@ -1739,11 +1740,7 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**<
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
uint32_t len;
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO)
{
len = CBC_EXTENDED_INFO_GET_LENGTH (ecma_compiled_code_resolve_extended_info (bytecode_data_p));
}
else if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
{
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_data_p;
len = args_p->argument_end;
@ -1754,6 +1751,16 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**<
len = args_p->argument_end;
}
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO)
{
uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (bytecode_data_p);
if (*extended_info_p & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH)
{
len = ecma_extended_info_decode_vlq (&extended_info_p);
}
}
/* Set tag bit to represent initialized 'length' property */
ECMA_SET_FIRST_BIT_TO_POINTER_TAG (ext_func_p->u.function.scope_cp);
ecma_property_t *value_prop_p;

View File

@ -30,7 +30,7 @@ extern "C"
/**
* Jerry snapshot format version.
*/
#define JERRY_SNAPSHOT_VERSION (67u)
#define JERRY_SNAPSHOT_VERSION (68u)
/**
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.

View File

@ -112,6 +112,7 @@ typedef enum
JERRY_FEATURE_PROMISE_CALLBACK, /**< Promise callback support */
JERRY_FEATURE_MODULE, /**< Module support */
JERRY_FEATURE_WEAKREF, /**< WeakRef support */
JERRY_FEATURE_FUNCTION_TO_STRING, /**< function toString support */
JERRY_FEATURE__COUNT /**< number of features. NOTE: must be at the end of the list */
} jerry_feature_t;

View File

@ -1003,7 +1003,13 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL, "setUTCMilliseco
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL, "toLocaleDateString")
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL, "toLocaleTimeString")
#endif
#if JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON, "function anonymous(")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL, "getOwnPropertyNames")
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR, "function* anonymous(")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL, "propertyIsEnumerable")
#if JERRY_ESNEXT
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL, "getOwnPropertySymbols")
@ -1011,10 +1017,20 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL, "AsyncGenera
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL, "RegExp String Iterator")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, "getOwnPropertyDescriptor")
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC, "async function anonymous(")
#endif
#if JERRY_ESNEXT
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL, "getOwnPropertyDescriptors")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING__FUNCTION_TO_STRING, "function(){/* ecmascript */}")
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR, "async function* anonymous(")
#endif
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE, "function () { [native code] }")
#if JERRY_FUNCTION_TO_STRING && JERRY_SNAPSHOT_EXEC \
|| !(JERRY_FUNCTION_TO_STRING)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA, "function () { /* ecmascript */ }")
#endif
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (0, LIT_MAGIC_STRING__EMPTY)
#if JERRY_ESNEXT
@ -1213,8 +1229,16 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_GET_TIMEZONE_OFFSE
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL)
#endif
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (18, LIT_MAGIC_STRING_DECODE_URI_COMPONENT)
#if JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON)
#else
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (19, LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL)
#endif
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR)
#else
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (20, LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL)
#endif
#if JERRY_ESNEXT
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (21, LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL)
#else
@ -1227,11 +1251,32 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (22, LIT_MAGIC_STRING_GET_OWN_PROPERTY_D
#endif
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (23, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (24, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL)
#if JERRY_ESNEXT
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC)
#elif JERRY_ESNEXT
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL)
#elif JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR)
#else
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING__FUNCTION_TO_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (25, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE)
#endif
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR)
#else
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE)
#endif
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (27, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (28, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (29, LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE)
#if JERRY_FUNCTION_TO_STRING && JERRY_SNAPSHOT_EXEC \
|| !(JERRY_FUNCTION_TO_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (30, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA)
#endif
#if JERRY_FUNCTION_TO_STRING && JERRY_SNAPSHOT_EXEC \
|| !(JERRY_FUNCTION_TO_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (31, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA)
#endif
#if JERRY_FUNCTION_TO_STRING && JERRY_SNAPSHOT_EXEC \
|| !(JERRY_FUNCTION_TO_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (32, LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA)
#endif
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (26, LIT_MAGIC_STRING__FUNCTION_TO_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (27, LIT_MAGIC_STRING__FUNCTION_TO_STRING)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (28, LIT_MAGIC_STRING__FUNCTION_TO_STRING)

View File

@ -406,10 +406,15 @@ LIT_MAGIC_STRING_SET_UTC_MILLISECONDS_UL = "setUTCMilliseconds"
LIT_MAGIC_STRING_TO_LOCALE_DATE_STRING_UL = "toLocaleDateString"
LIT_MAGIC_STRING_TO_LOCALE_TIME_STRING_UL = "toLocaleTimeString"
LIT_MAGIC_STRING_GET_OWN_PROPERTY_NAMES_UL = "getOwnPropertyNames"
LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON = "function anonymous("
LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_GENERATOR = "function* anonymous("
LIT_MAGIC_STRING_PROPERTY_IS_ENUMERABLE_UL = "propertyIsEnumerable"
LIT_MAGIC_STRING_GET_OWN_PROPERTY_SYMBOLS_UL = "getOwnPropertySymbols"
LIT_MAGIC_STRING_REGEXP_STRING_ITERATOR_UL = "RegExp String Iterator"
LIT_MAGIC_STRING_ASYNC_GENERATOR_FUNCTION_UL = "AsyncGeneratorFunction"
LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL = "getOwnPropertyDescriptor"
LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC = "async function anonymous("
LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL = "getOwnPropertyDescriptors"
LIT_MAGIC_STRING__FUNCTION_TO_STRING = "function(){/* ecmascript */}"
LIT_MAGIC_STRING_FUNCTION_TO_STRING_ANON_ASYNC_GENERATOR = "async function* anonymous("
LIT_MAGIC_STRING_FUNCTION_TO_STRING_NATIVE = "function () { [native code] }"
LIT_MAGIC_STRING_FUNCTION_TO_STRING_ECMA = "function () { /* ecmascript */ }"

View File

@ -22,14 +22,14 @@
*
* NOTE:
* Isolated surrogates are allowed.
* Correct pair of surrogates is not allowed, it should be represented as 4-byte utf-8 character.
*
* @return true if utf-8 string is well-formed
* false otherwise
*/
bool
lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string */
lit_utf8_size_t buf_size) /**< string size */
lit_utf8_size_t buf_size, /**< string size */
bool is_strict) /**< true if surrogate pairs are not allowed */
{
lit_utf8_size_t idx = 0;
@ -95,21 +95,22 @@ lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, /**< utf-8 string *
return false;
}
if (code_point >= LIT_UTF16_HIGH_SURROGATE_MIN
&& code_point <= LIT_UTF16_HIGH_SURROGATE_MAX)
{
is_prev_code_point_high_surrogate = true;
}
else if (code_point >= LIT_UTF16_LOW_SURROGATE_MIN
&& code_point <= LIT_UTF16_LOW_SURROGATE_MAX
&& is_prev_code_point_high_surrogate)
{
/* sequence of high and low surrogate is not allowed */
return false;
}
else
if (is_strict)
{
is_prev_code_point_high_surrogate = false;
if (code_point >= LIT_UTF16_HIGH_SURROGATE_MIN
&& code_point <= LIT_UTF16_HIGH_SURROGATE_MAX)
{
is_prev_code_point_high_surrogate = true;
}
else if (code_point >= LIT_UTF16_LOW_SURROGATE_MIN
&& code_point <= LIT_UTF16_LOW_SURROGATE_MAX
&& is_prev_code_point_high_surrogate)
{
/* sequence of high and low surrogate is not allowed */
return false;
}
}
idx += extra_bytes_count;

View File

@ -84,7 +84,7 @@
#define LIT_UTF8_FIRST_BYTE_MAX (0xF8)
/* validation */
bool lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t buf_size);
bool lit_is_valid_utf8_string (const lit_utf8_byte_t *utf8_buf_p, lit_utf8_size_t buf_size, bool strict);
bool lit_is_valid_cesu8_string (const lit_utf8_byte_t *cesu8_buf_p, lit_utf8_size_t buf_size);
/* checks */

View File

@ -895,6 +895,27 @@ typedef enum
check a range of types without decoding the actual type. */
} cbc_code_flags_t;
/**
* Optional byte code fields. These fields are stored in a reversed
* order from the end of the byte code data.
*
* Value fields:
* - when CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED is set:
* argument_end number of argument names encoded as strings
* - when function type is not CBC_FUNCTION_CONSTRUCTOR:
* function name encoded as string
* - when CBC_CODE_FLAGS_HAS_TAGGED_LITERALS is set:
* pointer to the tagged template collection encoded as value
*
* Byte fields when CBC_CODE_FLAGS_HAS_EXTENDED_INFO is set:
* - always available:
* a byte which contains a combination of CBC_EXTENDED_CODE_FLAGS bits
* - when CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH is set:
* a vlq encoded default value for function length
* - when CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE is set:
* a pair of vlq encoded values, representing the start and size of the range
*/
/**
* Compact byte code function types.
*/
@ -962,9 +983,15 @@ typedef enum
((flags) >= (CBC_FUNCTION_ARROW << CBC_FUNCTION_TYPE_SHIFT))
/**
* Get length property from extended info
* Compact byte code extended status flags.
*/
#define CBC_EXTENDED_INFO_GET_LENGTH(extended_info) (extended_info)
typedef enum
{
CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH = (1u << 0), /**< has argument length */
CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE = (1u << 1), /**< has source code range (start, end) */
CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS = (1u << 2), /**< source code range is inside
* the function arguments */
} cbc_extended_code_flags_t;
/**
* Shared script data.
@ -977,20 +1004,25 @@ typedef enum
} cbc_script_type;
/**
* Value for increasing or decreasing the script reference counter.
* Script is a function with arguments source code.
*/
#define CBC_SCRIPT_REF_ONE 0x4
#define CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS 0x4
/**
* Get the type of a script.
* Value for increasing or decreasing the script reference counter.
*/
#define CBC_SCRIPT_GET_TYPE(script_p) ((script_p)->refs_and_type & (CBC_SCRIPT_REF_ONE - 1))
#define CBC_SCRIPT_REF_ONE 0x8
/**
* Maximum value of script reference counter.
*/
#define CBC_SCRIPT_REF_MAX (UINT32_MAX - CBC_SCRIPT_REF_ONE + 1)
/**
* Get the type of a script.
*/
#define CBC_SCRIPT_GET_TYPE(script_p) ((script_p)->refs_and_type & 0x3)
/**
* Sets the type of a script using the user_value.
*/
@ -1018,16 +1050,30 @@ typedef struct
#if JERRY_RESOURCE_NAME
ecma_value_t resource_name; /**< resource name */
#endif /* JERRY_RESOURCE_NAME */
#if JERRY_FUNCTION_TO_STRING
ecma_value_t source_code; /**< source code */
#endif /* JERRY_FUNCTION_TO_STRING */
} cbc_script_t;
/**
* Script data with user value.
* Get the array of optional values assigned to a script.
*
* First value: user value
* Second value: function arguments value
*/
typedef struct
{
cbc_script_t header; /**< script header */
ecma_value_t user_value; /**< user value */
} cbc_script_user_t;
#define CBC_SCRIPT_GET_OPTIONAL_VALUES(script_p) ((ecma_value_t *) ((script_p) + 1))
/**
* Get user value.
*/
#define CBC_SCRIPT_GET_USER_VALUE(script_p) \
(CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[0])
/**
* Get function arguments.
*/
#define CBC_SCRIPT_GET_FUNCTION_ARGUMENTS(script_p, type) \
(CBC_SCRIPT_GET_OPTIONAL_VALUES (script_p)[(type) != CBC_SCRIPT_GENERIC ? 1 : 0])
#define CBC_OPCODE(arg1, arg2, arg3, arg4) arg1,

View File

@ -15,6 +15,7 @@
#include "common.h"
#include "ecma-helpers.h"
#include "ecma-extended-info.h"
#include "ecma-big-uint.h"
#include "ecma-bigint.h"
#include "js-parser-internal.h"
@ -396,16 +397,31 @@ util_print_cbc (ecma_compiled_code_t *compiled_code_p) /**< compiled code */
JERRY_DEBUG_MSG (" Const literal range end: %d\n", (int) const_literal_end);
JERRY_DEBUG_MSG (" Literal range end: %d\n\n", (int) literal_end);
#if JERRY_ESNEXT
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
if (compiled_code_p->status_flags & CBC_CODE_FLAGS_HAS_EXTENDED_INFO)
{
uint32_t extended_info = ecma_compiled_code_resolve_extended_info (compiled_code_p);
uint8_t *extended_info_p = ecma_compiled_code_resolve_extended_info (compiled_code_p);
uint8_t *extended_info_start_p = extended_info_p + sizeof (uint8_t);
uint8_t extended_info = *extended_info_p;
JERRY_DEBUG_MSG (" [Extended] Argument length: %d\n\n", (int) CBC_EXTENDED_INFO_GET_LENGTH (extended_info));
if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH)
{
uint32_t argument_length = ecma_extended_info_decode_vlq (&extended_info_p);
JERRY_DEBUG_MSG (" [Extended] Argument length: %d\n", (int) argument_length);
}
size -= sizeof (ecma_value_t);
if (extended_info & CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE)
{
uint32_t range_start = ecma_extended_info_decode_vlq (&extended_info_p);
uint32_t range_end = ecma_extended_info_decode_vlq (&extended_info_p) + range_start;
JERRY_DEBUG_MSG (" [Extended] Source code range: %d - %d\n", (int) range_start, (int) range_end);
}
JERRY_DEBUG_MSG ("\n");
size -= (size_t) (extended_info_start_p - extended_info_p);
}
#endif /* JERRY_ESNEXT */
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
byte_code_start_p = (uint8_t *) compiled_code_p;

View File

@ -741,6 +741,9 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
{
decoded_length = 2 * 3;
status_flags = LEXER_LIT_LOCATION_HAS_ESCAPE;
#if JERRY_FUNCTION_TO_STRING
context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER;
#endif /* JERRY_FUNCTION_TO_STRING */
}
#else /* !JERRY_ESNEXT */
if (code_point < LIT_UTF8_4_BYTE_MARKER)
@ -1171,6 +1174,9 @@ lexer_parse_string (parser_context_t *context_p, /**< context */
raw_length_adjust += 2;
#endif /* JERRY_ESNEXT */
column++;
#if JERRY_FUNCTION_TO_STRING
context_p->global_status_flags |= ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER;
#endif /* JERRY_FUNCTION_TO_STRING */
continue;
}
else if (*source_p == LIT_CHAR_TAB)
@ -1605,6 +1611,11 @@ lexer_next_token (parser_context_t *context_p) /**< context */
{
size_t length;
#if JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING
/* Needed by arrow functions with expression body */
context_p->function_end_p = context_p->source_p;
#endif /* JERRY_ESNEXT && JERRY_FUNCTION_TO_STRING */
lexer_skip_spaces (context_p);
context_p->token.keyword_type = LEXER_EOS;
@ -3069,7 +3080,7 @@ lexer_construct_regexp_object (parser_context_t *context_p, /**< context */
}
else
{
JERRY_ASSERT (lit_is_valid_utf8_string (regex_start_p, length));
JERRY_ASSERT (lit_is_valid_utf8_string (regex_start_p, length, false));
pattern_str_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (regex_start_p, length);
}
@ -3189,6 +3200,13 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
JERRY_ASSERT ((ident_opts & LEXER_OBJ_IDENT_CLASS_IDENTIFIER)
|| !(ident_opts & LEXER_OBJ_IDENT_CLASS_NO_STATIC));
#if JERRY_FUNCTION_TO_STRING
if (ident_opts & LEXER_OBJ_IDENT_SET_FUNCTION_START)
{
context_p->function_start_p = context_p->source_p;
}
#endif /* JERRY_FUNCTION_TO_STRING */
if (lexer_parse_identifier (context_p, LEXER_PARSE_NO_OPTS))
{
if (!(ident_opts & (LEXER_OBJ_IDENT_ONLY_IDENTIFIERS | LEXER_OBJ_IDENT_OBJECT_PATTERN)))
@ -3253,6 +3271,10 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
#if JERRY_ESNEXT
case LIT_CHAR_LEFT_SQUARE:
{
#if JERRY_FUNCTION_TO_STRING
const uint8_t *function_start_p = context_p->function_start_p;
#endif /* JERRY_FUNCTION_TO_STRING */
lexer_consume_next_character (context_p);
lexer_next_token (context_p);
@ -3262,6 +3284,10 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
{
parser_raise_error (context_p, PARSER_ERR_RIGHT_SQUARE_EXPECTED);
}
#if JERRY_FUNCTION_TO_STRING
context_p->function_start_p = function_start_p;
#endif /* JERRY_FUNCTION_TO_STRING */
return;
}
case LIT_CHAR_ASTERISK:
@ -3277,7 +3303,7 @@ lexer_expect_object_literal_id (parser_context_t *context_p, /**< context */
}
case LIT_CHAR_DOT:
{
if ((ident_opts & ((uint32_t) ~LEXER_OBJ_IDENT_OBJECT_PATTERN))
if ((ident_opts & ((uint32_t) ~(LEXER_OBJ_IDENT_OBJECT_PATTERN | LEXER_OBJ_IDENT_SET_FUNCTION_START)))
|| context_p->source_p + 2 >= context_p->source_end_p
|| context_p->source_p[1] != LIT_CHAR_DOT
|| context_p->source_p[2] != LIT_CHAR_DOT)

View File

@ -275,11 +275,16 @@ typedef enum
*/
typedef enum
{
LEXER_OBJ_IDENT_NO_OPTS = 0, /**< no options */
LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 0), /**< only identifiers are accepted */
LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 1), /**< expect identifier inside a class body */
LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 2), /**< static keyword was not present before the identifier */
LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 3), /**< parse "get"/"set" as string literal in object pattern */
LEXER_OBJ_IDENT_NO_OPTS = 0, /**< no options */
LEXER_OBJ_IDENT_ONLY_IDENTIFIERS = (1u << 0), /**< only identifiers are accepted */
LEXER_OBJ_IDENT_CLASS_IDENTIFIER = (1u << 1), /**< expect identifier inside a class body */
LEXER_OBJ_IDENT_CLASS_NO_STATIC = (1u << 2), /**< static keyword was not present before the identifier */
LEXER_OBJ_IDENT_OBJECT_PATTERN = (1u << 3), /**< parse "get"/"set" as string literal in object pattern */
#if JERRY_FUNCTION_TO_STRING
LEXER_OBJ_IDENT_SET_FUNCTION_START = (1u << 4), /**< set function start */
#else /* !JERRY_FUNCTION_TO_STRING */
LEXER_OBJ_IDENT_SET_FUNCTION_START = 0, /**< set function start (disabled) */
#endif /* JERRY_FUNCTION_TO_STRING */
} lexer_obj_ident_opts_t;
/**

View File

@ -562,6 +562,7 @@ parser_parse_class_body (parser_context_t *context_p, /**< context */
}
lexer_expect_object_literal_id (context_p, (LEXER_OBJ_IDENT_CLASS_IDENTIFIER
| LEXER_OBJ_IDENT_SET_FUNCTION_START
| (is_static ? 0 : LEXER_OBJ_IDENT_CLASS_NO_STATIC)));
if (context_p->token.type == LEXER_RIGHT_BRACE)
@ -1167,7 +1168,7 @@ parser_parse_object_literal (parser_context_t *context_p) /**< context */
while (true)
{
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_NO_OPTS);
lexer_expect_object_literal_id (context_p, LEXER_OBJ_IDENT_SET_FUNCTION_START);
switch (context_p->token.type)
{
@ -2011,6 +2012,10 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
{
JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
#if JERRY_FUNCTION_TO_STRING
context_p->function_start_p = context_p->token.lit_location.char_p;
#endif /* JERRY_FUNCTION_TO_STRING */
uint32_t arrow_status_flags = (PARSER_IS_FUNCTION
| PARSER_IS_ARROW_FUNCTION
| (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD));
@ -2124,6 +2129,9 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
}
case LEXER_KEYW_FUNCTION:
{
#if JERRY_FUNCTION_TO_STRING
context_p->function_start_p = context_p->token.lit_location.char_p;
#endif /* JERRY_FUNCTION_TO_STRING */
parser_parse_function_expression (context_p, PARSER_FUNCTION_CLOSURE | PARSER_IS_FUNC_EXPRESSION);
break;
}
@ -2270,6 +2278,10 @@ parser_parse_unary_expression (parser_context_t *context_p, /**< context */
parser_check_assignment_expr (context_p);
#if JERRY_FUNCTION_TO_STRING
context_p->function_start_p = context_p->source_p - 1;
#endif /* JERRY_FUNCTION_TO_STRING */
uint32_t arrow_status_flags = (PARSER_IS_FUNCTION
| PARSER_IS_ARROW_FUNCTION
| (context_p->status_flags & PARSER_INSIDE_CLASS_FIELD));

View File

@ -539,6 +539,10 @@ typedef struct parser_saved_context_t
#if JERRY_LINE_INFO
parser_line_info_data_t *line_info_p; /**< line info data */
#endif /* JERRY_LINE_INFO */
#if JERRY_FUNCTION_TO_STRING
const uint8_t *function_start_p; /**< start position of the current function */
#endif /* JERRY_FUNCTION_TO_STRING */
} parser_saved_context_t;
/**
@ -571,6 +575,7 @@ typedef struct
const uint8_t *arguments_start_p; /**< function argument list start */
lit_utf8_size_t arguments_size; /**< function argument list size */
ecma_value_t script_value; /**< current script as value */
ecma_value_t argument_list; /**< current argument list as value */
ecma_value_t user_value; /**< current user value */
#if JERRY_MODULE_SYSTEM
@ -639,6 +644,11 @@ typedef struct
#if JERRY_LINE_INFO
parser_line_info_data_t *line_info_p; /**< line info data */
#endif /* JERRY_LINE_INFO */
#if JERRY_FUNCTION_TO_STRING
const uint8_t *function_start_p; /**< start position of the function which will be parsed */
const uint8_t *function_end_p; /**< end position of the current function */
#endif /* JERRY_FUNCTION_TO_STRING */
} parser_context_t;
/**

View File

@ -656,6 +656,17 @@ parser_parse_function_statement (parser_context_t *context_p) /**< context */
}
#endif /* JERRY_ESNEXT */
#if JERRY_FUNCTION_TO_STRING
#if JERRY_ESNEXT
if (!(context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_ASYNC))
{
context_p->function_start_p = context_p->token.lit_location.char_p;
}
#else /* !JERRY_ESNEXT */
context_p->function_start_p = context_p->token.lit_location.char_p;
#endif /* JERRY_ESNEXT */
#endif /* JERRY_FUNCTION_TO_STRING */
#if JERRY_DEBUGGER
parser_line_counter_t debugger_line = context_p->token.line;
parser_line_counter_t debugger_column = context_p->token.column;
@ -2560,6 +2571,9 @@ parser_parse_export_statement (parser_context_t *context_p) /**< context */
&& context_p->next_scanner_info_p->source_p == context_p->source_p
&& context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION)
{
#if JERRY_FUNCTION_TO_STRING
context_p->function_start_p = context_p->token.lit_location.char_p;
#endif /* JERRY_FUNCTION_TO_STRING */
lexer_next_token (context_p);
}
@ -3246,6 +3260,9 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
parser_raise_error (context_p, PARSER_ERR_LEXICAL_SINGLE_STATEMENT);
}
#if JERRY_FUNCTION_TO_STRING
context_p->function_start_p = context_p->token.lit_location.char_p;
#endif /* JERRY_FUNCTION_TO_STRING */
lexer_next_token (context_p);
JERRY_ASSERT (context_p->token.type == LEXER_KEYW_FUNCTION);
continue;
@ -3343,6 +3360,10 @@ parser_parse_statements (parser_context_t *context_p) /**< context */
}
#endif /* JERRY_LINE_INFO */
#if JERRY_FUNCTION_TO_STRING
context_p->function_end_p = context_p->source_p;
#endif /* JERRY_FUNCTION_TO_STRING */
parser_stack_pop_uint8 (context_p);
context_p->last_statement.current_p = NULL;
/* There is no lexer_next_token here, since the

View File

@ -15,6 +15,7 @@
#include "debugger.h"
#include "ecma-exceptions.h"
#include "ecma-extended-info.h"
#include "ecma-helpers.h"
#include "ecma-literal-storage.h"
#include "ecma-module.h"
@ -910,11 +911,6 @@ parser_post_processing (parser_context_t *context_p) /**< context */
total_size += sizeof (ecma_value_t);
}
if (context_p->argument_length != UINT16_MAX)
{
total_size += sizeof (ecma_value_t);
}
if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
{
total_size += sizeof (ecma_value_t);
@ -925,6 +921,48 @@ parser_post_processing (parser_context_t *context_p) /**< context */
total_size += sizeof (ecma_value_t);
#endif /* JERRY_LINE_INFO */
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
uint8_t extended_info = 0;
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
#if JERRY_ESNEXT
if (context_p->argument_length != UINT16_MAX)
{
extended_info |= CBC_EXTENDED_CODE_FLAGS_HAS_ARGUMENT_LENGTH;
total_size += ecma_extended_info_get_encoded_length (context_p->argument_length);
}
#endif /* JERRY_ESNEXT */
#if JERRY_FUNCTION_TO_STRING
if (context_p->last_context_p != NULL)
{
extended_info |= CBC_EXTENDED_CODE_FLAGS_HAS_SOURCE_CODE_RANGE;
const uint8_t *start_p = context_p->source_start_p;
const uint8_t *function_start_p = context_p->last_context_p->function_start_p;
if (function_start_p < start_p || function_start_p >= start_p + context_p->source_size)
{
JERRY_ASSERT (context_p->arguments_start_p != NULL
&& function_start_p >= context_p->arguments_start_p
&& function_start_p < context_p->arguments_start_p + context_p->arguments_size);
start_p = context_p->arguments_start_p;
extended_info |= CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS;
}
total_size += ecma_extended_info_get_encoded_length ((uint32_t) (function_start_p - start_p));
total_size += ecma_extended_info_get_encoded_length ((uint32_t) (context_p->function_end_p - function_start_p));
}
#endif /* JERRY_FUNCTION_TO_STRING */
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
if (extended_info != 0)
{
total_size += sizeof (uint8_t);
}
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size);
@ -1327,19 +1365,10 @@ parser_post_processing (parser_context_t *context_p) /**< context */
*(--base_p) = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
}
if (context_p->argument_length != UINT16_MAX)
{
compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_EXTENDED_INFO;
*(--base_p) = context_p->argument_length;
}
if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
{
compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_TAGGED_LITERALS;
base_p[-1] = (ecma_value_t) context_p->tagged_template_literal_cp;
#if JERRY_LINE_INFO
--base_p;
#endif /* JERRY_LINE_INFO */
*(--base_p) = (ecma_value_t) context_p->tagged_template_literal_cp;
}
#endif /* JERRY_ESNEXT */
@ -1347,6 +1376,44 @@ parser_post_processing (parser_context_t *context_p) /**< context */
ECMA_SET_INTERNAL_VALUE_POINTER (base_p[-1], line_info_p);
#endif /* JERRY_LINE_INFO */
#if JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING
if (extended_info != 0)
{
#if JERRY_LINE_INFO
base_p--;
#endif /* JERRY_LINE_INFO */
uint8_t *extended_info_p = ((uint8_t *) base_p) - 1;
compiled_code_p->status_flags |= CBC_CODE_FLAGS_HAS_EXTENDED_INFO;
*extended_info_p = extended_info;
#if JERRY_ESNEXT
if (context_p->argument_length != UINT16_MAX)
{
ecma_extended_info_encode_vlq (&extended_info_p, context_p->argument_length);
}
#endif /* JERRY_ESNEXT */
#if JERRY_FUNCTION_TO_STRING
if (context_p->last_context_p != NULL)
{
const uint8_t *start_p = context_p->source_start_p;
if (extended_info & CBC_EXTENDED_CODE_FLAGS_SOURCE_CODE_IN_ARGUMENTS)
{
start_p = context_p->arguments_start_p;
}
const uint8_t *function_start_p = context_p->last_context_p->function_start_p;
ecma_extended_info_encode_vlq (&extended_info_p, (uint32_t) (function_start_p - start_p));
ecma_extended_info_encode_vlq (&extended_info_p, (uint32_t) (context_p->function_end_p - function_start_p));
}
#endif /* JERRY_FUNCTION_TO_STRING */
}
#endif /* JERRY_ESNEXT || JERRY_FUNCTION_TO_STRING */
#if JERRY_PARSER_DUMP_BYTE_CODE
if (context_p->is_show_opcodes)
{
@ -1793,22 +1860,22 @@ parser_parse_source (void *source_p, /**< source code */
context.module_names_p = NULL;
#endif /* JERRY_MODULE_SYSTEM */
ecma_value_t argument_list = ECMA_VALUE_EMPTY;
context.argument_list = ECMA_VALUE_EMPTY;
if (context.options_p != NULL
&& (context.options_p->options & JERRY_PARSE_HAS_ARGUMENT_LIST))
{
argument_list = context.options_p->argument_list;
context.argument_list = context.options_p->argument_list;
}
else if (context.global_status_flags & ECMA_PARSE_HAS_ARGUMENT_LIST_VALUE)
{
JERRY_ASSERT (context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE);
argument_list = ((ecma_value_t *) source_p)[1];
context.argument_list = ((ecma_value_t *) source_p)[1];
}
if (argument_list != ECMA_VALUE_EMPTY)
if (context.argument_list != ECMA_VALUE_EMPTY)
{
JERRY_ASSERT (ecma_is_value_string (argument_list));
JERRY_ASSERT (ecma_is_value_string (context.argument_list));
context.status_flags |= PARSER_IS_FUNCTION;
#if JERRY_ESNEXT
@ -1822,7 +1889,7 @@ parser_parse_source (void *source_p, /**< source code */
}
#endif /* JERRY_ESNEXT */
ecma_string_t *string_p = ecma_get_string_from_value (argument_list);
ecma_string_t *string_p = ecma_get_string_from_value (context.argument_list);
uint8_t flags = ECMA_STRING_FLAG_EMPTY;
context.arguments_start_p = ecma_string_get_chars (string_p, &context.arguments_size, NULL, NULL, &flags);
@ -1881,7 +1948,7 @@ parser_parse_source (void *source_p, /**< source code */
if (CBC_SCRIPT_GET_TYPE (parent_script_p) != CBC_SCRIPT_GENERIC)
{
context.user_value = ((cbc_script_user_t *) parent_script_p)->user_value;
context.user_value = CBC_SCRIPT_GET_USER_VALUE (parent_script_p);
}
#if JERRY_SNAPSHOT_EXEC
}
@ -1893,8 +1960,20 @@ parser_parse_source (void *source_p, /**< source code */
context.user_value = context.options_p->user_value;
}
uint32_t script_size = (context.user_value != ECMA_VALUE_EMPTY ? sizeof (cbc_script_user_t)
: sizeof (cbc_script_t));
size_t script_size = sizeof (cbc_script_t);
if (context.user_value != ECMA_VALUE_EMPTY)
{
script_size += sizeof (ecma_value_t);
}
#if JERRY_FUNCTION_TO_STRING
if (context.argument_list != ECMA_VALUE_EMPTY)
{
script_size += sizeof (ecma_value_t);
}
#endif /* JERRY_FUNCTION_TO_STRING */
context.script_p = jmem_heap_alloc_block_null_on_error (script_size);
if (JERRY_UNLIKELY (context.script_p == NULL))
@ -1977,6 +2056,11 @@ parser_parse_source (void *source_p, /**< source code */
context.line_info_p = NULL;
#endif /* JERRY_LINE_INFO */
#if JERRY_FUNCTION_TO_STRING
context.function_start_p = NULL;
context.function_end_p = NULL;
#endif /* JERRY_FUNCTION_TO_STRING */
#if JERRY_PARSER_DUMP_BYTE_CODE
context.is_show_opcodes = (JERRY_CONTEXT (jerry_init_flags) & JERRY_INIT_SHOW_OPCODES);
context.total_byte_code_size = 0;
@ -2116,9 +2200,44 @@ parser_parse_source (void *source_p, /**< source code */
if (context.user_value != ECMA_VALUE_EMPTY)
{
((cbc_script_user_t *) context.script_p)->user_value = ecma_copy_value_if_not_object (context.user_value);
CBC_SCRIPT_GET_USER_VALUE (context.script_p) = ecma_copy_value_if_not_object (context.user_value);
}
#if JERRY_FUNCTION_TO_STRING
if (!(context.global_status_flags & ECMA_PARSE_HAS_SOURCE_VALUE))
{
ecma_string_t *string_p;
if (context.global_status_flags & ECMA_PARSE_INTERNAL_HAS_4_BYTE_MARKER)
{
string_p = ecma_new_ecma_string_from_utf8_converted_to_cesu8 (context.source_start_p, context.source_size);
}
else
{
string_p = ecma_new_ecma_string_from_utf8 (context.source_start_p, context.source_size);
}
context.script_p->source_code = ecma_make_string_value (string_p);
}
else
{
ecma_value_t source = ((ecma_value_t *) source_p)[0];
ecma_ref_ecma_string (ecma_get_string_from_value (source));
context.script_p->source_code = source;
}
if (context.argument_list != ECMA_VALUE_EMPTY)
{
int idx = (context.user_value != ECMA_VALUE_EMPTY) ? 1 : 0;
CBC_SCRIPT_GET_OPTIONAL_VALUES (context.script_p)[idx] = context.argument_list;
ecma_ref_ecma_string (ecma_get_string_from_value (context.argument_list));
context.script_p->refs_and_type |= CBC_SCRIPT_HAS_FUNCTION_ARGUMENTS;
}
#endif /* JERRY_FUNCTION_TO_STRING */
#if JERRY_PARSER_DUMP_BYTE_CODE
if (context.is_show_opcodes)
{
@ -2315,6 +2434,10 @@ parser_save_context (parser_context_t *context_p, /**< context */
saved_context_p->line_info_p = context_p->line_info_p;
#endif /* JERRY_LINE_INFO */
#if JERRY_FUNCTION_TO_STRING
saved_context_p->function_start_p = context_p->function_start_p;
#endif /* JERRY_FUNCTION_TO_STRING */
/* Reset private part of the context. */
context_p->status_flags &= PARSER_IS_STRICT;

View File

@ -4573,7 +4573,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (CBC_SCRIPT_GET_TYPE (script_p) != CBC_SCRIPT_GENERIC)
{
user_value = ((cbc_script_user_t *) script_p)->user_value;
user_value = CBC_SCRIPT_GET_USER_VALUE (script_p);
}
#if JERRY_SNAPSHOT_EXEC
}

View File

@ -0,0 +1,188 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function check() {}
if (check.toString() !== "function () { /* ecmascript */ }")
{
var a, b, o, c, f;
/* Function statements. */
a = 6; function f1(a,b=1,c) { return a /* comment */ + b + c } b = 7
assert(f1.toString() === "function f1(a,b=1,c) { return a /* comment */ + b + c }")
a = 6; function * f2(a,b,c=1) {
function x() {}
} b = 7
assert(f2.toString() === "function * f2(a,b,c=1) {\n function x() {}\n }")
a = 6;async function f3 ( a , b , c ) { } b = 7
assert(f3.toString() === "async function f3 ( a , b , c ) { }")
a = 6;async/**/function*f4(a,b,c){} b = 7
assert(f4.toString() === "async/**/function*f4(a,b,c){}")
/* Object initializers. */
o = {f(a) { return a }}
assert(o.f.toString() === "f(a) { return a }")
o = {f:function(a){/**/}}
assert(o.f.toString() === "function(a){/**/}")
o = { [function(){ return 'f' }()] (a = function() {}) {} }
assert(o.f.toString() === "[function(){ return 'f' }()] (a = function() {}) {}")
o = {* f(a) {}}
assert(o.f.toString() === "* f(a) {}")
o = {*[function(){ return 'f' }()](a) {}}
assert(o.f.toString() === "*[function(){ return 'f' }()](a) {}")
o = {async/**/f(a) {}}
assert(o.f.toString() === "async/**/f(a) {}")
o = {/**/async [function(){ return 'f' }()](a) {}/**/}
assert(o.f.toString() === "async [function(){ return 'f' }()](a) {}")
o = {a:1,async/**/*/**/f(a) {},b:1}
assert(o.f.toString() === "async/**/*/**/f(a) {}")
o = {async *//
[function(){ return 'f' }()](a) {}/**/}
assert(o.f.toString() === "async *//\n [function(){ return 'f' }()](a) {}")
o = { get a() {return/**/6} }
assert(Object.getOwnPropertyDescriptor(o, "a").get.toString() === "get a() {return/**/6}")
o = { get[function(){ return 'a' }()](){} }
assert(Object.getOwnPropertyDescriptor(o, "a").get.toString() === "get[function(){ return 'a' }()](){}")
o = { set a(v) {/**/} }
assert(Object.getOwnPropertyDescriptor(o, "a").set.toString() === "set a(v) {/**/}")
o = {/**/set/**/[function(){ return 'a' }()]/**/(v) {/**/}/**/}
assert(Object.getOwnPropertyDescriptor(o, "a").set.toString() === "set/**/[function(){ return 'a' }()]/**/(v) {/**/}")
/* Class static functions. */
c = class { static/**/f() {}/**/ }
assert(c.f.toString() === "f() {}")
c = class { static[function(){ return 'f' }()]() {} }
assert(c.f.toString() === "[function(){ return 'f' }()]() {}")
c = class { static *f() {} }
assert(c.f.toString() === "*f() {}")
c = class {/**/static * [function(){ return 'f' }()](a=6){}/**/}
assert(c.f.toString() === "* [function(){ return 'f' }()](a=6){}")
c = class { static/**/async f() {} }
assert(c.f.toString() === "async f() {}")
c = class {static async[function(){ return 'f' }()]() {/**/}}
assert(c.f.toString() === "async[function(){ return 'f' }()]() {/**/}")
c = class { static async*f() {}}
assert(c.f.toString() === "async*f() {}")
c = class { static async*/**/[function(){ return 'f' }()](){} }
assert(c.f.toString() === "async*/**/[function(){ return 'f' }()](){}")
c = class { static/**/get/**/a() {}}
assert(Object.getOwnPropertyDescriptor(c, "a").get.toString() === "get/**/a() {}")
c = class {static set a(v){}}
assert(Object.getOwnPropertyDescriptor(c, "a").set.toString() === "set a(v){}")
c = class { static get[function(){ return 'a' }()](){} }
assert(Object.getOwnPropertyDescriptor(c, "a").get.toString() === "get[function(){ return 'a' }()](){}")
c = class { static set[function(){ return 'a' }()](v){}//
}
assert(Object.getOwnPropertyDescriptor(c, "a").set.toString() === "set[function(){ return 'a' }()](v){}")
/* Class functions. */
o = Object.getPrototypeOf(new class {/**/f() {}/**/})
assert(o.f.toString() === "f() {}")
o = Object.getPrototypeOf(new class {[function(){ return 'f' }()](){}})
assert(o.f.toString() === "[function(){ return 'f' }()](){}")
o = Object.getPrototypeOf(new class { * /**/ f() {} })
assert(o.f.toString() === "* /**/ f() {}")
o = Object.getPrototypeOf(new class { * [function(){ return 'f' }()]/**/(){} })
assert(o.f.toString() === "* [function(){ return 'f' }()]/**/(){}")
o = Object.getPrototypeOf(new class {async f() {}})
assert(o.f.toString() === "async f() {}")
o = Object.getPrototypeOf(new class {async[function(){ return 'f' }()](){}})
assert(o.f.toString() === "async[function(){ return 'f' }()](){}")
o = Object.getPrototypeOf(new class {/**/get/**/a() {}/**/})
assert(Object.getOwnPropertyDescriptor(o, "a").get.toString() === "get/**/a() {}")
o = Object.getPrototypeOf(new class { set a(v){} })
assert(Object.getOwnPropertyDescriptor(o, "a").set.toString() === "set a(v){}")
o = Object.getPrototypeOf(new class {/**/get/**/[function(){ return 'a' }()]() {}/**/})
assert(Object.getOwnPropertyDescriptor(o, "a").get.toString() === "get/**/[function(){ return 'a' }()]() {}")
o = Object.getPrototypeOf(new class { set/**/[function(){ return 'a' }()]( v ){} })
assert(Object.getOwnPropertyDescriptor(o, "a").set.toString() === "set/**/[function(){ return 'a' }()]( v ){}")
/* Function creators. */
f = Function("a,b", "return a + b")
assert(f.toString() === "function anonymous(a,b\n) {\nreturn a + b\n}")
f = Function("", "")
assert(f.toString() === "function anonymous(\n) {\n\n}")
f = function*(){}.constructor("a,b", "c", "yield a; return b + c")
assert(f.toString() === "function* anonymous(a,b,c\n) {\nyield a; return b + c\n}")
f = async function(){}.constructor("a", "return a + 'x'")
assert(f.toString() === "async function anonymous(a\n) {\nreturn a + 'x'\n}")
f = async function*(){}.constructor("a=3", "return a")
assert(f.toString() === "async function* anonymous(a=3\n) {\nreturn a\n}")
f = Function("a = function(x) { return x + 3 }", "return a")
assert(f().toString() === "function(x) { return x + 3 }")
f = Function("return function(x) { return x + 3 }")
assert(f().toString() === "function(x) { return x + 3 }")
/* Arrow functions. */
f = x => x + 1/**/
assert(f.toString() === "x => x + 1")
f =x => { return x + 1 }/**/
assert(f.toString() === "x => { return x + 1 }")
f = (/**/) => 'x' //
+ y
assert(f.toString() === "(/**/) => 'x' //\n + y")
f = async x => x + 1
assert(f.toString() === "async x => x + 1")
f =/**/async (x,/**/y)=>/**/null
assert(f.toString() === "async (x,/**/y)=>/**/null")
}

View File

@ -149,7 +149,9 @@ new delete_test ();
function binary_test_1 () {
/*/ new.target is converted to string */
assert ((new.target + 1) === "function(){/* ecmascript */}1");
var str = (new.target + 1);
assert (str.substring(0, 8) === "function"
&& str.substring(str.length - 2, str.length) === "}1");
}
function binary_test_2 () { assert (isNaN (new.target - 3)); }
function binary_test_3 () { assert (isNaN (new.target * 2)); }

View File

@ -14,4 +14,6 @@
var str = 'for (let i=0; i<(eval("1; function x() { }; 2;")); x - i++) { x += delete x;}'
assert(eval(str) === 'function(){/* ecmascript */}true');
var e = eval(str)
assert(e === 'function x() { }true'
|| e === 'function () { /* ecmascript */ }true');

View File

@ -12,16 +12,27 @@
// See the License for the specific language governing permissions and
// limitations under the License.
assert (Math.cos.toString() === "function(){/* ecmascript */}");
assert (Math.cos.toString() === "function () { [native code] }");
var has_toString = none.toString() != "function () { /* ecmascript */ }"
function check(f, expected)
{
assert (f.toString() === (has_toString ? expected : "function () { /* ecmascript */ }"))
}
function none() { return 1; }
assert (none.toString() === "function(){/* ecmascript */}");
check (none, "function none() { return 1; }")
assert (none.bind({}).toString() === "function () { [native code] }")
function single(b) { return 1; }
assert (single.toString() === "function(){/* ecmascript */}");
check (single, "function single(b) { return 1; }")
assert (single.bind({}).toString() === "function () { [native code] }")
function multiple(a,b) { return 1; }
assert (multiple.toString() === "function(){/* ecmascript */}");
check (multiple, "function multiple(a,b) { return 1; }")
assert (multiple.bind({}).toString() === "function () { [native code] }")
function lots(a,b,c,d,e,f,g,h,i,j,k) { return 1; }
assert (lots.toString() === "function(){/* ecmascript */}");
check (lots, "function lots(a,b,c,d,e,f,g,h,i,j,k) { return 1; }")
assert (lots.bind({}).toString() === "function () { [native code] }")

View File

@ -28,60 +28,9 @@
<test id="built-ins/BigInt/asUintN/length.js"><reason></reason></test>
<test id="built-ins/BigInt/asUintN/name.js"><reason></reason></test>
<test id="built-ins/BigInt/asUintN/order-of-steps.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/AsyncFunction.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/Function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/GeneratorFunction.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/arrow-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-arrow-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-function-declaration.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-function-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-method-class-expression-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-method-class-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-method-class-statement-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-method-class-statement.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-method-object.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/bound-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/built-in-function-object.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/class-declaration-complex-heritage.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/class-declaration-explicit-ctor.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/class-declaration-implicit-ctor.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/class-expression-explicit-ctor.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/class-expression-implicit-ctor.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/function-declaration-non-simple-parameter-list.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/function-declaration.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/function-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/generator-function-declaration.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/generator-function-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/generator-method.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/getter-class-expression-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/getter-class-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/getter-class-statement-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/getter-class-statement.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/getter-object.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/line-terminator-normalisation-CR-LF.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/line-terminator-normalisation-CR.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/line-terminator-normalisation-LF.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/method-class-expression-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/method-class-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/method-class-statement-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/method-class-statement.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/method-computed-property-name.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/method-object.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-arrow-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-async-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-async-method-definition.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-bound-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-class.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-function-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-generator-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-method-definition.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/setter-class-expression-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/setter-class-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/setter-class-statement-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/setter-class-statement.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/setter-object.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/symbol-named-builtins.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/unicode.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/well-known-intrinsic-object-functions.js"><reason></reason></test>
<test id="built-ins/GeneratorFunction/instance-yield-expr-in-param.js"><reason></reason></test>
<test id="built-ins/GeneratorPrototype/return/from-state-completed.js"><reason></reason></test>
@ -6678,16 +6627,6 @@
<test id="built-ins/AsyncGeneratorPrototype/throw/this-val-not-object.js"><reason></reason></test>
<test id="built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined-with-gc.js"><reason></reason></test>
<test id="built-ins/FinalizationRegistry/prototype/cleanupSome/return-undefined.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/AsyncGenerator.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-declaration.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-method-class-expression-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-method-class-expression.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-method-class-statement-static.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-method-class-statement.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/async-generator-method-object.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-async-generator-function.js"><reason></reason></test>
<test id="built-ins/Function/prototype/toString/proxy-async-generator-method-definition.js"><reason></reason></test>
<test id="language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-multiple.js"><reason></reason></test>
<test id="language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-null.js"><reason></reason></test>
<test id="language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-single-args.js"><reason></reason></test>

View File

@ -120,6 +120,8 @@ def get_arguments():
help='enable the jerry debugger (%(choices)s)')
coregrp.add_argument('--js-parser', metavar='X', choices=['ON', 'OFF'], type=str.upper,
help='enable js-parser (%(choices)s)')
coregrp.add_argument('--function-to-string', metavar='X', choices=['ON', 'OFF'], type=str.upper,
help='enable function toString (%(choices)s)')
coregrp.add_argument('--line-info', metavar='X', choices=['ON', 'OFF'], type=str.upper,
help='provide line info (%(choices)s)')
coregrp.add_argument('--logging', metavar='X', choices=['ON', 'OFF'], type=str.upper,
@ -208,6 +210,7 @@ def generate_build_options(arguments):
build_options_append('JERRY_EXTERNAL_CONTEXT', arguments.external_context)
build_options_append('JERRY_DEBUGGER', arguments.jerry_debugger)
build_options_append('JERRY_PARSER', arguments.js_parser)
build_options_append('JERRY_FUNCTION_TO_STRING', arguments.function_to_string)
build_options_append('JERRY_LINE_INFO', arguments.line_info)
build_options_append('JERRY_LOGGING', arguments.logging)
build_options_append('JERRY_GLOBAL_HEAP_SIZE', arguments.mem_heap)

View File

@ -42,7 +42,7 @@ def skip_if(condition, desc):
OPTIONS_COMMON = ['--lto=off']
OPTIONS_PROFILE_MIN = ['--profile=minimal']
OPTIONS_PROFILE_ES51 = ['--profile=es5.1']
OPTIONS_PROFILE_ESNEXT = ['--profile=es.next']
OPTIONS_PROFILE_ESNEXT = ['--profile=es.next', '--function-to-string=on']
OPTIONS_STACK_LIMIT = ['--stack-limit=96']
OPTIONS_GC_MARK_LIMIT = ['--gc-mark-limit=16']
OPTIONS_MEM_STRESS = ['--mem-stress-test=on']