[ES2016] Implement Object.values
authorgskachkov@gmail.com <gskachkov@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Aug 2016 22:32:48 +0000 (22:32 +0000)
committergskachkov@gmail.com <gskachkov@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Aug 2016 22:32:48 +0000 (22:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=160410

Reviewed by Saam Baraty, Yusuke Suzuki.

This patch adds values function to Object that return list of
own values of the object. Patch did according to the point of
spec http://tc39.github.io/ecma262/#sec-object.values

Also patch adds generic builtin intrinsic constants:
@IterationKindKey/@IterationKindValue/@IterationKindKeyValue
that is used in  EnumerableOwnProperties to set Kind of operation
and replace own IterationKind enums in following iterators:
ArrayIterator, MapIterator, and SetIterator

Source/JavaScriptCore:

* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/ObjectConstructor.js:
(globalPrivate.enumerableOwnProperties):
(values):
* bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
* bytecode/BytecodeIntrinsicRegistry.h:
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::getInternalProperties):
* runtime/ArrayIteratorPrototype.h:
* runtime/IterationKind.h: Copied from Source/JavaScriptCore/builtins/ObjectConstructor.js.
* runtime/JSMapIterator.h:
(JSC::JSMapIterator::create):
(JSC::JSMapIterator::next):
(JSC::JSMapIterator::kind):
(JSC::JSMapIterator::JSMapIterator):
* runtime/JSSetIterator.h:
(JSC::JSSetIterator::create):
(JSC::JSSetIterator::next):
(JSC::JSSetIterator::kind):
(JSC::JSSetIterator::JSSetIterator):
* runtime/MapPrototype.cpp:
(JSC::mapProtoFuncValues):
(JSC::mapProtoFuncEntries):
(JSC::mapProtoFuncKeys):
(JSC::privateFuncMapIterator):
* runtime/ObjectConstructor.cpp:
* runtime/SetPrototype.cpp:
(JSC::setProtoFuncValues):
(JSC::setProtoFuncEntries):
(JSC::privateFuncSetIterator):

Source/WebCore:

* ForwardingHeaders/runtime/IterationKind.h: Added.
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):

JSTests:

* stress/object-values.js: Added.
(compare):
(string_appeared_here.forEach):
(const.getInvokedFunctions.):
(const.getInvokedFunctions):
(Array.prototype.push):

LayoutTests:

* js/Object-getOwnPropertyNames-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@204358 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
JSTests/ChangeLog
JSTests/stress/object-values.js [new file with mode: 0644]
LayoutTests/ChangeLog
LayoutTests/js/Object-getOwnPropertyNames-expected.txt
LayoutTests/js/script-tests/Object-getOwnPropertyNames.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/ObjectConstructor.js
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/runtime/ArrayIteratorPrototype.h
Source/JavaScriptCore/runtime/IterationKind.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSMapIterator.h
Source/JavaScriptCore/runtime/JSSetIterator.h
Source/JavaScriptCore/runtime/MapPrototype.cpp
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/SetPrototype.cpp
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/runtime/IterationKind.h [new file with mode: 0644]
Source/WebCore/bindings/js/SerializedScriptValue.cpp

index 07e970f..d0d2240 100644 (file)
@@ -1,3 +1,17 @@
+2016-08-09  Skachkov Oleksandr  <gskachkov@gmail.com>
+
+        [ES2016] Implement Object.values
+        https://bugs.webkit.org/show_bug.cgi?id=160410
+
+        Reviewed by Saam Barati, Yusuke Suzuki.
+
+        * stress/object-values.js: Added.
+        (compare):
+        (string_appeared_here.forEach):
+        (const.getInvokedFunctions.):
+        (const.getInvokedFunctions):
+        (Array.prototype.push):
+
 2016-08-09  Saam Barati  <sbarati@apple.com>
 
         JSBoundFunction should lazily generate its name string
