Skip to content

Commit 1e90f83

Browse files
author
Zsolt Borbély
committed
Implement Function.prototype.bind function
JerryScript-DCO-1.0-Signed-off-by: Zsolt Borbély zsborbely.u-szeged@partner.samsung.com
1 parent 92bf785 commit 1e90f83

File tree

6 files changed

+437
-14
lines changed

6 files changed

+437
-14
lines changed

jerry-core/ecma/base/ecma-gc.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,9 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
331331
case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */
332332
case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
333333
case ECMA_INTERNAL_PROPERTY_REGEXP_BYTECODE:
334+
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION:
335+
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS:
336+
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS:
334337
{
335338
break;
336339
}

jerry-core/ecma/base/ecma-globals.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,11 @@ typedef enum
245245
/** Identifier of implementation-defined extension object */
246246
ECMA_INTERNAL_PROPERTY_EXTENSION_ID,
247247

248+
/** Bound function internal properties **/
249+
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION,
250+
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS,
251+
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS,
252+
248253
/**
249254
* Bit-mask of non-instantiated built-in's properties (bits 0-31)
250255
*/

jerry-core/ecma/base/ecma-helpers.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,23 @@ ecma_free_internal_property (ecma_property_t *property_p) /**< the property */
800800
case ECMA_INTERNAL_PROPERTY_EXTENSION_ID: /* an integer */
801801
case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_0_31: /* an integer (bit-mask) */
802802
case ECMA_INTERNAL_PROPERTY_NON_INSTANTIATED_BUILT_IN_MASK_32_63: /* an integer (bit-mask) */
803+
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION:
804+
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS:
803805
{
804806
break;
805807
}
806808

