Set constructor to prototype for ES2015 Classes (#2818)

JerryScript-DCO-1.0-Signed-off-by: legendecas legendecas@gmail.com
This commit is contained in:
legendecas 2019-04-29 19:36:23 +08:00 committed by László Langó
parent 56b6d3a45d
commit 097e1862d2
5 changed files with 29 additions and 19 deletions

View File

@ -548,8 +548,8 @@
/* Class opcodes */ \
CBC_OPCODE (CBC_EXT_INHERIT_AND_SET_CONSTRUCTOR, CBC_NO_FLAG, 0, \
VM_OC_CLASS_INHERITANCE) \
CBC_OPCODE (CBC_EXT_PUSH_CLASS_CONSTRUCTOR, CBC_NO_FLAG, 1, \
VM_OC_PUSH_CLASS_CONSTRUCTOR | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_EXT_PUSH_CLASS_CONSTRUCTOR_AND_PROTOTYPE, CBC_NO_FLAG, 2, \
VM_OC_PUSH_CLASS_CONSTRUCTOR_AND_PROTOTYPE | VM_OC_PUT_STACK) \
CBC_OPCODE (CBC_EXT_IMPLICIT_CONSTRUCTOR_CALL, CBC_NO_FLAG, 0, \
VM_OC_PUSH_IMPL_CONSTRUCTOR) \
CBC_OPCODE (CBC_EXT_SET_CLASS_LITERAL, CBC_HAS_LITERAL_ARG, 0, \

View File

@ -363,7 +363,6 @@ static void
parser_parse_class_literal (parser_context_t *context_p) /**< context */
{
JERRY_ASSERT (context_p->token.type == LEXER_LEFT_BRACE);
parser_emit_cbc (context_p, CBC_CREATE_OBJECT);
bool super_called = false;
uint32_t status_flags = PARSER_IS_FUNCTION | PARSER_IS_CLOSURE;
@ -605,7 +604,7 @@ parser_parse_class (parser_context_t *context_p, /**< context */
parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
}
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CLASS_CONSTRUCTOR);
parser_emit_cbc_ext (context_p, CBC_EXT_PUSH_CLASS_CONSTRUCTOR_AND_PROTOTYPE);
bool is_strict = context_p->status_flags & PARSER_IS_STRICT;

View File

@ -1384,14 +1384,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_object_t *child_class_p = ecma_get_object_from_value (child_value);
ecma_object_t *child_prototype_class_p = ecma_get_object_from_value (child_prototype_value);
ecma_property_value_t *prop_value_p;
prop_value_p = ecma_create_named_data_property (child_prototype_class_p,
ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
ecma_named_data_property_assign_value (child_prototype_class_p, prop_value_p, child_value);
ecma_object_t *super_class_p = ecma_get_lex_env_binding_object (frame_ctx_p->lex_env_p);
@ -1420,7 +1412,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
continue;
}
case VM_OC_PUSH_CLASS_CONSTRUCTOR:
case VM_OC_PUSH_CLASS_CONSTRUCTOR_AND_PROTOTYPE:
{
ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
@ -1431,7 +1423,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) function_obj_p;
ext_func_obj_p->u.external_handler_cb = ecma_op_function_implicit_constructor_handler_cb;
*stack_top_p++ = ecma_make_object_value (function_obj_p);
ecma_value_t function_obj_value = ecma_make_object_value (function_obj_p);
*stack_top_p++ = function_obj_value;
ecma_object_t *prototype_class_p = ecma_create_object (ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE),
0,
ECMA_OBJECT_TYPE_GENERAL);
*stack_top_p++ = ecma_make_object_value (prototype_class_p);
/* 14.5.14.18 Set constructor to prototype */
ecma_property_value_t *prop_value_p;
prop_value_p = ecma_create_named_data_property (prototype_class_p,
ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
ecma_named_data_property_assign_value (prototype_class_p, prop_value_p, function_obj_value);
continue;
}

View File

@ -215,7 +215,7 @@ typedef enum
#if ENABLED (JERRY_ES2015_CLASS)
VM_OC_CLASS_HERITAGE, /**< create a super class context */
VM_OC_CLASS_INHERITANCE, /**< inherit properties from the 'super' class */
VM_OC_PUSH_CLASS_CONSTRUCTOR, /**< push class constructor */
VM_OC_PUSH_CLASS_CONSTRUCTOR_AND_PROTOTYPE, /**< push class constructor */
VM_OC_SET_CLASS_CONSTRUCTOR, /**< set class constructor to the given function literal */
VM_OC_PUSH_IMPL_CONSTRUCTOR, /**< create implicit class constructor */
VM_OC_CLASS_EXPR_CONTEXT_END, /**< class expression heritage context end */
@ -257,7 +257,7 @@ typedef enum
#if !ENABLED (JERRY_ES2015_CLASS)
VM_OC_CLASS_HERITAGE = VM_OC_NONE, /**< create a super class context */
VM_OC_CLASS_INHERITANCE = VM_OC_NONE, /**< inherit properties from the 'super' class */
VM_OC_PUSH_CLASS_CONSTRUCTOR = VM_OC_NONE, /**< push class constructor */
VM_OC_PUSH_CLASS_CONSTRUCTOR_AND_PROTOTYPE = VM_OC_NONE, /**< push class constructor */
VM_OC_SET_CLASS_CONSTRUCTOR = VM_OC_NONE, /**< set class constructor to the given function literal */
VM_OC_PUSH_IMPL_CONSTRUCTOR = VM_OC_NONE, /**< create implicit class constructor */
VM_OC_CLASS_EXPR_CONTEXT_END = VM_OC_NONE, /**< class expression heritage context end */

View File

@ -68,8 +68,9 @@ class B {
}
var b = new B;
assert(typeof B === "function");
assert(typeof b === "object");
assert (typeof B === "function");
assert (typeof b === "object");
assert (b.constructor === B);
class C {
c1() {
@ -88,6 +89,7 @@ var c = new C;
assert (c.c1() === 5);
assert (c.c2() === undefined);
assert (c["3"]() === 3);
assert (c.constructor === C);
class D {
constructor(d) {
@ -99,7 +101,8 @@ class D {
}
}
var d = new D(5);
assert(d.d1() === 5);
assert (d.d1() === 5);
assert (d.constructor === D);
class E {
constructor(e) {
@ -118,6 +121,7 @@ var e = new E (5);
assert (e.e === 5);
e.e = 10;
assert (e.e === 10);
assert (e.constructor === E);
var F = class ClassF {
constructor(f) {
@ -159,6 +163,7 @@ assert (F.f3(1, 1) === 2);
assert (F.constructor(5) === 5);
assert (F.static(5) === 5);
assert (F["2"](5) === 10);
assert (f.constructor === F);
var G = class {
static set a(a) {