diff --git a/JSTests/stress/object-values.js b/JSTests/stress/object-values.js
new file mode 100644 (file)
index 0000000..d903e55
--- /dev/null
@@ -0,0 +1,112 @@
+var obj = Object.create({ a: "qux", d: "qux" });
+obj.a = "foo"; obj.b = "bar"; obj.c = "baz";
+var values = Object.values(obj);
+var passed = Array.isArray(values) && String(values) === "foo,bar,baz";
+
+if (!passed)
+    throw new Error("Object.values return wrong result.");
+
+var complexObject = {
+    obj : {
+        a: 'x',
+        b: 'y'
+    },
+    primitive : 'z'
+};
+
+passed = false;
+values = Object.values(complexObject);
+
+passed = values.length !== 2 || values[0].a !== 'x' || values[0].a !== 'y' || values[1] !== 'z';
+
+if (!passed)
+    throw new Error("Object.values return wrong result.");
+
+values = Object.values({ a: 'abcdef' });
+
+passed = values.length === 1 || values[0].a !== 'abcdef';
+
+if (!passed)
+    throw new Error("Object.values return wrong result.");
+
+var primitives = [
+    ["string", ['s', 't', 'r', 'i', 'n', 'g']],
+    [42, []],
+    [Symbol("symbol"), []],
+    [true, []],
+    [false, []]
+];
+
+function compare(ax, bx) {
+    if (ax.length !== bx.length)
+        return false;
+    for (var i = 0, iz = ax.length; i < iz; ++i) {
+        if (ax[i] !== bx[i])
+            return false;
+    }
+    return true;
+}
+
+for (var [primitive, expected] of primitives) {
+    var ret = Object.values(primitive);
+    if (!compare(ret, expected))
+        throw new Error("bad value for " + String(primitive) + ": " + String(ret));
+}
+
+[
+    [ null, "TypeError: Object.values requires that input parameter not be null or undefined" ],
+    [ undefined, "TypeError: Object.values requires that input parameter not be null or undefined" ]
+].forEach(function ([value, message]) {
+    var error = null;
+    try {
+        Object.values(value);
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error("error not thrown");
+    if (String(error) !== message)
+        throw new Error("bad error: " + String(error));
+});
+
+const getInvokedFunctions = (obj) => {
+    let arr = []
+    let p = new Proxy(obj, {
+        ownKeys: function(...args) {
+            arr.push("ownKeys");
+            return Reflect.ownKeys(...args);
+        },
+        getOwnPropertyDescriptor: function(...args) {
+            arr.push("getOwnPropertyDescriptor");
+            return Reflect.getOwnPropertyDescriptor(...args);
+        }
+    });
+
+    Object.values(p);
+    return arr;
+};
+
+const arr1 = getInvokedFunctions({});
+passed = arr1.length === 1 && arr1[0] === "ownKeys";
+
+if (!passed)
+    throw new Error("Object.values should invoke ownkeys.");
+
+const arr2 = getInvokedFunctions({a:'foo', b:'boo'});
+passed = arr2.length > 1 && arr2[0] === "ownKeys";
+
+if (!passed)
+    throw new Error("Object.values should invoke ownkeys.");
+
+passed = arr2[1] === "getOwnPropertyDescriptor";
+
+if (!passed)
+    throw new Error("Object.values should get property descriptor.");
+
+Array.prototype.push = function () { throw new Error("Array.prototype.push should not be used during invoking of Object.values.")};
+
+values = Object.values({a:'1-2', b:'3-4'});
+passed = Array.isArray(values) && String(values) === "1-2,3-4";
+
+if (!passed)
+    throw new Error("Object.values return wrong result.");
\ No newline at end of file
index d413df8..9fa12ce 100644 (file)
@@ -1,3 +1,13 @@
+2016-08-09  Skachkov Oleksandr  <gskachkov@gmail.com>
+
+        [ES2016] Implement Object.values
+        https://bugs.webkit.org/show_bug.cgi?id=160410
+
+        Reviewed by Saam Barati, Yusuke Suzuki.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/script-tests/Object-getOwnPropertyNames.js:
+
 2016-08-10  Saam Barati  <sbarati@apple.com>
 
         Web Inspector: rebase inspector/model/remote-object-get-properties.html and unskip
index c8abdf1..18ef136 100644 (file)
@@ -41,7 +41,7 @@ PASS getSortedOwnPropertyNames(decodeURI) is ['length', 'name']
 PASS getSortedOwnPropertyNames(decodeURIComponent) is ['length', 'name']
 PASS getSortedOwnPropertyNames(encodeURI) is ['length', 'name']
 PASS getSortedOwnPropertyNames(encodeURIComponent) is ['length', 'name']
-PASS getSortedOwnPropertyNames(Object) is ['assign', 'create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf']
+PASS getSortedOwnPropertyNames(Object) is ['assign', 'create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf', 'values']
 PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']
 PASS getSortedOwnPropertyNames(Function) is ['length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(Function.prototype) is ['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']
index ba1a8ec..6123bb6 100644 (file)
@@ -50,7 +50,7 @@ var expectedPropertyNamesSet = {
     "encodeURI": "['length', 'name']",
     "encodeURIComponent": "['length', 'name']",
 // Built-in ECMA objects
-    "Object": "['assign', 'create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf']",
+    "Object": "['assign', 'create', 'defineProperties', 'defineProperty', 'freeze', 'getOwnPropertyDescriptor', 'getOwnPropertyDescriptors', 'getOwnPropertyNames', 'getOwnPropertySymbols', 'getPrototypeOf', 'is', 'isExtensible', 'isFrozen', 'isSealed', 'keys', 'length', 'name', 'preventExtensions', 'prototype', 'seal', 'setPrototypeOf', 'values']",
     "Object.prototype": "['__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', '__proto__', 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']",
     "Function": "['length', 'name', 'prototype']",
     "Function.prototype": "['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']",
index 358da77..c8c716d 100644 (file)
@@ -1,3 +1,52 @@
+2016-08-09  Skachkov Oleksandr  <gskachkov@gmail.com>
+
+        [ES2016] Implement Object.values
+        https://bugs.webkit.org/show_bug.cgi?id=160410
+
+        Reviewed by Saam Barati, Yusuke Suzuki.
+
+        This patch adds values function to Object that return list of 
+        own values of the object. Patch did according to the point of 
+        spec http://tc39.github.io/ecma262/#sec-object.values
+        
+        Also patch adds generic builtin intrinsic constants: 
+        @IterationKindKey/@IterationKindValue/@IterationKindKeyValue 
+        that is used in  EnumerableOwnProperties to set Kind of operation  
+        and replace own IterationKind enums in following iterators: 
+        ArrayIterator, MapIterator, and SetIterator 
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/ObjectConstructor.js:
+        (globalPrivate.enumerableOwnProperties):
+        (values):
+        * bytecode/BytecodeIntrinsicRegistry.cpp:
+        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::getInternalProperties):
+        * runtime/ArrayIteratorPrototype.h:
+        * runtime/IterationKind.h: Copied from Source/JavaScriptCore/builtins/ObjectConstructor.js.
+        * runtime/JSMapIterator.h:
+        (JSC::JSMapIterator::create):
+        (JSC::JSMapIterator::next):
+        (JSC::JSMapIterator::kind):
+        (JSC::JSMapIterator::JSMapIterator):
+        * runtime/JSSetIterator.h:
+        (JSC::JSSetIterator::create):
+        (JSC::JSSetIterator::next):
+        (JSC::JSSetIterator::kind):
+        (JSC::JSSetIterator::JSSetIterator):
+        * runtime/MapPrototype.cpp:
+        (JSC::mapProtoFuncValues):
+        (JSC::mapProtoFuncEntries):
+        (JSC::mapProtoFuncKeys):
+        (JSC::privateFuncMapIterator):
+        * runtime/ObjectConstructor.cpp:
+        * runtime/SetPrototype.cpp:
+        (JSC::setProtoFuncValues):
+        (JSC::setProtoFuncEntries):
+        (JSC::privateFuncSetIterator):
+
 2016-08-10  Benjamin Poulain  <bpoulain@apple.com>
 
         [JSC] Speed up SparseCollection & related maps
index ac454fd..528115a 100644 (file)
                86F3EEBF168CDE930077B92A /* ObjcRuntimeExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F3EEB616855A5B0077B92A /* ObjcRuntimeExtras.h */; };
                86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */; };
                86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; };
