Fix lazy instantiation of external functions 'prototype' property (#3246)

This patch resolves #2302.

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2019-10-25 15:56:37 +02:00
committed by GitHub
parent 100a012931
commit b7aa21ebc7
4 changed files with 129 additions and 55 deletions
@@ -1204,6 +1204,45 @@ ecma_op_function_construct (ecma_object_t *func_obj_p, /**< Function object */
return this_arg_value;
} /* ecma_op_function_construct */
/**
* Lazy instantiation of 'prototype' property for non-builtin and external functions
*
* @return pointer to newly instantiated property
*/
static ecma_property_t *
ecma_op_lazy_instantiate_prototype_object (ecma_object_t *object_p) /**< the function object */
{
JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION
|| ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_EXTERNAL_FUNCTION);
/* ECMA-262 v5, 13.2, 16-18 */
/* 16. */
ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();
/* 17. */
ecma_property_value_t *constructor_prop_value_p;
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR),
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
constructor_prop_value_p->value = ecma_make_object_value (object_p);
/* 18. */
ecma_property_t *prototype_prop_p;
ecma_property_value_t *prototype_prop_value_p;
prototype_prop_value_p = ecma_create_named_data_property (object_p,
ecma_get_magic_string (LIT_MAGIC_STRING_PROTOTYPE),
ECMA_PROPERTY_FLAG_WRITABLE,
&prototype_prop_p);
prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);
ecma_deref_object (proto_object_p);
return prototype_prop_p;
} /* ecma_op_lazy_instantiate_prototype_object */
/**
* Lazy instantiation of non-builtin ecma function object's properties
*
@@ -1223,35 +1262,7 @@ ecma_op_function_try_to_lazy_instantiate_property (ecma_object_t *object_p, /**<
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE))
{
/* ECMA-262 v5, 13.2, 16-18 */
/* 16. */
ecma_object_t *proto_object_p = ecma_op_create_object_object_noarg ();
/* 17. */
ecma_string_t *magic_string_constructor_p = ecma_get_magic_string (LIT_MAGIC_STRING_CONSTRUCTOR);
ecma_property_value_t *constructor_prop_value_p;
constructor_prop_value_p = ecma_create_named_data_property (proto_object_p,
magic_string_constructor_p,
ECMA_PROPERTY_CONFIGURABLE_WRITABLE,
NULL);
constructor_prop_value_p->value = ecma_make_object_value (object_p);
/* 18. */
ecma_property_t *prototype_prop_p;
ecma_property_value_t *prototype_prop_value_p;
prototype_prop_value_p = ecma_create_named_data_property (object_p,
property_name_p,
ECMA_PROPERTY_FLAG_WRITABLE,
&prototype_prop_p);
prototype_prop_value_p->value = ecma_make_object_value (proto_object_p);
ecma_deref_object (proto_object_p);
return prototype_prop_p;
return ecma_op_lazy_instantiate_prototype_object (object_p);
}
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_CALLER)
@@ -1309,15 +1320,7 @@ ecma_op_external_function_try_to_lazy_instantiate_property (ecma_object_t *objec
if (ecma_compare_ecma_string_to_magic_id (property_name_p, LIT_MAGIC_STRING_PROTOTYPE))
{
ecma_property_t *prototype_prop_p;
ecma_property_value_t *prototype_prop_value_p;
prototype_prop_value_p = ecma_create_named_data_property (object_p,
property_name_p,
ECMA_PROPERTY_FLAG_WRITABLE,
&prototype_prop_p);
prototype_prop_value_p->value = ECMA_VALUE_UNDEFINED;
return prototype_prop_p;
return ecma_op_lazy_instantiate_prototype_object (object_p);
}
return NULL;
-9
View File
@@ -12,15 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
try {
({} instanceof assert);
assert(false);
} catch(e) {
assert(e instanceof TypeError);
}
assert.prototype = {}
try {
assert(!({} instanceof assert));
} catch(e) {
+2 -8
View File
@@ -27,13 +27,7 @@ try {
eval(code);
assert(false);
} catch(e) {
assert(e instanceof TypeError);
}
try {
eval("var x = {}; x instanceof assert;");
assert(false);
} catch(e) {
assert(e instanceof TypeError);
assert(e instanceof ReferenceError);
}
assert (!eval("var x = {}; x instanceof assert;"));
+86
View File
@@ -0,0 +1,86 @@
/* 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.
*/
#include "jerryscript.h"
#include "test-common.h"
static const char instanceof_source[] = "var x = function(o, c) {return (o instanceof c);}; x";
static jerry_value_t
external_function (const jerry_value_t function_obj,
const jerry_value_t this_arg,
const jerry_value_t args_p[],
const jerry_size_t args_count)
{
(void) function_obj;
(void) this_arg;
(void) args_p;
(void) args_count;
return jerry_create_undefined ();
} /* external_function */
static void
test_instanceof (jerry_value_t instanceof,
jerry_value_t constructor)
{
jerry_value_t instance = jerry_construct_object (constructor, NULL, 0);
jerry_value_t args[2] =
{
instance, constructor
};
jerry_value_t undefined = jerry_create_undefined ();
jerry_value_t result = jerry_call_function (instanceof, undefined, args, 2);
jerry_release_value (undefined);
TEST_ASSERT (!jerry_value_is_error (result));
TEST_ASSERT (jerry_value_is_boolean (result));
TEST_ASSERT (jerry_get_boolean_value (result));
jerry_release_value (instance);
jerry_release_value (result);
} /* test_instanceof */
int
main (void)
{
jerry_init (JERRY_INIT_EMPTY);
jerry_value_t instanceof = jerry_eval ((jerry_char_t *) instanceof_source, sizeof (instanceof_source) - 1, true);
/* Test for a native-backed function. */
jerry_value_t constructor = jerry_create_external_function (external_function);
test_instanceof (instanceof, constructor);
jerry_release_value (constructor);
/* Test for a JS constructor. */
jerry_value_t global = jerry_get_global_object ();
jerry_value_t object_name = jerry_create_string ((jerry_char_t *) "Object");
constructor = jerry_get_property (global, object_name);
jerry_release_value (object_name);
jerry_release_value (global);
test_instanceof (instanceof, constructor);
jerry_release_value (constructor);
jerry_release_value (instanceof);
jerry_cleanup ();
return 0;
} /* main */