[ES6] Implement Reflect.get
https://bugs.webkit.org/show_bug.cgi?id=147925

Reviewed by Geoffrey Garen.

This patch implements Reflect.get API.
It can take the receiver object as the third argument.
When the receiver is specified and there's a getter for the given property name,
we call the getter with the receiver as the |this| value.

* runtime/ReflectObject.cpp:
(JSC::reflectObjectGet):
* runtime/SparseArrayValueMap.cpp:
(JSC::SparseArrayEntry::get): Deleted.
* runtime/SparseArrayValueMap.h:
* tests/stress/reflect-get.js: Added.
(shouldBe):
(shouldThrow):
(.get shouldThrow):
(.get var):
(get var.object.get hello):
(.get shouldBe):
(get var.object.set hello):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@188532 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/tests/stress/reflect-get.js b/Source/JavaScriptCore/tests/stress/reflect-get.js
new file mode 100644
index 0000000..48419bd
--- /dev/null
+++ b/Source/JavaScriptCore/tests/stress/reflect-get.js
@@ -0,0 +1,91 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, message) {
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error("not thrown.");
+    if (String(error) !== message)
+        throw new Error("bad error: " + String(error));
+}
+
+shouldBe(Reflect.get.length, 2);
+
+shouldThrow(() => {
+    Reflect.get("hello");
+}, `TypeError: Reflect.get requires the first argument be an object`);
+
+var object = { hello: 42 };
+shouldBe(Reflect.get(object, 'hello'), 42);
+shouldBe(Reflect.get(object, 'world'), undefined);
+var proto = [];
+object.__proto__ = proto;
+shouldBe(Reflect.get(object, 'length'), 0);
+
+var array = [ 0, 1, 2 ];
+shouldBe(Reflect.get(array, 0), 0);
+var proto = [ 0, 1, 2, 5, 6 ];
+array.__proto__ = proto;
+shouldBe(Reflect.get(array, 3), 5);
+array.__proto__ = Object.prototype;
+shouldBe(Reflect.get(array, 3), undefined);
+
+var object = {
+    value: 42,
+    world: 200,
+    get hello()
+    {
+        return this.value;
+    }
+};
+shouldBe(Reflect.get(object, 'hello'), 42);
+shouldBe(Reflect.get(object, 'hello', { value: 200 }), 200);
+shouldBe(Reflect.get(object, 'hello', "OK"), undefined);
+shouldBe(Reflect.get(object, 'world'), 200);
+shouldBe(Reflect.get(object, 'world', { value: 200 }), 200);
+shouldBe(Reflect.get(object, 'world', "OK"), 200);
+var value = 400;
+shouldBe(Reflect.get(object, 'hello', null), 400);
+shouldBe(Reflect.get(object, 'hello', undefined), 400);
+
+var object = {
+    value: 42,
+    world: 200,
+    get hello()
+    {
+        "use strict";
+        return this.value;
+    }
+};
+shouldBe(Reflect.get(object, 'hello'), 42);
+shouldBe(Reflect.get(object, 'hello', { value: 200 }), 200);
+shouldBe(Reflect.get(object, 'hello', "OK"), undefined);
+shouldBe(Reflect.get(object, 'world'), 200);
+shouldBe(Reflect.get(object, 'world', { value: 200 }), 200);
+shouldBe(Reflect.get(object, 'world', "OK"), 200);
+
+shouldThrow(() => {
+    Reflect.get(object, 'hello', null);
+}, `TypeError: null is not an object (evaluating 'this.value')`);
+
+shouldThrow(() => {
+    Reflect.get(object, 'hello', undefined);
+}, `TypeError: undefined is not an object (evaluating 'this.value')`);
+
+var object = {
+    value: 42,
+    world: 200,
+    set hello(value)
+    {
+    }
+};
+shouldBe(Reflect.get(object, 'hello'), undefined);
+shouldBe(Reflect.get(object, 'hello', { hello: 42 }), undefined);
+shouldBe(Reflect.get(object, 'ok', { ok: 42 }), undefined);