+               8B9F6D561D5912FA001C739F /* IterationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 8B9F6D551D5912FA001C739F /* IterationKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
                90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; };
                90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; };
                93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; };
                86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpMatchesArray.cpp; sourceTree = "<group>"; };
                86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBoundFunction.cpp; sourceTree = "<group>"; };
                86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBoundFunction.h; sourceTree = "<group>"; };
+               8B9F6D551D5912FA001C739F /* IterationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IterationKind.h; sourceTree = "<group>"; };
                90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; };
                90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; };
                93052C320FB792190048FDC3 /* ParserArena.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParserArena.cpp; sourceTree = "<group>"; };
                                A12BBFF11B044A8B00664B69 /* IntlObject.h */,
                                708EBE231CE8F35000453146 /* IntlObjectInlines.h */,
                                86BF642A148DB2B5004DE36A /* Intrinsic.h */,
+                               8B9F6D551D5912FA001C739F /* IterationKind.h */,
                                FE4D55B71AE716CA0052E459 /* IterationStatus.h */,
                                70113D491A8DB093003848C4 /* IteratorOperations.cpp */,
                                70113D4A1A8DB093003848C4 /* IteratorOperations.h */,
                                0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
                                0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */,
                                0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
+                               8B9F6D561D5912FA001C739F /* IterationKind.h in Headers */,
                                0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
                                C2C0F7CE17BBFC5B00464FE4 /* DFGDesiredTransitions.h in Headers */,
                                0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
