From 3c5fb342be4d716c53cf4f98e3e94efc0a50ded3 Mon Sep 17 00:00:00 2001 From: Robert Fancsik Date: Thu, 23 Jan 2020 15:53:37 +0100 Subject: [PATCH] Update "arguments" and "caller" properties of function object to conform ES6 changes (#3530) This patch resolves #3393. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu --- .../ecma-builtin-function-prototype.inc.h | 8 ++++ .../ecma-builtin-helpers-macro-defines.inc.h | 4 ++ .../ecma-builtin-helpers-macro-undefs.inc.h | 1 + ...a-builtin-internal-routines-template.inc.h | 7 +++ .../ecma-builtin-type-error-thrower.c | 7 ++- .../builtin-objects/ecma-builtins-internal.h | 2 + .../ecma/builtin-objects/ecma-builtins.c | 11 +++++ .../ecma/operations/ecma-function-object.c | 15 ++++++ .../jerry/es2015/function-arguments-caller.js | 47 +++++++++++++++++++ 9 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 tests/jerry/es2015/function-arguments-caller.js diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h index 371c54a71..c5d8b1dba 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-function-prototype.inc.h @@ -48,6 +48,14 @@ ROUTINE (LIT_MAGIC_STRING_BIND, ECMA_FUNCTION_PROTOTYPE_BIND, NON_FIXED, 1) * the property attributes are: { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. */ ROUTINE_WITH_FLAGS (LIT_GLOBAL_SYMBOL_HAS_INSTANCE, ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE, 1, 1, 0 /* flags */) +ACCESSOR_BUILTIN_FUNCTION (LIT_MAGIC_STRING_ARGUMENTS, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) +ACCESSOR_BUILTIN_FUNCTION (LIT_MAGIC_STRING_CALLER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_BUILTIN_ID_TYPE_ERROR_THROWER, + ECMA_PROPERTY_FLAG_CONFIGURABLE) #endif /* ENABLED (JERRY_ES2015) */ #include "ecma-builtin-helpers-macro-undefs.inc.h" diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h index 41227d5ac..7c299b8f2 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-defines.inc.h @@ -33,6 +33,10 @@ #ifndef INTRINSIC_PROPERTY #define INTRINSIC_PROPERTY(name, magic_string_id) #endif /* !INTRINSIC_PROPERTY */ + +#ifndef ACCESSOR_BUILTIN_FUNCTION_OBJECT +#define ACCESSOR_BUILTIN_FUNCTION_OBJECT(name, getter_builtin_id, setter_builtin_id, prop_attributes) +#endif /* !ACCESSOR_BUILTIN_FUNCTION_OBJECT */ #endif /* ENABLED (JERRY_ES2015) */ #ifndef OBJECT_VALUE diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h index 0089fdaa1..21616666e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-helpers-macro-undefs.inc.h @@ -19,6 +19,7 @@ #if ENABLED (JERRY_ES2015) #undef SYMBOL_VALUE #undef INTRINSIC_PROPERTY +#undef ACCESSOR_BUILTIN_FUNCTION_OBJECT #endif /* ENABLED (JERRY_ES2015) */ #undef OBJECT_VALUE #undef ROUTINE diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h index 5ca45b828..f1fe9801d 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-internal-routines-template.inc.h @@ -189,6 +189,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] = ECMA_PROPERTY_CONFIGURABLE_WRITABLE, \ magic_string_id \ }, +#define ACCESSOR_BUILTIN_FUNCTION(name, getter_builtin_id, setter_builtin_id, prop_attributes) \ + { \ + name, \ + ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION, \ + prop_attributes, \ + ECMA_ACCESSOR_READ_WRITE (getter_builtin_id, setter_builtin_id) \ + }, #endif /* ENABLED (JERRY_ES2015) */ #define ACCESSOR_READ_WRITE(name, c_getter_name, c_setter_name, prop_attributes) \ { \ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.c b/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.c index fe58158bb..d6d7c4479 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-type-error-thrower.c @@ -55,8 +55,8 @@ ecma_builtin_type_error_thrower_dispatch_call (const ecma_value_t *arguments_lis { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); - /* The object should throw TypeError */ - return ecma_raise_type_error (ECMA_ERR_MSG ("")); + return ecma_raise_type_error (ECMA_ERR_MSG ("'caller', 'callee', and 'arguments' properties may not be accessed" + " on strict mode functions or the arguments objects for calls to them")); } /* ecma_builtin_type_error_thrower_dispatch_call */ /** @@ -73,8 +73,7 @@ ecma_builtin_type_error_thrower_dispatch_construct (const ecma_value_t *argument { JERRY_ASSERT (arguments_list_len == 0 || arguments_list_p != NULL); - /* The object is not a constructor */ - return ecma_raise_type_error (ECMA_ERR_MSG ("")); + return ecma_builtin_type_error_thrower_dispatch_call (arguments_list_p, arguments_list_len); } /* ecma_builtin_type_error_thrower_dispatch_construct */ /** diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h index 0efa46ce5..aca0f317e 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtins-internal.h @@ -34,6 +34,8 @@ typedef enum #if ENABLED (JERRY_ES2015) ECMA_BUILTIN_PROPERTY_SYMBOL, /**< symbol value property */ ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY, /**< intrinsic routine property */ + ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION, /**< full accessor property with builtin function object + getter/setter pair */ #endif /* ENABLED (JERRY_ES2015) */ ECMA_BUILTIN_PROPERTY_OBJECT, /**< builtin object property */ ECMA_BUILTIN_PROPERTY_ROUTINE, /**< routine property */ diff --git a/jerry-core/ecma/builtin-objects/ecma-builtins.c b/jerry-core/ecma/builtin-objects/ecma-builtins.c index dd4734173..5e0cd8547 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtins.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtins.c @@ -814,6 +814,17 @@ ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object * (lit_magic_string_id_t) curr_property_p->value); break; } + case ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION: + { + is_accessor = true; + uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value); + uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value); + getter_p = ecma_builtin_get (getter_id); + setter_p = ecma_builtin_get (setter_id); + ecma_ref_object (getter_p); + ecma_ref_object (setter_p); + break; + } #endif /* ENABLED (JERRY_ES2015) */ case ECMA_BUILTIN_PROPERTY_OBJECT: { diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index d36c6a708..e2b152167 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -1643,6 +1643,19 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< } #endif /* ENABLED (JERRY_ES2015) */ +#if ENABLED (JERRY_ES2015) + if (!(bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)) + { + ecma_property_t *value_prop_p; + /* The property_name_p argument contans the name. */ + ecma_property_value_t *value_p = ecma_create_named_data_property (object_p, + property_name_p, + ECMA_PROPERTY_FIXED, + &value_prop_p); + value_p->value = ECMA_VALUE_NULL; + return value_prop_p; + } +#else /* !ENABLED (JERRY_ES2015) */ if (bytecode_data_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE) { ecma_object_t *thrower_p = ecma_builtin_get (ECMA_BUILTIN_ID_TYPE_ERROR_THROWER); @@ -1657,6 +1670,8 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**< &caller_prop_p); return caller_prop_p; } +#endif /* ENABLED (JERRY_ES2015) */ + } return NULL; diff --git a/tests/jerry/es2015/function-arguments-caller.js b/tests/jerry/es2015/function-arguments-caller.js new file mode 100644 index 000000000..3eb2b9582 --- /dev/null +++ b/tests/jerry/es2015/function-arguments-caller.js @@ -0,0 +1,47 @@ +// 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 props = ['arguments', 'caller']; + +function f_simple () { +} + +function f_strict () { + "use strict"; +} + +for (let prop of props) { + try { + Function.prototype[prop]; + assert(false); + } catch (e) { + assert(e instanceof TypeError); + } + + assert(f_simple[prop] === null); + + try { + f_strict[prop]; + assert(false); + } catch (e) { + assert(e instanceof TypeError); + } + + let desc = Object.getOwnPropertyDescriptor(f_simple, prop); + assert(desc.value === null); + assert(desc.writable === false); + assert(desc.enumerable === false); + assert(desc.configurable === false); + assert(Object.getOwnPropertyDescriptor(f_strict, prop) === undefined); +}