Implement the core of the generator functions. (#3368)
Some things are missing: - yield* support - generator definition in object literal - the hidden GeneratorFunction JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
committed by
Dániel Bátyai
parent
14e95a4775
commit
110f75c99d
@@ -293,6 +293,7 @@ ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER)
|
||||
|
||||
/**
|
||||
* Mark objects referenced by Map/Set built-in.
|
||||
*/
|
||||
@@ -359,6 +360,73 @@ ecma_gc_mark_container_object (ecma_object_t *object_p) /**< object */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Mark objects referenced by inactive generator functions, async functions, etc.
|
||||
*/
|
||||
static void
|
||||
ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
|
||||
|
||||
if (!ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p->extended_object.u.class_prop.extra_info))
|
||||
{
|
||||
/* All objects referenced by running executable objects are strong roots,
|
||||
* and a finished executable object cannot refer to other values. */
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_gc_set_object_visited (executable_object_p->frame_ctx.lex_env_p);
|
||||
|
||||
if (ecma_is_value_object (executable_object_p->frame_ctx.this_binding))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->frame_ctx.this_binding));
|
||||
}
|
||||
|
||||
const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p;
|
||||
size_t register_end;
|
||||
|
||||
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
|
||||
register_end = args_p->register_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
|
||||
register_end = args_p->register_end;
|
||||
}
|
||||
|
||||
ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx);
|
||||
ecma_value_t *register_end_p = register_p + register_end;
|
||||
|
||||
while (register_p < register_end_p)
|
||||
{
|
||||
if (ecma_is_value_object (*register_p))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p));
|
||||
}
|
||||
|
||||
register_p++;
|
||||
}
|
||||
|
||||
register_p += executable_object_p->frame_ctx.context_depth;
|
||||
register_end_p = executable_object_p->frame_ctx.stack_top_p;
|
||||
|
||||
while (register_p < register_end_p)
|
||||
{
|
||||
if (ecma_is_value_object (*register_p))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p));
|
||||
}
|
||||
|
||||
register_p++;
|
||||
}
|
||||
} /* ecma_gc_mark_executable_object */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Mark objects as visited starting from specified object as root
|
||||
*/
|
||||
@@ -435,6 +503,13 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case LIT_MAGIC_STRING_GENERATOR_UL:
|
||||
{
|
||||
ecma_gc_mark_executable_object (object_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -641,6 +716,100 @@ ecma_free_fast_access_array (ecma_object_t *object_p) /**< fast access mode arra
|
||||
ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t));
|
||||
} /* ecma_free_fast_access_array */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Free non-objects referenced by inactive generator functions, async functions, etc.
|
||||
*
|
||||
* @return total object size
|
||||
*/
|
||||
static size_t
|
||||
ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */
|
||||
{
|
||||
vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p;
|
||||
size_t size, register_end;
|
||||
|
||||
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
|
||||
{
|
||||
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
|
||||
|
||||
register_end = args_p->register_end;
|
||||
size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
|
||||
|
||||
register_end = args_p->register_end;
|
||||
size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t);
|
||||
}
|
||||
|
||||
size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t));
|
||||
|
||||
JERRY_ASSERT (!(executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_RUNNING));
|
||||
|
||||
ecma_bytecode_deref ((ecma_compiled_code_t *) bytecode_header_p);
|
||||
|
||||
if (executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_COMPLETED)
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
ecma_free_value_if_not_object (executable_object_p->frame_ctx.this_binding);
|
||||
|
||||
ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx);
|
||||
ecma_value_t *register_end_p = register_p + register_end;
|
||||
|
||||
while (register_p < register_end_p)
|
||||
{
|
||||
ecma_free_value_if_not_object (*register_p++);
|
||||
}
|
||||
|
||||
if (executable_object_p->frame_ctx.context_depth > 0)
|
||||
{
|
||||
ecma_value_t *context_end_p = register_p;
|
||||
|
||||
register_p += executable_object_p->frame_ctx.context_depth;
|
||||
|
||||
ecma_value_t *context_top_p = register_p;
|
||||
|
||||
do
|
||||
{
|
||||
context_top_p[-1] &= (uint32_t) ~VM_CONTEXT_HAS_LEX_ENV;
|
||||
|
||||
uint32_t offsets = vm_get_context_value_offsets (context_top_p);
|
||||
|
||||
while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
|
||||
{
|
||||
int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets);
|
||||
|
||||
if (ecma_is_value_object (context_top_p[offset]))
|
||||
{
|
||||
context_top_p[offset] = ECMA_VALUE_UNDEFINED;
|
||||
}
|
||||
|
||||
offsets >>= VM_CONTEXT_OFFSET_SHIFT;
|
||||
}
|
||||
|
||||
context_top_p = vm_stack_context_abort (&executable_object_p->frame_ctx, context_top_p);
|
||||
}
|
||||
while (context_top_p > context_end_p);
|
||||
}
|
||||
|
||||
register_end_p = executable_object_p->frame_ctx.stack_top_p;
|
||||
|
||||
while (register_p < register_end_p)
|
||||
{
|
||||
ecma_free_value_if_not_object (*register_p++);
|
||||
}
|
||||
|
||||
return size;
|
||||
} /* ecma_gc_free_executable_object */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
/**
|
||||
* Free properties of an object
|
||||
*/
|
||||
@@ -930,6 +1099,13 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
case LIT_MAGIC_STRING_GENERATOR_UL:
|
||||
{
|
||||
ext_object_size = ecma_gc_free_executable_object (object_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
default:
|
||||
{
|
||||
/* The undefined id represents an uninitialized class. */
|
||||
|
||||
@@ -1750,6 +1750,35 @@ typedef struct
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/**
|
||||
* Executable (e.g. generator, async) object flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_EXECUTABLE_OBJECT_COMPLETED = (1u << 0), /**< executable object is completed and cannot be resumed */
|
||||
ECMA_EXECUTABLE_OBJECT_RUNNING = (1u << 1), /**< executable object is currently running */
|
||||
} ecma_executable_object_flags_t;
|
||||
|
||||
/**
|
||||
* Checks whether the executable object is waiting for resuming.
|
||||
*/
|
||||
#define ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED(extra_info) \
|
||||
(!((extra_info) & (ECMA_EXECUTABLE_OBJECT_COMPLETED | ECMA_EXECUTABLE_OBJECT_RUNNING)))
|
||||
|
||||
/**
|
||||
* Executable (e.g. generator, async) object flags.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_GENERATOR_NEXT, /**< generator should continue its execution */
|
||||
ECMA_GENERATOR_RETURN, /**< generator should perform a return operation */
|
||||
ECMA_GENERATOR_THROW, /**< generator should perform a throw operation */
|
||||
} ecma_generator_yield_mode_t;
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
|
||||
/**
|
||||
* Description of DataView objects.
|
||||
|
||||
@@ -855,10 +855,10 @@ ecma_fast_copy_value (ecma_value_t value) /**< value description */
|
||||
*
|
||||
* @return copy of the given value
|
||||
*/
|
||||
ecma_value_t
|
||||
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */
|
||||
{
|
||||
if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
|
||||
if (!ecma_is_value_object (value))
|
||||
{
|
||||
return ecma_copy_value (value);
|
||||
}
|
||||
@@ -866,6 +866,30 @@ ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */
|
||||
return value;
|
||||
} /* ecma_copy_value_if_not_object */
|
||||
|
||||
/**
|
||||
* Increase reference counter of a value if it is an object.
|
||||
*/
|
||||
inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_ref_if_object (ecma_value_t value) /**< value description */
|
||||
{
|
||||
if (ecma_is_value_object (value))
|
||||
{
|
||||
ecma_ref_object (ecma_get_object_from_value (value));
|
||||
}
|
||||
} /* ecma_ref_if_object */
|
||||
|
||||
/**
|
||||
* Decrease reference counter of a value if it is an object.
|
||||
*/
|
||||
inline void JERRY_ATTR_ALWAYS_INLINE
|
||||
ecma_deref_if_object (ecma_value_t value) /**< value description */
|
||||
{
|
||||
if (ecma_is_value_object (value))
|
||||
{
|
||||
ecma_deref_object (ecma_get_object_from_value (value));
|
||||
}
|
||||
} /* ecma_deref_if_object */
|
||||
|
||||
/**
|
||||
* Assign a new value to an ecma-value
|
||||
*
|
||||
|
||||
@@ -218,6 +218,8 @@ ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value);
|
||||
ecma_value_t ecma_copy_value (ecma_value_t value);
|
||||
ecma_value_t ecma_fast_copy_value (ecma_value_t value);
|
||||
ecma_value_t ecma_copy_value_if_not_object (ecma_value_t value);
|
||||
void ecma_ref_if_object (ecma_value_t value);
|
||||
void ecma_deref_if_object (ecma_value_t value);
|
||||
ecma_value_t ecma_update_float_number (ecma_value_t float_value, ecma_number_t new_number);
|
||||
void ecma_value_assign_value (ecma_value_t *value_p, ecma_value_t ecma_value);
|
||||
void ecma_value_assign_number (ecma_value_t *value_p, ecma_number_t ecma_number);
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
/* 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-builtins.h"
|
||||
#include "ecma-exceptions.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "ecma-iterator-object.h"
|
||||
#include "opcodes.h"
|
||||
#include "vm-defines.h"
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
#define ECMA_BUILTINS_INTERNAL
|
||||
#include "ecma-builtins-internal.h"
|
||||
|
||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-generator-prototype.inc.h"
|
||||
#define BUILTIN_UNDERSCORED_ID generator_prototype
|
||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||
|
||||
/** \addtogroup ecma ECMA
|
||||
* @{
|
||||
*
|
||||
* \addtogroup ecmabuiltins
|
||||
* @{
|
||||
*
|
||||
* \addtogroup generator ECMA Generator object built-in
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper function for next / return / throw
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_generator_prototype_object_do (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_value_t arg, /**< argument */
|
||||
uint8_t yield_mode) /**< yield mode */
|
||||
{
|
||||
vm_executable_object_t *executable_object_p = NULL;
|
||||
|
||||
if (ecma_is_value_object (this_arg))
|
||||
{
|
||||
ecma_object_t *object_p = ecma_get_object_from_value (this_arg);
|
||||
|
||||
if (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_CLASS)
|
||||
{
|
||||
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
|
||||
|
||||
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_GENERATOR_UL)
|
||||
{
|
||||
executable_object_p = (vm_executable_object_t *) ext_object_p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (executable_object_p == NULL)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a generator object."));
|
||||
}
|
||||
|
||||
if (executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_RUNNING)
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Generator is currently under execution."));
|
||||
}
|
||||
|
||||
if (executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_COMPLETED)
|
||||
{
|
||||
return ecma_create_iter_result_object (ECMA_VALUE_UNDEFINED, ECMA_VALUE_TRUE);
|
||||
}
|
||||
|
||||
executable_object_p->frame_ctx.call_operation = yield_mode;
|
||||
|
||||
ecma_value_t value = opfunc_resume_executable_object (executable_object_p, arg);
|
||||
|
||||
if (JERRY_UNLIKELY (ECMA_IS_VALUE_ERROR (value)))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool done = (executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_COMPLETED);
|
||||
ecma_value_t result = ecma_create_iter_result_object (value, ecma_make_boolean_value (done));
|
||||
|
||||
ecma_fast_free_value (value);
|
||||
return result;
|
||||
} /* ecma_builtin_generator_prototype_object_do */
|
||||
|
||||
/**
|
||||
* The Generator.prototype object's 'next' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 25.3.1.2
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_generator_prototype_object_next (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_value_t next_arg) /**< next argument */
|
||||
{
|
||||
return ecma_builtin_generator_prototype_object_do (this_arg, next_arg, ECMA_GENERATOR_NEXT);
|
||||
} /* ecma_builtin_generator_prototype_object_next */
|
||||
|
||||
/**
|
||||
* The Generator.prototype object's 'return' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 25.3.1.3
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_generator_prototype_object_return (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_value_t return_arg) /**< return argument */
|
||||
{
|
||||
return ecma_builtin_generator_prototype_object_do (this_arg, return_arg, ECMA_GENERATOR_RETURN);
|
||||
} /* ecma_builtin_generator_prototype_object_return */
|
||||
|
||||
/**
|
||||
* The Generator.prototype object's 'throw' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v6, 25.3.1.4
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_builtin_generator_prototype_object_throw (ecma_value_t this_arg, /**< this argument */
|
||||
ecma_value_t throw_arg) /**< throw argument */
|
||||
{
|
||||
return ecma_builtin_generator_prototype_object_do (this_arg, throw_arg, ECMA_GENERATOR_THROW);
|
||||
} /* ecma_builtin_generator_prototype_object_throw */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* 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.prototype built-in description
|
||||
*/
|
||||
|
||||
#include "ecma-builtin-helpers-macro-defines.inc.h"
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
|
||||
/* Object properties:
|
||||
* (property name, object pointer getter) */
|
||||
|
||||
/* ECMA-262 v6, 25.3.1.5 */
|
||||
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
|
||||
LIT_MAGIC_STRING_GENERATOR_UL,
|
||||
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)
|
||||
ROUTINE (LIT_MAGIC_STRING_RETURN, ecma_builtin_generator_prototype_object_return, 1, 1)
|
||||
ROUTINE (LIT_MAGIC_STRING_THROW, ecma_builtin_generator_prototype_object_throw, 1, 1)
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#include "ecma-builtin-helpers-macro-undefs.inc.h"
|
||||
@@ -524,7 +524,14 @@ BUILTIN_ROUTINE (ECMA_BUILTIN_ID_SYMBOL,
|
||||
true,
|
||||
symbol)
|
||||
|
||||
BUILTIN (ECMA_BUILTIN_ID_GENERATOR_PROTOTYPE,
|
||||
ECMA_OBJECT_TYPE_GENERAL,
|
||||
ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE,
|
||||
true,
|
||||
generator_prototype)
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_ITERATOR)
|
||||
/* The %IteratorPrototype% object (ECMA-262 v6, 25.1.2) */
|
||||
BUILTIN (ECMA_BUILTIN_ID_ITERATOR_PROTOTYPE,
|
||||
|
||||
@@ -789,21 +789,24 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
bool free_this_binding = false;
|
||||
|
||||
const ecma_compiled_code_t *bytecode_data_p = ecma_op_function_get_compiled_code (ext_func_p);
|
||||
uint16_t status_flags = bytecode_data_p->status_flags;
|
||||
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
bool is_class_constructor = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_CONSTRUCTOR) != 0;
|
||||
|
||||
if (is_class_constructor && !ecma_op_function_has_construct_flag (arguments_list_p))
|
||||
if (JERRY_UNLIKELY (status_flags & (CBC_CODE_FLAGS_CONSTRUCTOR | CBC_CODE_FLAGS_GENERATOR)))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
|
||||
if ((status_flags & CBC_CODE_FLAGS_CONSTRUCTOR) && !ecma_op_function_has_construct_flag (arguments_list_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
|
||||
}
|
||||
if ((status_flags & CBC_CODE_FLAGS_GENERATOR) && ecma_op_function_has_construct_flag (arguments_list_p))
|
||||
{
|
||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Generator functions cannot be invoked with 'new'."));
|
||||
}
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015) */
|
||||
|
||||
bool is_strict = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) != 0;
|
||||
bool is_no_lex_env = (bytecode_data_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED) != 0;
|
||||
|
||||
/* 1. */
|
||||
if (!is_strict)
|
||||
if (!(status_flags & CBC_CODE_FLAGS_STRICT_MODE))
|
||||
{
|
||||
if (ecma_is_value_undefined (this_binding)
|
||||
|| ecma_is_value_null (this_binding))
|
||||
@@ -825,7 +828,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
|
||||
/* 5. */
|
||||
ecma_object_t *local_env_p;
|
||||
if (is_no_lex_env)
|
||||
if (status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)
|
||||
{
|
||||
local_env_p = scope_p;
|
||||
}
|
||||
@@ -841,7 +844,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
bytecode_data_p);
|
||||
}
|
||||
#if ENABLED (JERRY_ES2015)
|
||||
if (JERRY_UNLIKELY (is_class_constructor))
|
||||
if (JERRY_UNLIKELY (status_flags & CBC_CODE_FLAGS_CONSTRUCTOR))
|
||||
{
|
||||
ecma_op_set_class_this_binding (local_env_p, this_binding);
|
||||
}
|
||||
@@ -854,7 +857,7 @@ ecma_op_function_call (ecma_object_t *func_obj_p, /**< Function object */
|
||||
arguments_list_p,
|
||||
arguments_list_len);
|
||||
|
||||
if (!is_no_lex_env)
|
||||
if (!(status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED))
|
||||
{
|
||||
ecma_deref_object (local_env_p);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user