index 408979b..1718d82 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2016 Oleksandr Skachkov <gskachkov@gmail.com>.
  * Copyright (C) 2015 Jordan Harband. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+@globalPrivate
+function enumerableOwnProperties(object, kind)
+{
+    "use strict";
+
+    const obj = @Object(object);
+    const ownKeys = @Reflect.@ownKeys(obj);
+    const properties = [];
+    for (let i = 0, keysLength = ownKeys.length; i < keysLength; ++i) {
+        let nextKey = ownKeys[i];
+        if (typeof nextKey === 'string') {
+            let descriptor = @Reflect.@getOwnPropertyDescriptor(obj, nextKey);
+            if (descriptor !== @undefined && descriptor.enumerable) {
+                if (kind === @iterationKindValue)
+                    properties.@push(obj[nextKey]);
+            // FIXME: Implement 'key+value' and 'key' cases
+            }
+        }
+    }
+    
+    return properties;
+}
+
+function values(object)
+{
+    "use strict";
+    
+    if (object == null)
+        throw new @TypeError("Object.values requires that input parameter not be null or undefined");
+
+    return @enumerableOwnProperties(object, @iterationKindValue);
+}
+
 function assign(target/*[*/, /*...*/sources/*] */)
 {
     "use strict";
index 47a6d7e..84413d2 100644 (file)
@@ -50,9 +50,9 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
 
     m_undefined.set(m_vm, jsUndefined());
     m_Infinity.set(m_vm, jsDoubleNumber(std::numeric_limits<double>::infinity()));
-    m_arrayIterationKindKey.set(m_vm, jsNumber(ArrayIterateKey));
-    m_arrayIterationKindValue.set(m_vm, jsNumber(ArrayIterateValue));
-    m_arrayIterationKindKeyValue.set(m_vm, jsNumber(ArrayIterateKeyValue));
+    m_iterationKindKey.set(m_vm, jsNumber(IterateKey));
+    m_iterationKindValue.set(m_vm, jsNumber(IterateValue));
+    m_iterationKindKeyValue.set(m_vm, jsNumber(IterateKeyValue));
     m_MAX_STRING_LENGTH.set(m_vm, jsNumber(JSString::MaxLength));
     m_MAX_SAFE_INTEGER.set(m_vm, jsDoubleNumber(maxSafeInteger()));
     m_ModuleFetch.set(m_vm, jsNumber(static_cast<unsigned>(JSModuleLoader::Status::Fetch)));
index 2fc50db..6b01159 100644 (file)
@@ -53,9 +53,9 @@ class Identifier;
 #define JSC_COMMON_BYTECODE_INTRINSIC_CONSTANTS_EACH_NAME(macro) \
     macro(undefined) \
     macro(Infinity) \
-    macro(arrayIterationKindKey) \
-    macro(arrayIterationKindValue) \
-    macro(arrayIterationKindKeyValue) \
+    macro(iterationKindKey) \
+    macro(iterationKindValue) \
+    macro(iterationKindKeyValue) \
     macro(MAX_STRING_LENGTH) \
     macro(MAX_SAFE_INTEGER) \
     macro(ModuleFetch) \
index dd52959..ae49cf7 100644 (file)
@@ -320,13 +320,13 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
     if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(value)) {
         String kind;
         switch (mapIterator->kind()) {
-        case MapIterateKey:
+        case IterateKey:
             kind = ASCIILiteral("key");
             break;
-        case MapIterateValue:
+        case IterateValue:
             kind = ASCIILiteral("value");
             break;
-        case MapIterateKeyValue:
+        case IterateKeyValue:
             kind = ASCIILiteral("key+value");
             break;
         }
@@ -342,13 +342,13 @@ JSValue JSInjectedScriptHost::getInternalProperties(ExecState* exec)
     if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(value)) {
         String kind;
         switch (setIterator->kind()) {
-        case SetIterateKey:
+        case IterateKey:
             kind = ASCIILiteral("key");
             break;
-        case SetIterateValue:
+        case IterateValue:
             kind = ASCIILiteral("value");
             break;
-        case SetIterateKeyValue:
+        case IterateKeyValue:
             kind = ASCIILiteral("key+value");
             break;
         }
index b515c2b..3b647a8 100644 (file)
 #ifndef ArrayIteratorPrototype_h
 #define ArrayIteratorPrototype_h
 
+#include "IterationKind.h"
 #include "JSObject.h"
 
 namespace JSC {
 
-enum ArrayIterationKind : uint32_t {
-    ArrayIterateKey,
-    ArrayIterateValue,
-    ArrayIterateKeyValue
-};
-
 class ArrayIteratorPrototype : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;
diff --git a/Source/JavaScriptCore/runtime/IterationKind.h b/Source/JavaScriptCore/runtime/IterationKind.h
new file mode 100644 (file)
index 0000000..07f1fcf
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  Copyright (C) 2016 Oleksandr Skachkov (gskachkov@gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace JSC {
+    
+enum IterationKind : uint32_t {
+    IterateKey,
+    IterateValue,
+    IterateKeyValue,
+};
+
+    
+} // namespace JSC
index 377d656..7e5403d 100644 (file)
 #ifndef JSMapIterator_h
 #define JSMapIterator_h
 
+#include "IterationKind.h"
 #include "JSMap.h"
 #include "JSObject.h"
 #include "MapData.h"
 
 namespace JSC {
-enum MapIterationKind : uint32_t {
-    MapIterateKey,
-    MapIterateValue,
-    MapIterateKeyValue,
-};
 
 class JSMapIterator : public JSNonFinalObject {
 public:
@@ -48,7 +44,7 @@ public:
         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
 
-    static JSMapIterator* create(VM& vm, Structure* structure, JSMap* iteratedObject, MapIterationKind kind)
+    static JSMapIterator* create(VM& vm, Structure* structure, JSMap* iteratedObject, IterationKind kind)
     {
         JSMapIterator* instance = new (NotNull, allocateCell<JSMapIterator>(vm.heap)) JSMapIterator(vm, structure, iteratedObject, kind);
         instance->finishCreation(vm, iteratedObject);
@@ -61,9 +57,9 @@ public:
         if (!m_iterator.next(pair))
             return false;
 
-        if (m_kind == MapIterateValue)
+        if (m_kind == IterateValue)
             value = pair.value;
-        else if (m_kind == MapIterateKey)
+        else if (m_kind == IterateKey)
             value = pair.key;
         else
             value = createPair(callFrame, pair.key, pair.value);
@@ -86,7 +82,7 @@ public:
         m_iterator.finish();
     }
 
-    MapIterationKind kind() const { return m_kind; }
+    IterationKind kind() const { return m_kind; }
     JSValue iteratedValue() const { return m_map.get(); }
     JSMapIterator* clone(ExecState*);
 
@@ -96,7 +92,7 @@ public:
     }
 
 private:
-    JSMapIterator(VM& vm, Structure* structure, JSMap* iteratedObject, MapIterationKind kind)
+    JSMapIterator(VM& vm, Structure* structure, JSMap* iteratedObject, IterationKind kind)
         : Base(vm, structure)
         , m_iterator(iteratedObject->m_mapData.createIteratorData(this))
         , m_kind(kind)
@@ -109,7 +105,7 @@ private:
 
     WriteBarrier<JSMap> m_map;
     JSMap::MapData::IteratorData m_iterator;
-    MapIterationKind m_kind;
+    IterationKind m_kind;
 };
 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSMapIterator);
 
index b9121de..2097fdb 100644 (file)
 #ifndef JSSetIterator_h
 #define JSSetIterator_h
 
+#include "IterationKind.h"
 #include "JSObject.h"
 #include "JSSet.h"
 
 #include "MapData.h"
 
 namespace JSC {
-enum SetIterationKind : uint32_t {
-    SetIterateKey,
-    SetIterateValue,
-    SetIterateKeyValue,
-};
 
 class JSSetIterator : public JSNonFinalObject {
 public:
@@ -49,7 +45,7 @@ public:
         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
 
-    static JSSetIterator* create(VM& vm, Structure* structure, JSSet* iteratedObject, SetIterationKind kind)
+    static JSSetIterator* create(VM& vm, Structure* structure, JSSet* iteratedObject, IterationKind kind)
     {
         JSSetIterator* instance = new (NotNull, allocateCell<JSSetIterator>(vm.heap)) JSSetIterator(vm, structure, iteratedObject, kind);
         instance->finishCreation(vm, iteratedObject);
@@ -61,7 +57,7 @@ public:
         WTF::KeyValuePair<JSValue, JSValue> pair;
         if (!m_iterator.next(pair))
             return false;
-        if (m_kind == SetIterateValue || m_kind == SetIterateKey)
+        if (m_kind == IterateValue || m_kind == IterateKey)
             value = pair.key;
         else
             value = createPair(callFrame, pair.key, pair.key);
@@ -73,7 +69,7 @@ public:
         m_iterator.finish();
     }
 
-    SetIterationKind kind() const { return m_kind; }
+    IterationKind kind() const { return m_kind; }
     JSValue iteratedValue() const { return m_set.get(); }
     JSSetIterator* clone(ExecState*);
 
@@ -83,7 +79,7 @@ public:
     }
 
 private:
-    JSSetIterator(VM& vm, Structure* structure, JSSet* iteratedObject, SetIterationKind kind)
+    JSSetIterator(VM& vm, Structure* structure, JSSet* iteratedObject, IterationKind kind)
         : Base(vm, structure)
         , m_iterator(iteratedObject->m_setData.createIteratorData(this))
         , m_kind(kind)
@@ -96,7 +92,7 @@ private:
 
     WriteBarrier<JSSet> m_set;
     JSSet::SetData::IteratorData m_iterator;
-    SetIterationKind m_kind;
+    IterationKind m_kind;
 };
 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSSetIterator);
 
index 33c05d5..3f2d530 100644 (file)
@@ -158,7 +158,7 @@ EncodedJSValue JSC_HOST_CALL mapProtoFuncValues(CallFrame* callFrame)
     JSMap* thisObj = jsDynamicCast<JSMap*>(callFrame->thisValue());
     if (!thisObj)
         return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot create a Map value iterator for a non-Map object.")));
-    return JSValue::encode(JSMapIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->mapIteratorStructure(), thisObj, MapIterateValue));
+    return JSValue::encode(JSMapIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->mapIteratorStructure(), thisObj, IterateValue));
 }
 
 EncodedJSValue JSC_HOST_CALL mapProtoFuncEntries(CallFrame* callFrame)
