diff --git a/jerry-core/ecma/operations/ecma-function-object.c b/jerry-core/ecma/operations/ecma-function-object.c index 1c86db375..e2e7ef9de 100644 --- a/jerry-core/ecma/operations/ecma-function-object.c +++ b/jerry-core/ecma/operations/ecma-function-object.c @@ -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; diff --git a/tests/jerry/function-external.js b/tests/jerry/function-external.js index d6eae3922..b1cc8c310 100644 --- a/tests/jerry/function-external.js +++ b/tests/jerry/function-external.js @@ -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) { diff --git a/tests/jerry/regression-test-issue-736.js b/tests/jerry/regression-test-issue-736.js index 9d31f7365..887357c82 100644 --- a/tests/jerry/regression-test-issue-736.js +++ b/tests/jerry/regression-test-issue-736.js @@ -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;")); diff --git a/tests/unit-core/test-native-instanceof.c b/tests/unit-core/test-native-instanceof.c new file mode 100644 index 000000000..7954c5100 --- /dev/null +++ b/tests/unit-core/test-native-instanceof.c @@ -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 */