Repository: robertkrimen/otto
Pull request #518 (2024-04-10 21:14:03)

Support Object.values()
This adds support for `Object.values()`, alongside tests

rorymalcolm: It seems likely we need to bump the Go version of this project - I can do that this week
stevenh: Could you rebase to pickup the fix for the check failures please @rorymalcolm 
rorymalcolm: > Could you rebase to pickup the fix for the check failures please @rorymalcolm

Done - was going to try get https://github.com/rorymalcolm/otto/pull/1 up today but you beat me to it - thanks so much!


Patch:
diff --git a/builtin_object.go b/builtin_object.go
index 029a75f..82da2cf 100644
--- a/builtin_object.go
+++ b/builtin_object.go
@@ -273,6 +273,17 @@ func builtinObjectKeys(call FunctionCall) Value {
 	panic(call.runtime.panicTypeError("Object.Keys is nil"))
 }
 
+func builtinObjectValues(call FunctionCall) Value {
+	if obj, values := call.Argument(0).object(), []Value(nil); nil != obj {
+		obj.enumerate(false, func(name string) bool {
+			values = append(values, obj.get(name))
+			return true
+		})
+		return objectValue(call.runtime.newArrayOf(values))
+	}
+	panic(call.runtime.panicTypeError("Object.Values is nil"))
+}
+
 func builtinObjectGetOwnPropertyNames(call FunctionCall) Value {
 	if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj {
 		obj.enumerate(true, func(name string) bool {
diff --git a/inline.go b/inline.go
index 51f7f44..30e00be 100644
--- a/inline.go
+++ b/inline.go
@@ -902,6 +902,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"values": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "values",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "values",
+							call: builtinObjectValues,
+						},
+					},
+				},
+			},
 			"getOwnPropertyNames": {
 				mode: 0o101,
 				value: Value{
@@ -955,6 +992,7 @@ func (rt *runtime) newContext() {
 			"isFrozen",
 			"freeze",
 			"keys",
+			"values",
 			"getOwnPropertyNames",
 		},
 	}
diff --git a/tools/gen-jscore/.gen-jscore.yaml b/tools/gen-jscore/.gen-jscore.yaml
index 524df5e..5bca766 100644
--- a/tools/gen-jscore/.gen-jscore.yaml
+++ b/tools/gen-jscore/.gen-jscore.yaml
@@ -32,6 +32,8 @@ types:
         function: 1
       - name: keys
         function: 1
+      - name: values
+        function: 1
       - name: getOwnPropertyNames
         function: 1
     prototype:


Test patch:
diff --git a/object_test.go b/object_test.go
index 3af0188..7ff3474 100644
--- a/object_test.go
+++ b/object_test.go
@@ -360,6 +360,40 @@ func TestObject_keys(t *testing.T) {
 	})
 }
 
+func TestObject_values(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Object.values({ abc:"first_example", def:"second_example" })`, "first_example,second_example")
+
+		test(`
+			function abc() {
+				this.abc = "first_example";
+				this.def = "second_example";
+			}
+			Object.values(new abc())
+		`, "first_example,second_example")
+
+		test(`
+			function def() {
+				this.ghi = "third_example"
+			}
+			def.prototype = new abc();
+			Object.values(new def());
+		`, "third_example")
+
+		test(`
+			var arr = [1, 2, 3];
+			Object.values(arr);
+		`, "1,2,3")
+
+		test(`
+			var arr = [{"abc": "first_example"}, {"def": "second_example"}];
+			Object.values(arr);
+		`, "[object Object],[object Object]")
+	})
+}
+
 func TestObject_getOwnPropertyNames(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()