@@ -166,7 +166,7 @@ EncodedJSValue JSC_HOST_CALL mapProtoFuncEntries(CallFrame* callFrame)
     JSMap* thisObj = jsDynamicCast<JSMap*>(callFrame->thisValue());
     if (!thisObj)
         return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot create a Map entry iterator for a non-Map object.")));
-    return JSValue::encode(JSMapIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->mapIteratorStructure(), thisObj, MapIterateKeyValue));
+    return JSValue::encode(JSMapIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->mapIteratorStructure(), thisObj, IterateKeyValue));
 }
 
 EncodedJSValue JSC_HOST_CALL mapProtoFuncKeys(CallFrame* callFrame)
@@ -174,7 +174,7 @@ EncodedJSValue JSC_HOST_CALL mapProtoFuncKeys(CallFrame* callFrame)
     JSMap* thisObj = jsDynamicCast<JSMap*>(callFrame->thisValue());
     if (!thisObj)
         return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot create a Map key iterator for a non-Map object.")));
-    return JSValue::encode(JSMapIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->mapIteratorStructure(), thisObj, MapIterateKey));
+    return JSValue::encode(JSMapIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->mapIteratorStructure(), thisObj, IterateKey));
 }
 
 EncodedJSValue JSC_HOST_CALL privateFuncIsMap(ExecState* exec)
