Implement ES2015 Function.prototype[@@hasInstance] (#3225)

Added hasInstance well known symbol implementation for Function.prototype.
This change however does not implement the ES2015 `instanceof` operator changes.

JerryScript-DCO-1.0-Signed-off-by: Peter Gal pgal.u-szeged@partner.samsung.com
JerryScript-DCO-1.0-Signed-off-by: Dániel Vince vinced@inf.u-szeged.hu
This commit is contained in:
Daniel Vince
2019-10-21 11:04:12 +02:00
committed by Dániel Bátyai
parent d60587f838
commit d85988af96
7 changed files with 179 additions and 0 deletions
@@ -44,6 +44,9 @@ enum
ECMA_FUNCTION_PROTOTYPE_CALL,
ECMA_FUNCTION_PROTOTYPE_APPLY,
ECMA_FUNCTION_PROTOTYPE_BIND,
#if ENABLED (JERRY_ES2015_BUILTIN)
ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE,
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
};
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-function-prototype.inc.h"
@@ -350,6 +353,12 @@ ecma_builtin_function_prototype_dispatch_routine (uint16_t builtin_routine_id, /
{
return ecma_builtin_function_prototype_object_bind (func_obj_p, arguments_list_p, arguments_number);
}
#if ENABLED (JERRY_ES2015_BUILTIN)
case ECMA_FUNCTION_PROTOTYPE_SYMBOL_HAS_INSTANCE:
{
return ecma_op_object_has_instance (func_obj_p, arguments_list_p[0]);
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
default:
{
JERRY_UNREACHABLE ();
@@ -42,4 +42,12 @@ ROUTINE (LIT_MAGIC_STRING_APPLY, ECMA_FUNCTION_PROTOTYPE_APPLY, 2, 2)
ROUTINE (LIT_MAGIC_STRING_CALL, ECMA_FUNCTION_PROTOTYPE_CALL, NON_FIXED, 1)
ROUTINE (LIT_MAGIC_STRING_BIND, ECMA_FUNCTION_PROTOTYPE_BIND, NON_FIXED, 1)
#if ENABLED (JERRY_ES2015_BUILTIN)
/**
* ECMA-262 v6.0 19.2.3.6 @@hasInstance
* 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 */)
#endif /* ENABLED (JERRY_ES2015_BUILTIN) */
#include "ecma-builtin-helpers-macro-undefs.inc.h"
@@ -43,6 +43,10 @@
#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value)
#endif /* !ROUTINE_CONFIGURABLE_ONLY */
#ifndef ROUTINE_WITH_FLAGS
#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags)
#endif /* !ROUTINE_WITH_FLAGS */
#ifndef ACCESSOR_READ_WRITE
#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes)
#endif /* !ACCESSOR_READ_WRITE */
@@ -22,5 +22,6 @@
#undef OBJECT_VALUE
#undef ROUTINE
#undef ROUTINE_CONFIGURABLE_ONLY
#undef ROUTINE_WITH_FLAGS
#undef ACCESSOR_READ_WRITE
#undef ACCESSOR_READ_ONLY
@@ -45,6 +45,8 @@
static ecma_value_t c_function_name (ROUTINE_ARG_LIST_ ## args_number);
#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \
static ecma_value_t c_function_name (ROUTINE_ARG_LIST_ ## args_number);
#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \
static ecma_value_t c_function_name (ROUTINE_ARG_LIST_ ## args_number);
#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \
static ecma_value_t c_getter_func_name (ROUTINE_ARG_LIST_0); \
static ecma_value_t c_setter_func_name (ROUTINE_ARG_LIST_1);
@@ -68,6 +70,8 @@ enum
ECMA_ROUTINE_ ## name ## c_function_name,
#define ROUTINE_CONFIGURABLE_ONLY(name, c_function_name, args_number, length_prop_value) \
ECMA_ROUTINE_ ## name ## c_function_name,
#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \
ECMA_ROUTINE_ ## name ## c_function_name,
#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \
ECMA_ACCESSOR_ ## name ## c_getter_func_name, \
ECMA_ACCESSOR_ ## name ## c_setter_func_name,
@@ -98,6 +102,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] =
ECMA_PROPERTY_FLAG_CONFIGURABLE, \
ECMA_ROUTINE_VALUE (ECMA_ROUTINE_ ## name ## c_function_name, length_prop_value) \
},
#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \
{ \
name, \
ECMA_BUILTIN_PROPERTY_ROUTINE, \
flags, \
ECMA_ROUTINE_VALUE (ECMA_ROUTINE_ ## name ## c_function_name, length_prop_value) \
},
#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \
{ \
name, \
@@ -120,6 +131,13 @@ const ecma_builtin_property_descriptor_t PROPERTY_DESCRIPTOR_LIST_NAME[] =
ECMA_PROPERTY_FLAG_CONFIGURABLE, \
ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) \
},
#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \
{ \
name, \
ECMA_BUILTIN_PROPERTY_ROUTINE, \
flags, \
ECMA_ROUTINE_VALUE (c_function_name, length_prop_value) \
},
#define ACCESSOR_READ_ONLY(name, c_getter_func_name, prop_attributes) \
{ \
name, \
@@ -222,6 +240,11 @@ DISPATCH_ROUTINE_ROUTINE_NAME (uint16_t builtin_routine_id, /**< built-in wide r
{ \
return c_function_name (this_arg_value ROUTINE_ARG_LIST_ ## args_number); \
}
#define ROUTINE_WITH_FLAGS(name, c_function_name, args_number, length_prop_value, flags) \
case ECMA_ROUTINE_ ## name ## c_function_name: \
{ \
return c_function_name (this_arg_value ROUTINE_ARG_LIST_ ## args_number); \
}
#define ACCESSOR_READ_WRITE(name, c_getter_func_name, c_setter_func_name, prop_attributes) \
case ECMA_ACCESSOR_ ## name ## c_getter_func_name: \
{ \
@@ -0,0 +1,53 @@
// 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.
class base {
constructor (value) {
this.member = value;
}
method () {
return this.member;
}
}
class sub {
constructor (value) {
this.member = value;
}
}
var obj_base = new base (3);
var obj_sub = new sub (4);
assert (base[Symbol.hasInstance](obj_base) === true);
assert (base[Symbol.hasInstance](obj_sub) === false);
assert (sub[Symbol.hasInstance](obj_base) === false);
assert (sub[Symbol.hasInstance](obj_sub) === true);
class sub_c extends base {
constructor (value) {
super(value);
this.member = value;
}
}
var obj_sub_c = new sub_c (5);
assert (base[Symbol.hasInstance](obj_sub_c) === true);
assert (sub_c[Symbol.hasInstance](obj_base) === false);
assert (sub_c[Symbol.hasInstance](obj_sub_c) === true);
@@ -0,0 +1,81 @@
// 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.
function base (value) {
this.member = value;
}
base.prototype.method = function () { return this.member; }
function sub (value) {
this.member = value;
}
sub.prototype = base;
var obj_base = new base (3);
var obj_sub = new sub (4);
assert (base[Symbol.hasInstance] (obj_base) === true);
assert (base[Symbol.hasInstance] (obj_sub) === false);
assert (Object[Symbol.hasInstance] (obj_base) === true);
assert (Object[Symbol.hasInstance] (obj_sub) === true);
assert (obj_base.method () === 3);
assert (sub[Symbol.hasInstance] (obj_base) === false);
assert (sub[Symbol.hasInstance] (obj_sub) === true);
assert (obj_sub.method === undefined);
function sub_c (value) {
this.member = value;
}
sub_c.prototype = Object.create (base.prototype)
sub_c.prototype.constructor = sub_c
var obj_sub_c = new sub_c (5);
assert (base[Symbol.hasInstance] (obj_sub_c) === true);
assert (sub_c[Symbol.hasInstance] (obj_base) === false);
assert (sub_c[Symbol.hasInstance] (obj_sub_c) === true);
assert (Object[Symbol.hasInstance] (obj_sub_c) === true);
assert (Function.prototype[Symbol.hasInstance].call (sub_c, obj_sub_c) === true);
assert (obj_sub_c.method () === 5);
assert (base[Symbol.hasInstance] (3) === false);
assert (Number[Symbol.hasInstance] (33) === false);
assert (Number[Symbol.hasInstance] (new Number (33)) === true);
assert (Object[Symbol.hasInstance] (44) === false);
assert (Object[Symbol.hasInstance] (new Number (22)) === true);
assert (base[Symbol.hasInstance] ('demo') === false);
assert (String[Symbol.hasInstance] ('demo') === false);
assert (String[Symbol.hasInstance] (new String ('demo')) === true);
assert (Object[Symbol.hasInstance] ('demo') === false);
assert (Object[Symbol.hasInstance] (new String ('demo')) === true);
assert (base[Symbol.hasInstance] ([]) === false);
assert (base[Symbol.hasInstance] ([1, 2]) === false);
assert (Array[Symbol.hasInstance] ([1, 2]) === true);
assert (Array[Symbol.hasInstance] (new Array(1, 2)) === true);
assert (Object[Symbol.hasInstance] ([]) === true);
assert (Object[Symbol.hasInstance] (new Array()) === true);
assert (base[Symbol.hasInstance] (new RegExp('abc')) === false);
assert (RegExp[Symbol.hasInstance] (/abc/) === true);
assert (RegExp[Symbol.hasInstance] (new RegExp('abc')) === true);
assert (Object[Symbol.hasInstance] (/abc/) === true);