809+
case ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS:
810+
{
811+
if (property_value != ECMA_NULL_POINTER)
812+
{
813+
ecma_free_values_collection (ECMA_GET_NON_NULL_POINTER (ecma_collection_header_t, property_value),
814+
false);
815+
}
816+
817+
break;
818+
}
819+
807820
case ECMA_INTERNAL_PROPERTY__COUNT: /* not a real internal property type,
808821
* but number of the real internal property types */
809822
{

jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.cpp

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,135 @@ ecma_builtin_function_prototype_object_bind (ecma_value_t this_arg, /**< this ar
226226
const ecma_value_t* arguments_list_p, /**< list of arguments */
227227
ecma_length_t arguments_number) /**< number of arguments */
228228
{
229-
ECMA_BUILTIN_CP_UNIMPLEMENTED (this_arg, arguments_list_p, arguments_number);
229+
ecma_completion_value_t ret_value = ecma_make_empty_completion_value ();
230+
231+
/* 2. */
232+
if (!ecma_op_is_callable (this_arg))
233+
{
234+
ret_value = ecma_make_throw_obj_completion_value (ecma_new_standard_error (ECMA_ERROR_TYPE));
235+
}
236+
else
237+
{
238+
/* 4. 11. 18. */
239+
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
240+
ecma_object_t *function_p = ecma_create_object (prototype_obj_p, true, ECMA_OBJECT_TYPE_BOUND_FUNCTION);
241+
242+
ecma_deref_object (prototype_obj_p);
243+
244+
/* 7. */
245+
ecma_property_t *target_function_prop_p;
246+
target_function_prop_p = ecma_create_internal_property (function_p,
247+
ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_TARGET_FUNCTION);
248+
249+
ecma_object_t *this_arg_obj_p = ecma_get_object_from_value (this_arg);
250+
ECMA_SET_NON_NULL_POINTER (target_function_prop_p->u.internal_property.value, this_arg_obj_p);
251+
252+
/* 8. */
253+
ecma_property_t *bound_this_prop_p;
254+
bound_this_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_THIS);
255+
const ecma_length_t arg_count = arguments_number;
256+
257+
if (arg_count > 0)
258+
{
259+
bound_this_prop_p->u.internal_property.value = ecma_copy_value (arguments_list_p[0], false);
260+
}
261+
else
262+
{
263+
bound_this_prop_p->u.internal_property.value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_UNDEFINED);
264+
}
265+
266+
if (arg_count > 1)
267+
{
268+
ecma_collection_header_t *bound_args_collection_p;
269+
bound_args_collection_p = ecma_new_values_collection (&arguments_list_p[1], arg_count - 1, false);
270+
271+
ecma_property_t *bound_args_prop_p;
272+
bound_args_prop_p = ecma_create_internal_property (function_p, ECMA_INTERNAL_PROPERTY_BOUND_FUNCTION_BOUND_ARGS);
273+
ECMA_SET_NON_NULL_POINTER (bound_args_prop_p->u.internal_property.value, bound_args_collection_p);
274+
}
275+
276+
/*
277+
* [[Class]] property is not stored explicitly for objects of ECMA_OBJECT_TYPE_FUNCTION type.
278+
*
279+
* See also: ecma_object_get_class_name
280+
*/
281+
282+
/* 17. */
283+
ecma_number_t *length_p = ecma_alloc_number ();
284+
*length_p = 0;
285+
286+
ecma_property_descriptor_t length_prop_desc = ecma_make_empty_property_descriptor ();
287+
{
288+
length_prop_desc.is_value_defined = true;
289+
length_prop_desc.value = ecma_make_number_value (length_p);
290+
291+
length_prop_desc.is_writable_defined = true;
292+
length_prop_desc.is_writable = false;
293+
294+
length_prop_desc.is_enumerable_defined = true;
295+
length_prop_desc.is_enumerable = false;
296+
297+
length_prop_desc.is_configurable_defined = true;
298+
length_prop_desc.is_configurable = false;
299+
}
300+
ecma_string_t *magic_string_length_p = ecma_get_magic_string (LIT_MAGIC_STRING_LENGTH);
301+
ecma_completion_value_t completion = ecma_op_object_define_own_property (function_p,
302+
magic_string_length_p,
303+
&length_prop_desc,
304+
false);
305+
306+
JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
307+
|| ecma_is_completion_value_normal_false (completion));
308+
309+
ecma_deref_ecma_string (magic_string_length_p);
310+
ecma_dealloc_number (length_p);
311+
312+
/* 19-21. */
313+
ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER);
314+
315+
ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor ();
316+
{
317+
prop_desc.is_enumerable_defined = true;
318+
prop_desc.is_enumerable = false;
319+
320+
prop_desc.is_configurable_defined = true;
321+
prop_desc.is_configurable = false;
322+
323+
prop_desc.is_get_defined = true;
324+
prop_desc.get_p = thrower_p;
325+
326+
prop_desc.is_set_defined = true;
327+
prop_desc.set_p = thrower_p;
328+
}
329+
330+
ecma_string_t *magic_string_caller_p = ecma_get_magic_string (LIT_MAGIC_STRING_CALLER);
331+
completion = ecma_op_object_define_own_property (function_p,
332+
magic_string_caller_p,
333+
&prop_desc,
334+
false);
335+
336+
JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
337+
|| ecma_is_completion_value_normal_false (completion));
338+
339+
ecma_deref_ecma_string (magic_string_caller_p);
340+
341+
ecma_string_t *magic_string_arguments_p = ecma_get_magic_string (LIT_MAGIC_STRING_ARGUMENTS);
342+
completion = ecma_op_object_define_own_property (function_p,
343+
magic_string_arguments_p,
344+
&prop_desc,
345+
false);
346+
347+
JERRY_ASSERT (ecma_is_completion_value_normal_true (completion)
348+
|| ecma_is_completion_value_normal_false (completion));
349+
350+
ecma_deref_ecma_string (magic_string_arguments_p);
351+
ecma_deref_object (thrower_p);
352+
353+
/* 22. */
354+
ret_value = ecma_make_normal_completion_value (ecma_make_object_value (function_p));
355+
}
356+
357+
return ret_value;
230358
} /* ecma_builtin_function_prototype_object_bind */
231359

232360
/**

0 commit comments

Comments
 (0)