@@ -186,7 +186,7 @@ EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState* exec)
 {
     ASSERT(jsDynamicCast<JSMap*>(exec->uncheckedArgument(0)));
     JSMap* map = jsCast<JSMap*>(exec->uncheckedArgument(0));
-    return JSValue::encode(JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), map, MapIterateKeyValue));
+    return JSValue::encode(JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), map, IterateKeyValue));
 }
 
 EncodedJSValue JSC_HOST_CALL privateFuncMapIteratorNext(ExecState* exec)
index 26a236c..ddaaf3e 100644 (file)
@@ -84,6 +84,7 @@ const ClassInfo ObjectConstructor::s_info = { "Function", &InternalFunction::s_i
   isExtensible              objectConstructorIsExtensible               DontEnum|Function 1
   is                        objectConstructorIs                         DontEnum|Function 2
   assign                    JSBuiltin                                   DontEnum|Function 2
+  values                    JSBuiltin                                   DontEnum|Function 1
 @end
 */
 
index 05e23f4..b17a430 100644 (file)
@@ -144,7 +144,7 @@ EncodedJSValue JSC_HOST_CALL setProtoFuncValues(CallFrame* callFrame)
     JSSet* thisObj = jsDynamicCast<JSSet*>(callFrame->thisValue());
     if (!thisObj)
         return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot create a Set value iterator for a non-Set object.")));
-    return JSValue::encode(JSSetIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->setIteratorStructure(), thisObj, SetIterateValue));
+    return JSValue::encode(JSSetIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->setIteratorStructure(), thisObj, IterateValue));
 }
 
 EncodedJSValue JSC_HOST_CALL setProtoFuncEntries(CallFrame* callFrame)
