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:
committed by
Dániel Bátyai
parent
d60587f838
commit
d85988af96
@@ -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);
|
||||
Reference in New Issue
Block a user