diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c index 0020ddf9b..29d45f824 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c @@ -135,6 +135,127 @@ ecma_builtin_object_object_get_prototype_of (ecma_value_t this_arg, /**< 'this' return ret_value; } /* ecma_builtin_object_object_get_prototype_of */ +#ifndef CONFIG_DISABLE_ES2015_BUILTIN +/** + * [[SetPrototypeOf]] + * + * See also: + * ES2015 9.1.2 + */ +static bool +ecma_set_prototype_of (ecma_value_t o_value, /**< O */ + ecma_value_t v_value) /**< V */ +{ + /* 1. */ + JERRY_ASSERT (ecma_is_value_object (o_value)); + JERRY_ASSERT (ecma_is_value_object (v_value) || ecma_is_value_null (v_value)); + + ecma_object_t *o_p = ecma_get_object_from_value (o_value); + ecma_object_t *v_p = ecma_is_value_null (v_value) ? NULL : ecma_get_object_from_value (v_value); + + /* 3., 4. */ + if (v_p == ecma_get_object_prototype (o_p)) + { + return true; + } + + /* 2., 5. */ + if (!ecma_get_object_extensible (o_p)) + { + return false; + } + + /* 6., 7., 8. */ + ecma_object_t *p_p = v_p; + while (true) + { + /* a. */ + if (p_p == NULL) + { + break; + } + + /* b. */ + if (p_p == o_p) + { + return false; + } + + /* c.i. TODO: es2015-subset profile does not support having a different + * [[GetPrototypeOf]] internal method */ + + /* c.ii. */ + p_p = ecma_get_object_prototype (p_p); + } + + /* 9. */ + ECMA_SET_POINTER (o_p->prototype_or_outer_reference_cp, v_p); + + /* 10. */ + return true; +} /* ecma_set_prototype_of */ + +/** + * The Object object's 'setPrototypeOf' routine + * + * See also: + * ES2015 19.1.2.18 + * + * @return ecma value + * Returned value must be freed with ecma_free_value. + */ +static ecma_value_t +ecma_builtin_object_object_set_prototype_of (ecma_value_t this_arg, /**< 'this' argument */ + ecma_value_t arg1, /**< routine's first argument */ + ecma_value_t arg2) /**< routine's second argument */ +{ + JERRY_UNUSED (this_arg); + ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + + /* 1., 2. */ + ECMA_TRY_CATCH (unused_value, + ecma_op_check_object_coercible (arg1), + ret_value); + + /* 3. */ + if (!ecma_is_value_object (arg2) && !ecma_is_value_null (arg2)) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("proto is neither Object nor Null.")); + } + else + { + /* 4. */ + if (!ecma_is_value_object (arg1)) + { + ret_value = ecma_copy_value (arg1); + } + else + { + /* 5. */ + bool status = ecma_set_prototype_of (arg1, arg2); + + /* 6. TODO: es2015-subset profile does not support having a different + * [[SetPrototypeOf]] internal method */ + + /* 7. */ + if (!status) + { + ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("cannot set prototype.")); + } + else + { + /* 8. */ + ret_value = ecma_copy_value (arg1); + } + } + } + + ECMA_FINALIZE (unused_value); + + return ret_value; +} /* ecma_builtin_object_object_set_prototype_of */ +#endif /* !CONFIG_DISABLE_ES2015_BUILTIN */ + /** * The Object object's 'getOwnPropertyNames' routine * diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h index d957c2fb1..7d5de6792 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h @@ -60,6 +60,10 @@ ROUTINE (LIT_MAGIC_STRING_CREATE, ecma_builtin_object_object_create, 2, 2) ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, ecma_builtin_object_object_define_properties, 2, 2) ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, ecma_builtin_object_object_define_property, 3, 3) +#ifndef CONFIG_DISABLE_ES2015_BUILTIN +ROUTINE (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, ecma_builtin_object_object_set_prototype_of, 2, 2) +#endif /* !CONFIG_DISABLE_ES2015_BUILTIN */ + #undef SIMPLE_VALUE #undef NUMBER_VALUE #undef STRING_VALUE diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h index 6a1c45ecb..c5d9ed2ff 100644 --- a/jerry-core/lit/lit-magic-strings.inc.h +++ b/jerry-core/lit/lit-magic-strings.inc.h @@ -262,6 +262,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DEFINE_PROPERTY_UL, "defineProperty") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_PROTOTYPE_OF_UL, "getPrototypeOf") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_UTC_FULL_YEAR_UL, "getUTCFullYear") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_HAS_OWN_PROPERTY_UL, "hasOwnProperty") +LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_PROTOTYPE_OF_UL, "setPrototypeOf") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_SET_UTC_FULL_YEAR_UL, "setUTCFullYear") LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, "toLocaleString") LIT_MAGIC_STRING_FIRST_STRING_WITH_SIZE (15, LIT_MAGIC_STRING_GET_MILLISECONDS_UL) diff --git a/jerry-core/profiles/es5.1.profile b/jerry-core/profiles/es5.1.profile index 533c2349d..8761434ff 100644 --- a/jerry-core/profiles/es5.1.profile +++ b/jerry-core/profiles/es5.1.profile @@ -1,3 +1,3 @@ CONFIG_DISABLE_ARRAYBUFFER_BUILTIN +CONFIG_DISABLE_ES2015_BUILTIN CONFIG_DISABLE_TYPEDARRAY_BUILTIN - diff --git a/jerry-core/profiles/minimal.profile b/jerry-core/profiles/minimal.profile index d7504439b..b5566462c 100644 --- a/jerry-core/profiles/minimal.profile +++ b/jerry-core/profiles/minimal.profile @@ -4,6 +4,7 @@ CONFIG_DISABLE_ARRAY_BUILTIN CONFIG_DISABLE_BOOLEAN_BUILTIN CONFIG_DISABLE_DATE_BUILTIN CONFIG_DISABLE_ERROR_BUILTINS +CONFIG_DISABLE_ES2015_BUILTIN CONFIG_DISABLE_JSON_BUILTIN CONFIG_DISABLE_MATH_BUILTIN CONFIG_DISABLE_NUMBER_BUILTIN @@ -11,4 +12,3 @@ CONFIG_DISABLE_REGEXP_BUILTIN CONFIG_DISABLE_STRING_BUILTIN CONFIG_DISABLE_TYPEDARRAY_BUILTIN CONFIG_DISABLE_UNICODE_CASE_CONVERSION - diff --git a/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-001.js b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-001.js new file mode 100644 index 000000000..4741fc501 --- /dev/null +++ b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-001.js @@ -0,0 +1,41 @@ +/* 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 test_set_prototype_of_error(o, proto, msg) +{ + var name = ""; + + try + { + Object.setPrototypeOf(o, proto); + } + catch (e) + { + name = e.name; + } + + assert(name === "TypeError"); + + if (msg) + { + print(msg + " PASS (XFAIL)"); + } +} + +(function test_incoercible_o(undefined) +{ + test_set_prototype_of_error(undefined, new Object(), "Object.setPrototypeOf(undefined, ...)"); + test_set_prototype_of_error(null, new Object(), "Object.setPrototypeOf(null, ...)"); +})(); diff --git a/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-002.js b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-002.js new file mode 100644 index 000000000..3f1c564b6 --- /dev/null +++ b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-002.js @@ -0,0 +1,43 @@ +/* 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 test_set_prototype_of_error(o, proto, msg) +{ + var name = ""; + + try + { + Object.setPrototypeOf(o, proto); + } + catch (e) + { + name = e.name; + } + + assert(name === "TypeError"); + + if (msg) + { + print(msg + " PASS (XFAIL)"); + } +} + +(function test_nonobject_proto(undefined) +{ + test_set_prototype_of_error(new Object(), undefined, "Object.setPrototypeOf(..., undefined)"); + test_set_prototype_of_error(new Object(), true, "Object.setPrototypeOf(..., boolean)"); + test_set_prototype_of_error(new Object(), 3.14, "Object.setPrototypeOf(..., number)"); + test_set_prototype_of_error(new Object(), "xyz", "Object.setPrototypeOf(..., string)"); +})() diff --git a/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-003.js b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-003.js new file mode 100644 index 000000000..442265e5c --- /dev/null +++ b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-003.js @@ -0,0 +1,31 @@ +/* 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 test_set_prototype_of_success(o, proto, msg) +{ + assert(o === Object.setPrototypeOf(o, proto)); + + if (msg) + { + print(msg + " PASS"); + } +} + +(function test_nonobject_o(undefined) +{ + test_set_prototype_of_success(true, new Object(), "Object.setPrototypeOf(boolean, ...)"); + test_set_prototype_of_success(3.14, new Object(), "Object.setPrototypeOf(number, ...)"); + test_set_prototype_of_success("xyz", new Object(), "Object.setPrototypeOf(string, ...)"); +})() diff --git a/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-004.js b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-004.js new file mode 100644 index 000000000..3e93f7b4d --- /dev/null +++ b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-004.js @@ -0,0 +1,56 @@ +/* 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 test_set_prototype_of_error(o, proto, msg) +{ + var name = ""; + + try + { + Object.setPrototypeOf(o, proto); + } + catch (e) + { + name = e.name; + } + + assert(name === "TypeError"); + + if (msg) + { + print(msg + " PASS (XFAIL)"); + } +} + +function test_set_prototype_of_success_set(o, proto, msg) +{ + assert(o === Object.setPrototypeOf(o, proto)); + assert(proto === Object.getPrototypeOf(o)); + + if (msg) + { + print(msg + " PASS"); + } +} + +(function test_nonextensible_o(undefined) +{ + var o = new Object(); + var o_proto = Object.getPrototypeOf(o); + Object.preventExtensions(o); + + test_set_prototype_of_success_set(o, o_proto, "Object.setPrototypeOf(o_nonext, o_nonext.__proto__)"); + test_set_prototype_of_error(o, new Object(), "Object.setPrototypeOf(o_nonext, ...)"); +})() diff --git a/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-005.js b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-005.js new file mode 100644 index 000000000..98a82aa1e --- /dev/null +++ b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-005.js @@ -0,0 +1,42 @@ +/* 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 test_set_prototype_of_error(o, proto, msg) +{ + var name = ""; + + try + { + Object.setPrototypeOf(o, proto); + } + catch (e) + { + name = e.name; + } + + assert(name === "TypeError"); + + if (msg) + { + print(msg + " PASS (XFAIL)"); + } +} + +(function test_circularity(undefined) +{ + var o = new Object(); + + test_set_prototype_of_error(o, o, "Object.setPrototypeOf(o, o)"); +})() diff --git a/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-006.js b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-006.js new file mode 100644 index 000000000..caa9a2631 --- /dev/null +++ b/tests/jerry-test-suite/es2015/19/19.01/19.01.02/19.01.02-006.js @@ -0,0 +1,31 @@ +/* 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 test_set_prototype_of_success_set(o, proto, msg) +{ + assert(o === Object.setPrototypeOf(o, proto)); + assert(proto === Object.getPrototypeOf(o)); + + if (msg) + { + print(msg + " PASS"); + } +} + +(function test_set_prototype_of(undefined) +{ + test_set_prototype_of_success_set(new Object(), new Object(), "Object.setPrototypeOf(o1, o2)"); + test_set_prototype_of_success_set(new Object(), null, "Object.setPrototypeOf(o, null)"); +})()