@@ -152,7 +152,7 @@ EncodedJSValue JSC_HOST_CALL setProtoFuncEntries(CallFrame* callFrame)
     JSSet* thisObj = jsDynamicCast<JSSet*>(callFrame->thisValue());
     if (!thisObj)
         return JSValue::encode(throwTypeError(callFrame, ASCIILiteral("Cannot create a Set entry iterator for a non-Set object.")));
-    return JSValue::encode(JSSetIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->setIteratorStructure(), thisObj, SetIterateKeyValue));
+    return JSValue::encode(JSSetIterator::create(callFrame->vm(), callFrame->callee()->globalObject()->setIteratorStructure(), thisObj, IterateKeyValue));
 }
 
 EncodedJSValue JSC_HOST_CALL privateFuncIsSet(ExecState* exec)
@@ -164,7 +164,7 @@ EncodedJSValue JSC_HOST_CALL privateFuncSetIterator(ExecState* exec)
 {
     ASSERT(jsDynamicCast<JSSet*>(exec->uncheckedArgument(0)));
     JSSet* set = jsCast<JSSet*>(exec->uncheckedArgument(0));
-    return JSValue::encode(JSSetIterator::create(exec->vm(), exec->callee()->globalObject()->setIteratorStructure(), set, SetIterateKey));
+    return JSValue::encode(JSSetIterator::create(exec->vm(), exec->callee()->globalObject()->setIteratorStructure(), set, IterateKey));
 }
 
 EncodedJSValue JSC_HOST_CALL privateFuncSetIteratorNext(ExecState* exec)
