Add builtin GeneratorFunction support (#3499)

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2020-01-15 12:01:58 +01:00
committed by GitHub
parent e3decffdd3
commit 4a331b2edc
24 changed files with 659 additions and 152 deletions
+1 -2
View File
@@ -990,8 +990,7 @@ jerry_snapshot_result (const uint32_t *snapshot_p, /**< snapshot */
if (as_function)
{
ecma_object_t *lex_env_p = ecma_get_global_environment ();
ecma_object_t *func_obj_p = ecma_op_create_function_object (lex_env_p,
bytecode_p);
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_p);
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION))
{
+2 -4
View File
@@ -457,8 +457,7 @@ jerry_parse (const jerry_char_t *resource_name_p, /**< resource name (usually a
ecma_free_value (parse_status);
ecma_object_t *lex_env_p = ecma_get_global_environment ();
ecma_object_t *func_obj_p = ecma_op_create_function_object (lex_env_p,
bytecode_data_p);
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
ecma_bytecode_deref (bytecode_data_p);
return ecma_make_object_value (func_obj_p);
@@ -539,8 +538,7 @@ jerry_parse_function (const jerry_char_t *resource_name_p, /**< resource name (u
ecma_free_value (parse_status);
ecma_object_t *lex_env_p = ecma_get_global_environment ();
ecma_object_t *func_obj_p = ecma_op_create_function_object (lex_env_p,
bytecode_data_p);
ecma_object_t *func_obj_p = ecma_op_create_simple_function_object (lex_env_p, bytecode_data_p);
ecma_bytecode_deref (bytecode_data_p);
return ecma_make_object_value (func_obj_p);
+1
View File
@@ -108,6 +108,7 @@ typedef enum
ECMA_PARSE_EVAL = (1u << 6), /**< eval is called */
ECMA_PARSE_MODULE = (1u << 7), /**< module is parsed */
ECMA_PARSE_FUNCTION = (1u << 8), /**< a function body is parsed or the code is inside a function */
ECMA_PARSE_GENERATOR_FUNCTION = (1u << 9), /**< generator function is parsed */
} ecma_parse_opts_t;
/**
@@ -57,6 +57,7 @@ ecma_init (void)
#if ENABLED (JERRY_ES2015)
JERRY_CONTEXT (current_new_target) = JERRY_CONTEXT_INVALID_NEW_TARGET;
JERRY_CONTEXT (current_function_obj_p) = NULL;
#endif /* ENABLED (JERRY_ES2015) */
} /* ecma_init */
@@ -68,6 +69,7 @@ ecma_finalize (void)
{
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (JERRY_CONTEXT (current_new_target) == JERRY_CONTEXT_INVALID_NEW_TARGET);
JERRY_ASSERT (JERRY_CONTEXT (current_function_obj_p) == NULL);
#endif /* ENABLED (JERRY_ES2015) */
ecma_finalize_global_lex_env ();
@@ -59,58 +59,6 @@ ecma_builtin_function_dispatch_call (const ecma_value_t *arguments_list_p, /**<
return ecma_builtin_function_dispatch_construct (arguments_list_p, arguments_list_len);
} /* ecma_builtin_function_dispatch_call */
/**
* Helper method to count and convert the arguments for the Function constructor call.
*
* Performs the operation described in ECMA 262 v5.1 15.3.2.1 steps 5.a-d
*
*
* @return ecma value - concatenated arguments as a string.
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_function_helper_get_function_arguments (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
if (arguments_list_len <= 1)
{
return ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
}
ecma_string_t *final_str_p = ecma_op_to_string (arguments_list_p[0]);
if (JERRY_UNLIKELY (final_str_p == NULL))
{
return ECMA_VALUE_ERROR;
}
if (arguments_list_len == 2)
{
return ecma_make_string_value (final_str_p);
}
for (ecma_length_t idx = 1; idx < arguments_list_len - 1; idx++)
{
ecma_string_t *new_str_p = ecma_op_to_string (arguments_list_p[idx]);
if (JERRY_UNLIKELY (new_str_p == NULL))
{
ecma_deref_ecma_string (final_str_p);
return ECMA_VALUE_ERROR;
}
final_str_p = ecma_append_magic_string_to_string (final_str_p,
LIT_MAGIC_STRING_COMMA_CHAR);
final_str_p = ecma_concat_ecma_strings (final_str_p, new_str_p);
ecma_deref_ecma_string (new_str_p);
}
return ecma_make_string_value (final_str_p);
} /* ecma_builtin_function_helper_get_function_arguments */
/**
* Handle calling [[Construct]] of built-in Function object
*
@@ -123,70 +71,7 @@ ecma_value_t
ecma_builtin_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
ecma_value_t arguments_value = ecma_builtin_function_helper_get_function_arguments (arguments_list_p,
arguments_list_len);
if (ECMA_IS_VALUE_ERROR (arguments_value))
{
return arguments_value;
}
ecma_string_t *function_body_str_p;
if (arguments_list_len > 0)
{
function_body_str_p = ecma_op_to_string (arguments_list_p[arguments_list_len - 1]);
if (JERRY_UNLIKELY (function_body_str_p == NULL))
{
ecma_free_value (arguments_value);
return ECMA_VALUE_ERROR;
}
}
else
{
/* Very unlikely code path, not optimized. */
function_body_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
}
ecma_string_t *arguments_str_p = ecma_get_string_from_value (arguments_value);
ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
ecma_compiled_code_t *bytecode_data_p = NULL;
ecma_value_t ret_value = parser_parse_script (arguments_buffer_p,
arguments_buffer_size,
function_body_buffer_p,
function_body_buffer_size,
ECMA_PARSE_NO_OPTS,
&bytecode_data_p);
if (!ECMA_IS_VALUE_ERROR (ret_value))
{
JERRY_ASSERT (ecma_is_value_true (ret_value));
ecma_object_t *func_obj_p = ecma_op_create_function_object (ecma_get_global_environment (),
bytecode_data_p);
ecma_bytecode_deref (bytecode_data_p);
ret_value = ecma_make_object_value (func_obj_p);
}
ECMA_FINALIZE_UTF8_STRING (function_body_buffer_p, function_body_buffer_size);
ECMA_FINALIZE_UTF8_STRING (arguments_buffer_p, arguments_buffer_size);
ecma_deref_ecma_string (arguments_str_p);
ecma_deref_ecma_string (function_body_str_p);
return ret_value;
return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_NO_OPTS);
} /* ecma_builtin_function_dispatch_construct */
/**
@@ -0,0 +1,72 @@
/* 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 "ecma-globals.h"
#if ENABLED (JERRY_ES2015)
#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
#include "ecma-function-object.h"
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator-function.inc.h"
#define BUILTIN_UNDERSCORED_ID generator_function
#include "ecma-builtin-internal-routines-template.inc.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmabuiltins
* @{
*
* \addtogroup generator ECMA GeneratorFunction object built-in
* @{
*/
/**
* Handle calling [[Call]] of built-in GeneratorFunction object
*
* @return constructed generator function object - if success
* raised error otherwise
*/
ecma_value_t
ecma_builtin_generator_function_dispatch_call (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
return ecma_op_create_dynamic_function (arguments_list_p, arguments_list_len, ECMA_PARSE_GENERATOR_FUNCTION);
} /* ecma_builtin_generator_function_dispatch_call */
/**
* Handle calling [[Construct]] of built-in GeneratorFunction object
*
* @return constructed generator function object - if success
* raised error otherwise
*/
ecma_value_t
ecma_builtin_generator_function_dispatch_construct (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
return ecma_builtin_generator_function_dispatch_call (arguments_list_p, arguments_list_len);
} /* ecma_builtin_generator_function_dispatch_construct */
/**
* @}
* @}
* @}
*/
#endif /* ENABLED (JERRY_ES2015) */
@@ -0,0 +1,41 @@
/* 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.
*/
/*
* %GeneratorFunction% built-in description
*/
#include "ecma-builtin-helpers-macro-defines.inc.h"
#if ENABLED (JERRY_ES2015)
/* ECMA-262 v6, 25.2.2 */
STRING_VALUE (LIT_MAGIC_STRING_NAME,
LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
/* ECMA-262 v6, 25.2.2 */
NUMBER_VALUE (LIT_MAGIC_STRING_LENGTH,
1,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
/* ECMA-262 v6, 25.2.2.2 */
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
ECMA_BUILTIN_ID_GENERATOR,
ECMA_PROPERTY_FIXED)
#endif /* ENABLED (JERRY_ES2015) */
#include "ecma-builtin-helpers-macro-undefs.inc.h"
@@ -38,7 +38,7 @@
* \addtogroup ecmabuiltins
* @{
*
* \addtogroup generator ECMA Generator object built-in
* \addtogroup generator ECMA Generator.prototype object built-in
* @{
*/
@@ -29,6 +29,11 @@ STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
LIT_MAGIC_STRING_GENERATOR_UL,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
/* ECMA-262 v6, 25.2.3.1 */
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
ECMA_BUILTIN_ID_GENERATOR,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
/* Routine properties:
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
ROUTINE (LIT_MAGIC_STRING_NEXT, ecma_builtin_generator_prototype_object_next, 1, 1)
@@ -0,0 +1,43 @@
/* 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 "ecma-globals.h"
#if ENABLED (JERRY_ES2015)
#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator.inc.h"
#define BUILTIN_UNDERSCORED_ID generator
#include "ecma-builtin-internal-routines-template.inc.h"
/** \addtogroup ecma ECMA
* @{
*
* \addtogroup ecmabuiltins
* @{
*
* \addtogroup generator ECMA Generator object built-in
* @{
*/
/**
* @}
* @}
* @}
*/
#endif /* ENABLED (JERRY_ES2015) */
@@ -0,0 +1,41 @@
/* 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.
*/
/*
* %Generator% built-in description (GeneratorFunction.prototype)
*/
#include "ecma-builtin-helpers-macro-defines.inc.h"
#if ENABLED (JERRY_ES2015)
/* ECMA-262 v6, 25.3.2.3.1 */
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
ECMA_BUILTIN_ID_GENERATOR_FUNCTION,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
/* ECMA-262 v6, 25.3.2.3.2 */
OBJECT_VALUE (LIT_MAGIC_STRING_PROTOTYPE,
ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
/* ECMA-262 v6, 25.3.2.3.3 */
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL,
ECMA_PROPERTY_FLAG_CONFIGURABLE)
#endif /* ENABLED (JERRY_ES2015) */
#include "ecma-builtin-helpers-macro-undefs.inc.h"
@@ -552,6 +552,21 @@ BUILTIN (ECMA_BUILTIN_ID_STRING_ITERATOR_PROTOTYPE,
true,
string_iterator_prototype)
/* The %(GeneratorFunction)% object */
BUILTIN_ROUTINE (ECMA_BUILTIN_ID_GENERATOR_FUNCTION,
ECMA_OBJECT_TYPE_FUNCTION,
ECMA_BUILTIN_ID_FUNCTION,
true,
generator_function)
/* The %(Generator)% object */
BUILTIN (ECMA_BUILTIN_ID_GENERATOR,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE,
true,
generator)
/* The %(Generator).prototype% object */
BUILTIN (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE,
ECMA_OBJECT_TYPE_GENERAL,
ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE,
+264 -15
View File
@@ -15,11 +15,11 @@
#include "ecma-alloc.h"
#include "ecma-builtin-helpers.h"
#include "ecma-builtins.h"
#include "ecma-exceptions.h"
#include "ecma-function-object.h"
#include "ecma-gc.h"
#include "ecma-helpers.h"
#include "lit-char-helpers.h"
#include "ecma-lex-env.h"
#include "ecma-objects.h"
#include "ecma-objects-general.h"
@@ -143,6 +143,152 @@ ecma_is_constructor (ecma_value_t value) /**< ecma value */
&& ecma_object_is_constructor (ecma_get_object_from_value (value)));
} /* ecma_is_constructor */
/**
* Helper method to count and convert the arguments for the Function/GeneratorFunction constructor call.
*
* See also:
* ECMA 262 v5.1 15.3.2.1 steps 5.a-d
* ECMA 262 v6 19.2.1.1.1 steps 8
*
* @return ecma value - concatenated arguments as a string.
* Returned value must be freed with ecma_free_value.
*/
static ecma_string_t *
ecma_op_create_dynamic_function_arguments_helper (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< number of arguments */
{
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
if (arguments_list_len <= 1)
{
return ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
}
ecma_string_t *str_p = ecma_op_to_string (arguments_list_p[0]);
if (JERRY_UNLIKELY (str_p == NULL))
{
return str_p;
}
if (arguments_list_len == 2)
{
return str_p;
}
ecma_stringbuilder_t builder = ecma_stringbuilder_create_from (str_p);
ecma_deref_ecma_string (str_p);
for (ecma_length_t idx = 1; idx < arguments_list_len - 1; idx++)
{
str_p = ecma_op_to_string (arguments_list_p[idx]);
if (JERRY_UNLIKELY (str_p == NULL))
{
ecma_stringbuilder_destroy (&builder);
return str_p;
}
ecma_stringbuilder_append_char (&builder, LIT_CHAR_COMMA);
ecma_stringbuilder_append (&builder, str_p);
ecma_deref_ecma_string (str_p);
}
return ecma_stringbuilder_finalize (&builder);
} /* ecma_op_create_dynamic_function_arguments_helper */
/**
* CreateDynamicFunction operation
*
* See also:
* ECMA-262 v5, 15.3.
* ECMA-262 v6, 19.2.1.1
*
* @return ECMA_VALUE_ERROR - if the operation fails
* constructed function object - otherwise
*/
ecma_value_t
ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len, /**< number of arguments */
ecma_parse_opts_t parse_opts) /**< parse options */
{
JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL);
ecma_string_t *arguments_str_p = ecma_op_create_dynamic_function_arguments_helper (arguments_list_p,
arguments_list_len);
if (JERRY_UNLIKELY (arguments_str_p == NULL))
{
return ECMA_VALUE_ERROR;
}
ecma_string_t *function_body_str_p;
if (arguments_list_len > 0)
{
function_body_str_p = ecma_op_to_string (arguments_list_p[arguments_list_len - 1]);
if (JERRY_UNLIKELY (function_body_str_p == NULL))
{
ecma_deref_ecma_string (arguments_str_p);
return ECMA_VALUE_ERROR;
}
}
else
{
/* Very unlikely code path, not optimized. */
function_body_str_p = ecma_get_magic_string (LIT_MAGIC_STRING__EMPTY);
}
ECMA_STRING_TO_UTF8_STRING (arguments_str_p, arguments_buffer_p, arguments_buffer_size);
ECMA_STRING_TO_UTF8_STRING (function_body_str_p, function_body_buffer_p, function_body_buffer_size);
#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
JERRY_CONTEXT (resource_name) = ecma_make_magic_string_value (LIT_MAGIC_STRING_RESOURCE_ANON);
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
ecma_compiled_code_t *bytecode_data_p = NULL;
ecma_value_t ret_value = parser_parse_script (arguments_buffer_p,
arguments_buffer_size,
function_body_buffer_p,
function_body_buffer_size,
parse_opts,
&bytecode_data_p);
if (!ECMA_IS_VALUE_ERROR (ret_value))
{
JERRY_ASSERT (ecma_is_value_true (ret_value));
ecma_object_t *func_obj_p;
ecma_object_t *global_env_p = ecma_get_global_environment ();
#if ENABLED (JERRY_ES2015)
if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)
{
func_obj_p = ecma_op_create_generator_function_object (global_env_p, bytecode_data_p);
}
else
{
#endif /* ENABLED (JERRY_ES2015) */
func_obj_p = ecma_op_create_simple_function_object (global_env_p, bytecode_data_p);
#if ENABLED (JERRY_ES2015)
}
#endif /* ENABLED (JERRY_ES2015) */
ecma_bytecode_deref (bytecode_data_p);
ret_value = ecma_make_object_value (func_obj_p);
}
ECMA_FINALIZE_UTF8_STRING (function_body_buffer_p, function_body_buffer_size);
ECMA_FINALIZE_UTF8_STRING (arguments_buffer_p, arguments_buffer_size);
ecma_deref_ecma_string (arguments_str_p);
ecma_deref_ecma_string (function_body_str_p);
return ret_value;
} /* ecma_op_create_dynamic_function */
/**
* Function object creation operation.
*
@@ -150,14 +296,15 @@ ecma_is_constructor (ecma_value_t value) /**< ecma value */
*
* @return pointer to newly created Function object
*/
ecma_object_t *
static ecma_object_t *
ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */
const ecma_compiled_code_t *bytecode_data_p, /**< byte-code array */
ecma_builtin_id_t proto_id) /**< builtin id of the prototype object */
{
JERRY_ASSERT (ecma_is_lexical_environment (scope_p));
/* 1., 4., 13. */
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
ecma_object_t *prototype_obj_p = ecma_builtin_get (proto_id);
size_t function_object_size = sizeof (ecma_extended_object_t);
@@ -219,8 +366,36 @@ ecma_op_create_function_object (ecma_object_t *scope_p, /**< function's scope */
return func_p;
} /* ecma_op_create_function_object */
/**
* Function object creation operation.
*
* See also: ECMA-262 v5, 13.2
*
* @return pointer to newly created Function object
*/
ecma_object_t *
ecma_op_create_simple_function_object (ecma_object_t *scope_p, /**< function's scope */
const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */
{
return ecma_op_create_function_object (scope_p, bytecode_data_p, ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
} /* ecma_op_create_simple_function_object */
#if ENABLED (JERRY_ES2015)
/**
* GeneratorFunction object creation operation.
*
* See also: ECMA-262 v5, 13.2
*
* @return pointer to newly created Function object
*/
ecma_object_t *
ecma_op_create_generator_function_object (ecma_object_t *scope_p, /**< function's scope */
const ecma_compiled_code_t *bytecode_data_p) /**< byte-code array */
{
return ecma_op_create_function_object (scope_p, bytecode_data_p, ECMA_BUILTIN_ID_GENERATOR);
} /* ecma_op_create_generator_function_object */
/**
* Arrow function object creation operation.
*
@@ -722,6 +897,43 @@ ecma_op_set_class_prototype (ecma_value_t completion_value, /**< completion_valu
completion_obj_p->u2.prototype_cp = prototype_obj_cp;
} /* ecma_op_set_class_prototype */
/**
* Ordinary internal method: GetPrototypeFromConstructor (constructor, intrinsicDefaultProto)
*
* See also: ECMAScript v6, 9.1.15
*
* @return NULL - if the operation fail (exception on the global context is raised)
* pointer to the prototype object - otherwise
*/
ecma_object_t *
ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, /**< constructor to get prototype from */
ecma_builtin_id_t default_proto_id) /**< intrinsicDefaultProto */
{
JERRY_ASSERT (ecma_object_is_constructor (ctor_obj_p));
JERRY_ASSERT (default_proto_id < ECMA_BUILTIN_ID__COUNT);
ecma_value_t proto = ecma_op_object_get_by_magic_id (ctor_obj_p, LIT_MAGIC_STRING_PROTOTYPE);
if (ECMA_IS_VALUE_ERROR (proto))
{
return NULL;
}
ecma_object_t *proto_obj_p;
if (!ecma_is_value_object (proto))
{
proto_obj_p = ecma_builtin_get (default_proto_id);
ecma_ref_object (proto_obj_p);
}
else
{
proto_obj_p = ecma_get_object_from_value (proto);
}
return proto_obj_p;
} /* ecma_op_get_prototype_from_constructor */
#endif /* ENABLED (JERRY_ES2015) */
/**
@@ -776,9 +988,15 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
}
if (is_construct_call && (status_flags & CBC_CODE_FLAGS_GENERATOR))
if (status_flags & CBC_CODE_FLAGS_GENERATOR)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Generator functions cannot be invoked with 'new'."));
if (is_construct_call)
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Generator functions cannot be invoked with 'new'."));
}
JERRY_CONTEXT (current_function_obj_p) = func_obj_p;
}
}
#endif /* ENABLED (JERRY_ES2015) */
@@ -835,6 +1053,13 @@ ecma_op_function_call_simple (ecma_object_t *func_obj_p, /**< Function object */
arguments_list_p,
arguments_list_len);
#if ENABLED (JERRY_ES2015)
if (JERRY_UNLIKELY (status_flags & CBC_CODE_FLAGS_GENERATOR))
{
JERRY_CONTEXT (current_function_obj_p) = NULL;
}
#endif /* ENABLED (JERRY_ES2015) */
if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED))
{
ecma_deref_object (local_env_p);
@@ -1320,21 +1545,45 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
static ecma_property_t *
ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the function object */
{
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION
|| ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
/* ECMA-262 v5, 13.2, 16-18 */
/* 16. */
ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();
ecma_object_t *proto_object_p = NULL;
bool init_constructor = true;
#if ENABLED (JERRY_ES2015)
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION)
{
const ecma_compiled_code_t *byte_code_p = ecma_op_function_get_compiled_code ((ecma_extended_object_t *) object_p);
if (byte_code_p->status_flags & CBC_CODE_FLAGS_GENERATOR)
{
proto_object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE),
0,
ECMA_OBJECT_TYPE_GENERAL);
init_constructor = false;
}
}
#endif /* ENABLED (JERRY_ES2015) */
if (proto_object_p == NULL)
{
proto_object_p = ecma_op_create_object_object_noarg ();
}
/* 17. */
ecma_property_value_t *constructor_prop_value_p;
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
if (init_constructor)
{
ecma_property_value_t *constructor_prop_value_p;
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
constructor_prop_value_p->value = ecma_make_object_value (object_p);
constructor_prop_value_p->value = ecma_make_object_value (object_p);
}
/* 18. */
ecma_property_t *prototype_prop_p;
@@ -17,6 +17,7 @@
#define ECMA_FUNCTION_OBJECT_H
#include "ecma-globals.h"
#include "ecma-builtins.h"
#include "vm.h"
/** \addtogroup ecma ECMA
@@ -38,8 +39,7 @@ bool ecma_is_constructor (ecma_value_t value);
bool ecma_object_is_constructor (ecma_object_t *obj_p);
ecma_object_t *
ecma_op_create_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p);
ecma_op_create_simple_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p);
ecma_object_t *
ecma_op_create_external_function_object (ecma_external_handler_t handler_cb);
@@ -47,6 +47,11 @@ ecma_op_create_external_function_object (ecma_external_handler_t handler_cb);
const ecma_compiled_code_t *
ecma_op_function_get_compiled_code (ecma_extended_object_t *function_p);
ecma_value_t
ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p,
ecma_length_t arguments_list_len,
ecma_parse_opts_t opts);
#if ENABLED (JERRY_ES2015)
void
ecma_op_set_super_called (ecma_object_t *lex_env_p);
@@ -69,6 +74,12 @@ ecma_op_function_implicit_constructor_handler_cb (const ecma_value_t function_ob
void
ecma_op_set_class_prototype (ecma_value_t completion_value, ecma_value_t this_arg);
ecma_object_t *
ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, ecma_builtin_id_t default_proto_id);
ecma_object_t *
ecma_op_create_generator_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p);
ecma_object_t *
ecma_op_create_arrow_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p,
ecma_value_t this_binding);
@@ -2471,6 +2471,12 @@ ecma_object_get_class_name (ecma_object_t *obj_p) /**< object */
return LIT_MAGIC_STRING_REFLECT_UL;
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_REFLECT) */
#if ENABLED (JERRY_ES2015)
case ECMA_BUILTIN_ID_GENERATOR:
{
return LIT_MAGIC_STRING_GENERATOR_UL;
}
#endif /* ENABLED (JERRY_ES2015) */
#if ENABLED (JERRY_BUILTIN_JSON)
case ECMA_BUILTIN_ID_JSON:
{
+2
View File
@@ -229,6 +229,8 @@ struct jerry_context_t
* * Any other valid function object pointer: the current "new.target" is valid and it is constructor call.
*/
ecma_object_t *current_new_target;
ecma_object_t *current_function_obj_p; /** currently invoked function object
(Note: currently used only in generator functions) */
#endif /* ENABLED (JERRY_ES2015) */
};
+8
View File
@@ -25,7 +25,10 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_RIGHT_PAREN, ")")
#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_ASTERIX_CHAR, "*")
#endif
#if ENABLED (JERRY_BUILTIN_ARRAY) \
|| ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COMMA_CHAR, ",")
#endif
#if ENABLED (JERRY_LINE_INFO)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_COLON_CHAR, ":")
#endif
@@ -772,6 +775,9 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, "defineProperties")
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U, "BYTES_PER_ELEMENT")
#endif
#if ENABLED (JERRY_ES2015)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL, "GeneratorFunction")
#endif
#if ENABLED (JERRY_BUILTIN_NUMBER)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_NEGATIVE_INFINITY_U, "NEGATIVE_INFINITY")
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_POSITIVE_INFINITY_U, "POSITIVE_INFINITY")
@@ -916,6 +922,8 @@ LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (16, LIT_MAGIC_STRING_DEFINE_PROPERTIES_
#endif
#if ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U)
#elif ENABLED (JERRY_ES2015)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL)
#elif ENABLED (JERRY_BUILTIN_NUMBER)
LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (17, LIT_MAGIC_STRING_NEGATIVE_INFINITY_U)
#elif ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY)
+1
View File
@@ -325,6 +325,7 @@ LIT_MAGIC_STRING_MIN_SAFE_INTEGER_U = "MIN_SAFE_INTEGER"
LIT_MAGIC_STRING_BYTES_PER_ELEMENT_U = "BYTES_PER_ELEMENT"
LIT_MAGIC_STRING_NEGATIVE_INFINITY_U = "NEGATIVE_INFINITY"
LIT_MAGIC_STRING_POSITIVE_INFINITY_U = "POSITIVE_INFINITY"
LIT_MAGIC_STRING_GENERATOR_FUNCTION_UL = "GeneratorFunction"
LIT_MAGIC_STRING_UINT8_CLAMPED_ARRAY_UL = "Uint8ClampedArray"
LIT_MAGIC_STRING_GET_TIMEZONE_OFFSET_UL = "getTimezoneOffset"
LIT_MAGIC_STRING_PREVENT_EXTENSIONS_UL = "preventExtensions"
+14 -1
View File
@@ -1915,7 +1915,20 @@ parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
error_location_p->error = PARSER_ERR_NO_ERROR;
}
context.status_flags = (arg_list_p == NULL) ? 0 : PARSER_IS_FUNCTION;
if (arg_list_p == NULL)
{
context.status_flags = 0;
}
else
{
context.status_flags = PARSER_IS_FUNCTION;
#if ENABLED (JERRY_ES2015)
if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)
{
context.status_flags |= PARSER_IS_GENERATOR_FUNCTION;
}
#endif /* ENABLED (JERRY_ES2015) */
}
#if ENABLED (JERRY_ES2015)
context.status_flags |= PARSER_GET_CLASS_PARSER_OPTS (parse_opts);
-1
View File
@@ -3071,7 +3071,6 @@ scan_completed:
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (scanner_context.active_binding_list_p == NULL);
JERRY_ASSERT (!(context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION));
#endif /* ENABLED (JERRY_ES2015) */
JERRY_ASSERT (scanner_context.active_literal_pool_p == NULL);
+6 -1
View File
@@ -571,10 +571,15 @@ opfunc_create_executable_object (vm_frame_ctx_t *frame_ctx_p) /**< frame context
size_t total_size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t));
ecma_object_t *object_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE),
ecma_object_t *proto_p = ecma_op_get_prototype_from_constructor (JERRY_CONTEXT (current_function_obj_p),
ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE);
ecma_object_t *object_p = ecma_create_object (proto_p,
total_size,
ECMA_OBJECT_TYPE_CLASS);
ecma_deref_object (proto_p);
vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
executable_object_p->extended_object.u.class_prop.class_id = LIT_MAGIC_STRING_GENERATOR_UL;
+19 -9
View File
@@ -414,19 +414,22 @@ vm_construct_literal_object (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
ecma_object_t *func_obj_p;
#if ENABLED (JERRY_ES2015)
if (!(bytecode_p->status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION))
{
#endif /* ENABLED (JERRY_ES2015) */
func_obj_p = ecma_op_create_function_object (frame_ctx_p->lex_env_p,
bytecode_p);
#if ENABLED (JERRY_ES2015)
}
else
if (bytecode_p->status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION)
{
func_obj_p = ecma_op_create_arrow_function_object (frame_ctx_p->lex_env_p,
bytecode_p,
frame_ctx_p->this_binding);
}
else if (bytecode_p->status_flags & CBC_CODE_FLAGS_GENERATOR)
{
func_obj_p = ecma_op_create_generator_function_object (frame_ctx_p->lex_env_p, bytecode_p);
}
else
{
#endif /* ENABLED (JERRY_ES2015) */
func_obj_p = ecma_op_create_simple_function_object (frame_ctx_p->lex_env_p, bytecode_p);
#if ENABLED (JERRY_ES2015)
}
#endif /* ENABLED (JERRY_ES2015) */
return ecma_make_object_value (func_obj_p);
@@ -2077,7 +2080,14 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
frame_ctx_p->call_operation = VM_EXEC_RETURN;
frame_ctx_p->byte_code_p = byte_code_p;
frame_ctx_p->stack_top_p = stack_top_p;
return opfunc_create_executable_object (frame_ctx_p);
result = opfunc_create_executable_object (frame_ctx_p);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
return result;
}
case VM_OC_YIELD:
{
+97
View File
@@ -0,0 +1,97 @@
// 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.
// Test %GeneratorPrototype%
(function () {
function* generatorFn(){}
var ownProto = Object.getPrototypeOf(generatorFn());
var sharedProto = Object.getPrototypeOf(ownProto);
assert(ownProto === generatorFn.prototype);
assert(sharedProto !== Object.prototype);
assert(sharedProto === Object.getPrototypeOf(function*(){}.prototype));
assert(sharedProto.hasOwnProperty('next'));
})();
// Test %GeneratorPrototype% prototype chain
(function () {
function* generatorFn(){}
var g = generatorFn();
var ownProto = Object.getPrototypeOf(g);
var sharedProto = Object.getPrototypeOf(ownProto);
var iterProto = Object.getPrototypeOf(sharedProto);
assert(ownProto === generatorFn.prototype);
assert(iterProto.hasOwnProperty(Symbol.iterator));
assert(!sharedProto.hasOwnProperty(Symbol.iterator));
assert(!ownProto.hasOwnProperty(Symbol.iterator));
assert(g[Symbol.iterator]() === g);
})();
// Test %GeneratorPrototype% prototype chain
(function () {
function* g(){}
var iterator = new g.constructor("a","b","c","yield a; yield b; yield c;")(1,2,3);
var item = iterator.next();
assert(item.value === 1);
assert(item.done === false);
item = iterator.next();
assert(item.value === 2);
assert(item.done === false);
item = iterator.next();
assert(item.value === 3);
assert(item.done === false);
item = iterator.next();
assert(item.value === undefined);
assert(item.done === true);
assert(g.constructor === (function*(){}).constructor);
})();
// Test GeneratorFunction parsing
(function () {
function *f() {};
try {
Object.getPrototypeOf(f).constructor("yield", "");
} catch (e) {
assert(e instanceof SyntaxError);
}
})();
// Test correct property membership
(function () {
function *f() {};
Object.getPrototypeOf(f).xx = 5;
assert(Object.getPrototypeOf(f).prototype.constructor.xx === 5);
})();
// Test GetPrototypeFromConstructor
(function () {
function *f() {};
var originalProto = f.prototype;
f.prototype = 5;
assert(Object.getPrototypeOf(f()) === Object.getPrototypeOf(originalProto));
var fakeProto = { x : 6 };
f.prototype = fakeProto;
assert(Object.getPrototypeOf(f()) === fakeProto);
assert(f.next === undefined);
})();
+4
View File
@@ -29,6 +29,10 @@ catch (e)
assert (e instanceof ReferenceError);
}
var singleArgFunction = new Function ('arg', 'return arg');
assert (singleArgFunction (5) === 5);
for (i = 1; i < 10; i ++)
{
var f = new Function ('a', 'b', 'var q = a; b++; function f (k) {return q + k + b++;}; return f;');