Add new target support to Function object (#3708)
Added steps 1, 2.c, 3.c, 21, 22 to ecma_op_create_dynamic_function JerryScript-DCO-1.0-Signed-off-by: Adam Szilagyi aszilagy@inf.u-szeged.hu
This commit is contained in:
@@ -208,6 +208,80 @@ ecma_op_create_dynamic_function_arguments_helper (const ecma_value_t *arguments_
|
|||||||
return ecma_stringbuilder_finalize (&builder);
|
return ecma_stringbuilder_finalize (&builder);
|
||||||
} /* ecma_op_create_dynamic_function_arguments_helper */
|
} /* ecma_op_create_dynamic_function_arguments_helper */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function object creation operation.
|
||||||
|
*
|
||||||
|
* See also: ECMA-262 v5, 13.2
|
||||||
|
*
|
||||||
|
* @return pointer to newly created Function object
|
||||||
|
*/
|
||||||
|
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 */
|
||||||
|
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 (proto_id);
|
||||||
|
|
||||||
|
size_t function_object_size = sizeof (ecma_extended_object_t);
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||||
|
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||||
|
{
|
||||||
|
function_object_size = sizeof (ecma_static_function_t);
|
||||||
|
}
|
||||||
|
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||||
|
|
||||||
|
ecma_object_t *func_p = ecma_create_object (prototype_obj_p,
|
||||||
|
function_object_size,
|
||||||
|
ECMA_OBJECT_TYPE_FUNCTION);
|
||||||
|
|
||||||
|
/* 2., 6., 7., 8. */
|
||||||
|
/*
|
||||||
|
* We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object.
|
||||||
|
* Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION
|
||||||
|
* that defines which version of the routine should be used on demand.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 3. */
|
||||||
|
/*
|
||||||
|
* [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type.
|
||||||
|
*
|
||||||
|
* See also: ecma_object_get_class_name
|
||||||
|
*/
|
||||||
|
|
||||||
|
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p;
|
||||||
|
|
||||||
|
/* 9. */
|
||||||
|
ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, scope_p, 0);
|
||||||
|
|
||||||
|
/* 10., 11., 12. */
|
||||||
|
|
||||||
|
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
||||||
|
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
||||||
|
{
|
||||||
|
ext_func_p->u.function.bytecode_cp = ECMA_NULL_POINTER;
|
||||||
|
((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
||||||
|
{
|
||||||
|
ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p);
|
||||||
|
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 14., 15., 16., 17., 18. */
|
||||||
|
/*
|
||||||
|
* 'length' and 'prototype' properties are instantiated lazily
|
||||||
|
*
|
||||||
|
* See also: ecma_op_function_try_to_lazy_instantiate_property
|
||||||
|
*/
|
||||||
|
|
||||||
|
return func_p;
|
||||||
|
} /* ecma_op_create_function_object */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CreateDynamicFunction operation
|
* CreateDynamicFunction operation
|
||||||
*
|
*
|
||||||
@@ -271,20 +345,44 @@ ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< argu
|
|||||||
{
|
{
|
||||||
JERRY_ASSERT (ecma_is_value_true (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 ();
|
ecma_object_t *global_env_p = ecma_get_global_environment ();
|
||||||
|
ecma_builtin_id_t fallback_proto = ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE;
|
||||||
|
|
||||||
#if ENABLED (JERRY_ES2015)
|
#if ENABLED (JERRY_ES2015)
|
||||||
if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)
|
ecma_object_t *new_target_p = JERRY_CONTEXT (current_new_target);
|
||||||
|
bool is_generator_func = parse_opts & ECMA_PARSE_GENERATOR_FUNCTION;
|
||||||
|
|
||||||
|
if (is_generator_func)
|
||||||
{
|
{
|
||||||
func_obj_p = ecma_op_create_generator_function_object (global_env_p, bytecode_data_p);
|
fallback_proto = ECMA_BUILTIN_ID_GENERATOR;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (new_target_p == NULL)
|
||||||
{
|
{
|
||||||
|
if (is_generator_func)
|
||||||
|
{
|
||||||
|
new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_GENERATOR_FUNCTION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new_target_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_object_t *proto = ecma_op_get_prototype_from_constructor (new_target_p, fallback_proto);
|
||||||
|
|
||||||
|
if (JERRY_UNLIKELY (proto == NULL))
|
||||||
|
{
|
||||||
|
ecma_bytecode_deref (bytecode_data_p);
|
||||||
|
return ECMA_VALUE_ERROR;
|
||||||
|
}
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
func_obj_p = ecma_op_create_simple_function_object (global_env_p, bytecode_data_p);
|
|
||||||
|
ecma_object_t *func_obj_p = ecma_op_create_function_object (global_env_p, bytecode_data_p, fallback_proto);
|
||||||
|
|
||||||
#if ENABLED (JERRY_ES2015)
|
#if ENABLED (JERRY_ES2015)
|
||||||
}
|
ECMA_SET_NON_NULL_POINTER (func_obj_p->u2.prototype_cp, proto);
|
||||||
|
ecma_deref_object (proto);
|
||||||
#endif /* ENABLED (JERRY_ES2015) */
|
#endif /* ENABLED (JERRY_ES2015) */
|
||||||
|
|
||||||
ecma_bytecode_deref (bytecode_data_p);
|
ecma_bytecode_deref (bytecode_data_p);
|
||||||
@@ -300,82 +398,6 @@ ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p, /**< argu
|
|||||||
return ret_value;
|
return ret_value;
|
||||||
} /* ecma_op_create_dynamic_function */
|
} /* ecma_op_create_dynamic_function */
|
||||||
|
|
||||||
/**
|
|
||||||
* Function object creation operation.
|
|
||||||
*
|
|
||||||
* See also: ECMA-262 v5, 13.2
|
|
||||||
*
|
|
||||||
* @return pointer to newly created Function object
|
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
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 (proto_id);
|
|
||||||
|
|
||||||
size_t function_object_size = sizeof (ecma_extended_object_t);
|
|
||||||
|
|
||||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
|
||||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
|
||||||
{
|
|
||||||
function_object_size = sizeof (ecma_static_function_t);
|
|
||||||
}
|
|
||||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
|
||||||
|
|
||||||
ecma_object_t *func_p = ecma_create_object (prototype_obj_p,
|
|
||||||
function_object_size,
|
|
||||||
ECMA_OBJECT_TYPE_FUNCTION);
|
|
||||||
|
|
||||||
/* 2., 6., 7., 8. */
|
|
||||||
/*
|
|
||||||
* We don't setup [[Get]], [[Call]], [[Construct]], [[HasInstance]] for each function object.
|
|
||||||
* Instead we set the object's type to ECMA_OBJECT_TYPE_FUNCTION
|
|
||||||
* that defines which version of the routine should be used on demand.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 3. */
|
|
||||||
/*
|
|
||||||
* [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type.
|
|
||||||
*
|
|
||||||
* See also: ecma_object_get_class_name
|
|
||||||
*/
|
|
||||||
|
|
||||||
ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) func_p;
|
|
||||||
|
|
||||||
/* 9. */
|
|
||||||
ECMA_SET_NON_NULL_POINTER_TAG (ext_func_p->u.function.scope_cp, scope_p, 0);
|
|
||||||
|
|
||||||
/* 10., 11., 12. */
|
|
||||||
|
|
||||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
|
||||||
if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION)
|
|
||||||
{
|
|
||||||
ext_func_p->u.function.bytecode_cp = ECMA_NULL_POINTER;
|
|
||||||
((ecma_static_function_t *) func_p)->bytecode_p = bytecode_data_p;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
|
||||||
ECMA_SET_INTERNAL_VALUE_POINTER (ext_func_p->u.function.bytecode_cp, bytecode_data_p);
|
|
||||||
ecma_bytecode_ref ((ecma_compiled_code_t *) bytecode_data_p);
|
|
||||||
#if ENABLED (JERRY_SNAPSHOT_EXEC)
|
|
||||||
}
|
|
||||||
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
|
|
||||||
|
|
||||||
/* 14., 15., 16., 17., 18. */
|
|
||||||
/*
|
|
||||||
* 'length' and 'prototype' properties are instantiated lazily
|
|
||||||
*
|
|
||||||
* See also: ecma_op_function_try_to_lazy_instantiate_property
|
|
||||||
*/
|
|
||||||
|
|
||||||
return func_p;
|
|
||||||
} /* ecma_op_create_function_object */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function object creation operation.
|
* Function object creation operation.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
var get = [];
|
||||||
|
var p = new Proxy(Function, { get: function(o, k) { get.push(k); return o[k]; }});
|
||||||
|
new p;
|
||||||
|
|
||||||
|
assert(get + '' === "prototype");
|
||||||
|
|
||||||
|
var func = function() {}
|
||||||
|
var reflect = Reflect.construct(Function, ['a','b','return a+b'], func);
|
||||||
|
assert(Object.getPrototypeOf(reflect) == func.prototype);
|
||||||
|
|
||||||
|
var o = new Proxy (function f () {}, { get(t,p,r) { if (p == "prototype") { throw 42 }}})
|
||||||
|
|
||||||
|
try {
|
||||||
|
Reflect.construct(Function, [], o);
|
||||||
|
assert(false);
|
||||||
|
} catch (e) {
|
||||||
|
assert(e === 42);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user