index 2b75c70..f0377bb 100644 (file)
@@ -1,3 +1,17 @@
+2016-08-09  Skachkov Oleksandr  <gskachkov@gmail.com>
+
+        [ES2016] Implement Object.values
+        https://bugs.webkit.org/show_bug.cgi?id=160410
+
+        Reviewed by Saam Barati, Yusuke Suzuki.
+
+        No new tests because all tests are implemented in JavaScriptCore 
+        and there is no behavior change.
+
+        * ForwardingHeaders/runtime/IterationKind.h: Added.
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::serialize):
+
 2016-08-10  Anders Carlsson  <andersca@apple.com>
 
         Move more functions to from SQLTransactionBackend to SQLTransaction
diff --git a/Source/WebCore/ForwardingHeaders/runtime/IterationKind.h b/Source/WebCore/ForwardingHeaders/runtime/IterationKind.h
new file mode 100644 (file)
index 0000000..aef6f30
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef WebCore_FWD_IterationKind_h
+#define WebCore_FWD_IterationKind_h
+#include <JavaScriptCore/IterationKind.h>
+#endif
index dbf752e..69c0696 100644 (file)
@@ -60,6 +60,7 @@
 #include <runtime/Error.h>
 #include <runtime/Exception.h>
 #include <runtime/ExceptionHelpers.h>
+#include <runtime/IterationKind.h>
 #include <runtime/JSArrayBuffer.h>
 #include <runtime/JSArrayBufferView.h>
 #include <runtime/JSCInlines.h>
@@ -1354,7 +1355,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                 JSMap* inMap = jsCast<JSMap*>(inValue);
                 if (!startMap(inMap))
                     break;
-                JSMapIterator* iterator = JSMapIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, MapIterateKeyValue);
+                JSMapIterator* iterator = JSMapIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, IterateKeyValue);
                 m_gcBuffer.append(inMap);
                 m_gcBuffer.append(iterator);
                 mapIteratorStack.append(iterator);
@@ -1398,7 +1399,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                 JSSet* inSet = jsCast<JSSet*>(inValue);
                 if (!startSet(inSet))
                     break;
-                JSSetIterator* iterator = JSSetIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, SetIterateKey);
+                JSSetIterator* iterator = JSSetIterator::create(m_exec->vm(), m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, IterateKey);
                 m_gcBuffer.append(inSet);
                 m_gcBuffer.append(iterator);
                 setIteratorStack.append(iterator);