diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c
index 7b4138011..fa7b026e8 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.c
+++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.c
@@ -27,6 +27,10 @@
#include "ecma-objects-general.h"
#include "jrt.h"
#include "ecma-builtin-object.h"
+#if ENABLED (JERRY_ESNEXT)
+#include "ecma-iterator-object.h"
+#include "ecma-function-object.h"
+#endif /* ENABLED (JERRY_ESNEXT) */
#define ECMA_BUILTINS_INTERNAL
#include "ecma-builtins-internal.h"
@@ -56,6 +60,7 @@ enum
ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR,
ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS,
ECMA_OBJECT_ROUTINE_GET_PROTOTYPE_OF,
+ ECMA_OBJECT_ROUTINE_FROM_ENTRIES,
ECMA_OBJECT_ROUTINE_KEYS,
ECMA_OBJECT_ROUTINE_VALUES,
ECMA_OBJECT_ROUTINE_ENTRIES,
@@ -1151,6 +1156,141 @@ ecma_builtin_object_object_is (ecma_value_t arg1, /**< routine's first argument
return ecma_op_same_value (arg1, arg2) ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
} /* ecma_builtin_object_object_is */
+/**
+ * The Object object's 'fromEntries' routine
+ *
+ * See also:
+ * ECMA-262 v10, 19.1.2.7
+ * @return ecma value
+ * Returned value must be freed with ecma_free_value.
+ */
+static ecma_value_t
+ecma_builtin_object_from_entries (ecma_value_t iterator) /**< object's iterator */
+{
+ JERRY_ASSERT (ecma_op_check_object_coercible (iterator));
+ /* 2 */
+ ecma_object_t *object_prototype_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
+ ecma_object_t *obj_p = ecma_create_object (object_prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
+
+ /* 6.a */
+ ecma_value_t next_method;
+ ecma_value_t result = ecma_op_get_iterator (iterator, ECMA_VALUE_SYNC_ITERATOR, &next_method);
+
+ if (ECMA_IS_VALUE_ERROR (result))
+ {
+ ecma_deref_object (obj_p);
+ return result;
+ }
+
+ const ecma_value_t original_iterator = result;
+
+ /* 6.b */
+ while (true)
+ {
+ /* 6.a.i */
+ result = ecma_op_iterator_step (original_iterator, next_method);
+
+ if (ECMA_IS_VALUE_ERROR (result))
+ {
+ goto cleanup_iterator;
+ }
+
+ /* 6.a.ii */
+ if (ecma_is_value_false (result))
+ {
+ break;
+ }
+
+ /* 6.a.iii */
+ const ecma_value_t next = result;
+ result = ecma_op_iterator_value (next);
+ ecma_free_value (next);
+
+ if (ECMA_IS_VALUE_ERROR (result))
+ {
+ goto cleanup_iterator;
+ }
+
+ /* 6.a.iv */
+ if (!ecma_is_value_object (result))
+ {
+ ecma_free_value (result);
+ ecma_raise_type_error (ECMA_ERR_MSG ("Iterator value is not an object."));
+ result = ecma_op_iterator_close (original_iterator);
+ JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result));
+ goto cleanup_iterator;
+ }
+
+ /* 6.a.v-vi */
+ ecma_object_t *next_object_p = ecma_get_object_from_value (result);
+
+ result = ecma_op_object_get_by_index (next_object_p, 0);
+
+ if (ECMA_IS_VALUE_ERROR (result))
+ {
+ ecma_deref_object (next_object_p);
+ ecma_op_iterator_close (original_iterator);
+ goto cleanup_iterator;
+ }
+
+ const ecma_value_t key = result;
+
+ result = ecma_op_object_get_by_index (next_object_p, 1);
+
+ if (ECMA_IS_VALUE_ERROR (result))
+ {
+ ecma_deref_object (next_object_p);
+ ecma_free_value (key);
+ ecma_op_iterator_close (original_iterator);
+ goto cleanup_iterator;
+ }
+
+ /* 6.a.vii */
+ const ecma_value_t value = result;
+ ecma_string_t *property_key = ecma_op_to_property_key (key);
+
+ if (property_key == NULL)
+ {
+ ecma_deref_object (next_object_p);
+ ecma_free_value (key);
+ ecma_op_iterator_close (original_iterator);
+ result = ECMA_VALUE_ERROR;
+ goto cleanup_iterator;
+ }
+
+ ecma_property_value_t *prop;
+ ecma_property_t *property_p = ecma_find_named_property (obj_p, property_key);
+
+ if (property_p == NULL)
+ {
+ prop = ecma_create_named_data_property (obj_p,
+ property_key,
+ ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE,
+ NULL);
+ prop->value = ecma_copy_value_if_not_object (value);
+ }
+ else
+ {
+ ecma_named_data_property_assign_value (obj_p, ECMA_PROPERTY_VALUE_PTR (property_p), value);
+ }
+
+ ecma_deref_ecma_string (property_key);
+ ecma_free_value (key);
+ ecma_free_value (value);
+ ecma_deref_object (next_object_p);
+ }
+
+ ecma_ref_object (obj_p);
+ result = ecma_make_object_value (obj_p);
+
+cleanup_iterator:
+ ecma_free_value (original_iterator);
+ ecma_free_value (next_method);
+ ecma_deref_object (obj_p);
+
+ return result;
+} /* ecma_builtin_object_from_entries */
+
#endif /* ENABLED (JERRY_ESNEXT) */
/**
@@ -1359,6 +1499,11 @@ ecma_builtin_object_dispatch_routine (uint16_t builtin_routine_id, /**< built-in
result = ecma_builtin_object_object_get_own_property_descriptors (obj_p);
break;
}
+ case ECMA_OBJECT_ROUTINE_FROM_ENTRIES:
+ {
+ result = ecma_builtin_object_from_entries (arg1);
+ break;
+ }
#endif /* ENABLED (JERRY_ESNEXT) */
default:
{
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 735d450b2..63df72fbc 100644
--- a/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h
+++ b/jerry-core/ecma/builtin-objects/ecma-builtin-object.inc.h
@@ -61,6 +61,7 @@ ROUTINE (LIT_MAGIC_STRING_KEYS, ECMA_OBJECT_ROUTINE_KEYS, 1, 1)
ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTOR_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTOR, 2, 2)
#if ENABLED (JERRY_ESNEXT)
ROUTINE (LIT_MAGIC_STRING_GET_OWN_PROPERTY_DESCRIPTORS_UL, ECMA_OBJECT_ROUTINE_GET_OWN_PROPERTY_DESCRIPTORS, 1, 1)
+ROUTINE (LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES, ECMA_OBJECT_ROUTINE_FROM_ENTRIES, 1, 1)
#endif /* ENABLED (JERRY_ESNEXT) */
ROUTINE (LIT_MAGIC_STRING_CREATE, ECMA_OBJECT_ROUTINE_CREATE, 2, 2)
ROUTINE (LIT_MAGIC_STRING_DEFINE_PROPERTIES_UL, ECMA_OBJECT_ROUTINE_DEFINE_PROPERTIES, 2, 2)
diff --git a/jerry-core/lit/lit-magic-strings.inc.h b/jerry-core/lit/lit-magic-strings.inc.h
index 0f2a66bc2..12b35397d 100644
--- a/jerry-core/lit/lit-magic-strings.inc.h
+++ b/jerry-core/lit/lit-magic-strings.inc.h
@@ -740,6 +740,7 @@ LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CODE_POINT_AT, "codePointAt")
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_CONSTRUCTOR, "constructor")
#if ENABLED (JERRY_ESNEXT)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_DESCRIPTION, "description")
+LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES, "fromEntries")
#endif
#if ENABLED (JERRY_BUILTIN_DATE)
LIT_MAGIC_STRING_DEF (LIT_MAGIC_STRING_GET_FULL_YEAR_UL, "getFullYear")
diff --git a/jerry-core/lit/lit-magic-strings.ini b/jerry-core/lit/lit-magic-strings.ini
index d3247d76c..8c3ccb635 100644
--- a/jerry-core/lit/lit-magic-strings.ini
+++ b/jerry-core/lit/lit-magic-strings.ini
@@ -297,6 +297,7 @@ LIT_MAGIC_STRING_UINT16_ARRAY_UL = "Uint16Array"
LIT_MAGIC_STRING_UINT32_ARRAY_UL = "Uint32Array"
LIT_MAGIC_STRING_CONSTRUCTOR = "constructor"
LIT_MAGIC_STRING_CODE_POINT_AT = "codePointAt"
+LIT_MAGIC_STRING_OBJECT_FROM_ENTRIES = "fromEntries"
LIT_MAGIC_STRING_GET_FULL_YEAR_UL = "getFullYear"
LIT_MAGIC_STRING_GET_UTC_HOURS_UL = "getUTCHours"
LIT_MAGIC_STRING_GET_UTC_MONTH_UL = "getUTCMonth"
diff --git a/tests/jerry/es.next/object-fromEntries.js b/tests/jerry/es.next/object-fromEntries.js
new file mode 100644
index 000000000..48972e0d2
--- /dev/null
+++ b/tests/jerry/es.next/object-fromEntries.js
@@ -0,0 +1,267 @@
+// 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.
+
+// helper function - simple implementation
+Array.prototype.equals = function (array) {
+ if (this.length != array.length)
+ return false;
+
+ for (var i = 0; i < this.length; i++) {
+ if (this[i] instanceof Array && array[i] instanceof Array) {
+ if (!this[i].equals (array[i]))
+ return false;
+ }
+ else if (this[i] != array[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// converting map to object
+const map = new Map ([ ['foo', 'bar'], ['baz', 42] ]);
+const obj_map = Object.fromEntries (map);
+assert (Object.values (obj_map).equals (["bar", 42]));
+assert (Object.keys (obj_map).equals (["foo", 'baz']));
+
+// converting array to object
+const arr = [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ];
+const obj_arr = Object.fromEntries (arr);
+assert (Object.values (obj_arr).equals (["a", "b", "c"]));
+assert (Object.keys (obj_arr).equals (["0", '1', '2']));
+
+// transfrom object to other object
+const object1 = { a: 1, b: 2, c: 3 };
+const object2 = Object.fromEntries (
+ Object.entries (object1)
+ .map (([ key, val ]) => [ key, val * 2 ])
+);
+assert (Object.keys (object2).equals (["a", "b", "c"]));
+assert (Object.values (object2).equals ([2, 4, 6]));
+
+// map with undefined or null member
+const map2 = new Map ([ ['foo', undefined], ['baz', null] ]);
+const obj_map2 = Object.fromEntries (map2);
+assert (Object.values (obj_map2).equals ([undefined, null]));
+assert (Object.keys(obj_map2).equals (["foo", 'baz']))
+
+// don't have a value
+const map3 = new Map ([ ['foo'], ['baz'] ]);
+const obj_map3 = Object.fromEntries (map3);
+assert (Object.values(obj_map3).equals ([undefined, undefined]));
+assert (Object.keys(obj_map3).equals (["foo", 'baz']));
+
+// empty map
+const map4 = new Map ([]);
+const obj_map4 = Object.fromEntries (map4);
+assert (Object.values(obj_map4).equals ([]));
+assert (Object.keys(obj_map4).equals ([]));
+
+// few invalid argument
+function check_iterator (iterator) {
+ try {
+ Object.fromEntries (iterator);
+ assert (false);
+ } catch (e) {
+ assert (e instanceof TypeError);
+ }
+}
+
+check_iterator (null);
+check_iterator (undefined);
+check_iterator (5);
+check_iterator ()
+
+// closed iterator
+var returned = false;
+var closed_iterable = {
+ [Symbol.iterator]: function () {
+ var advanced = false;
+ return {
+ next: function () {
+ if (advanced) {
+ throw 42 // meaning of life;
+ }
+ advanced = true;
+ return {
+ done: false,
+ value: 'ab',
+ };
+ },
+ return: function () {
+ if (returned) {
+ throw 42 // meaning of life;
+ }
+ returned = true;
+ },
+ };
+ },
+};
+
+check_iterator (closed_iterable)
+assert (returned);
+
+var next_iterable = {
+ [Symbol.iterator]: function () {
+ return {
+ next: function () {
+ return null;
+ },
+ return: function () {
+ throw 42 // meaning of life;
+ },
+ };
+ },
+};
+
+check_iterator (next_iterable)
+
+// uncallable next
+var next_iterable_2 = {
+ [Symbol.iterator]: function () {
+ return {
+ next: null,
+ return: function () {
+ throw 42 // meaning of life;
+ },
+ };
+ },
+};
+
+check_iterator (next_iterable_2)
+
+// get '0' error
+returned = false;
+var iterable_0 = {
+ [Symbol.iterator]: function () {
+ var advanced = false;
+ return {
+ next: function () {
+ if (advanced) {
+ throw 42 // meaning of life;
+ }
+ advanced = true;
+ return {
+ done: false,
+ value: {
+ get '0' () {
+ throw new TypeError ();
+ },
+ get '1' () {
+ return "value";
+ },
+ },
+ };
+ },
+ return: function () {
+ if (returned) {
+ throw 42 // meaning of life;
+ }
+ returned = true;
+ },
+ };
+ },
+};
+
+check_iterator (iterable_0)
+assert (returned);
+
+// error in toPropertyKey
+returned = false;
+var iterable = {
+ [Symbol.iterator]: function () {
+ var advanced = false;
+ return {
+ next: function () {
+ if (advanced) {
+ throw 42 // meaning of life;
+ }
+ advanced = true;
+ return {
+ done: false,
+ value: {
+ 0: {
+ get toString () { throw new TypeError }
+ },
+ get '1' () {
+ return "value";
+ },
+ },
+ };
+ },
+ return: function () {
+ if (returned) {
+ throw 42 // meaning of life;
+ }
+ returned = true;
+ },
+ };
+ },
+};
+
+check_iterator (iterable)
+assert (returned);
+
+// get '1' error
+returned = false;
+var iterable = {
+ [Symbol.iterator]: function () {
+ var advanced = false;
+ return {
+ next: function () {
+ if (advanced) {
+ throw 42 // meaning of life;
+ }
+ advanced = true;
+ return {
+ done: false,
+ value: {
+ get '0' () {
+ return 'key';
+ },
+ get '1' () {
+ throw new TypeError;
+ },
+ },
+ };
+ },
+ return: function () {
+ if (returned) {
+ throw 42 // meaning of life;
+ }
+ returned = true;
+ },
+ };
+ },
+};
+
+check_iterator (iterable)
+assert (returned);
+
+// next value is error
+var iterable = {
+ [Symbol.iterator] () {
+ return {
+ next () {
+ return {
+ get value () {
+ throw new TypeError }
+ }
+ }
+ }
+ }
+ }
+
+check_iterator (iterable)
diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml
index 0b15c7565..5b4a6fbca 100644
--- a/tests/test262-esnext-excludelist.xml
+++ b/tests/test262-esnext-excludelist.xml
@@ -1069,30 +1069,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-