[ES6] Implement Reflect.has
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Aug 2015 18:18:39 +0000 (18:18 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Aug 2015 18:18:39 +0000 (18:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=147875

Reviewed by Sam Weinig.

This patch implements Reflect.has[1].
Since the semantics is the same to the `in` operator in the JS[2],
we can implement it in builtin JS code.

[1]: http://www.ecma-international.org/ecma-262/6.0/#sec-reflect.has
[2]: http://www.ecma-international.org/ecma-262/6.0/#sec-relational-operators-runtime-semantics-evaluation

* builtins/ReflectObject.js:
(has):
* runtime/ReflectObject.cpp:
* tests/stress/reflect-has.js: Added.
(shouldBe):
(shouldThrow):

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

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/ReflectObject.js
Source/JavaScriptCore/runtime/ReflectObject.cpp
Source/JavaScriptCore/tests/stress/reflect-has.js [new file with mode: 0644]

index 4443d4d..cdc3b81 100644 (file)
@@ -1,5 +1,26 @@
 2015-08-11  Yusuke Suzuki  <utatane.tea@gmail.com>
 
+        [ES6] Implement Reflect.has
+        https://bugs.webkit.org/show_bug.cgi?id=147875
+
+        Reviewed by Sam Weinig.
+
+        This patch implements Reflect.has[1].
+        Since the semantics is the same to the `in` operator in the JS[2],
+        we can implement it in builtin JS code.
+
+        [1]: http://www.ecma-international.org/ecma-262/6.0/#sec-reflect.has
+        [2]: http://www.ecma-international.org/ecma-262/6.0/#sec-relational-operators-runtime-semantics-evaluation
+
+        * builtins/ReflectObject.js:
+        (has):
+        * runtime/ReflectObject.cpp:
+        * tests/stress/reflect-has.js: Added.
+        (shouldBe):
+        (shouldThrow):
+
+2015-08-11  Yusuke Suzuki  <utatane.tea@gmail.com>
+
         [ES6] Implement Reflect.getPrototypeOf and Reflect.setPrototypeOf
         https://bugs.webkit.org/show_bug.cgi?id=147874
 
index 166af07..804c1e6 100644 (file)
@@ -47,3 +47,12 @@ function deleteProperty(target, propertyKey)
     return delete target[propertyKey];
 }
 
+function has(target, propertyKey)
+{
+    "use strict";
+
+    if (!@isObject(target))
+        throw new @TypeError("Reflect.has requires the first argument be an object");
+
+    return propertyKey in target;
+}
index f06bf1f..275a247 100644 (file)
@@ -57,6 +57,7 @@ const ClassInfo ReflectObject::s_info = { "Reflect", &Base::s_info, &reflectObje
     deleteProperty    reflectObjectDeleteProperty    DontEnum|Function 2
     enumerate         reflectObjectEnumerate         DontEnum|Function 1
     getPrototypeOf    reflectObjectGetPrototypeOf    DontEnum|Function 1
+    has               reflectObjectHas               DontEnum|Function 2
     isExtensible      reflectObjectIsExtensible      DontEnum|Function 1
     ownKeys           reflectObjectOwnKeys           DontEnum|Function 1
     preventExtensions reflectObjectPreventExtensions DontEnum|Function 1
diff --git a/Source/JavaScriptCore/tests/stress/reflect-has.js b/Source/JavaScriptCore/tests/stress/reflect-has.js
new file mode 100644 (file)
index 0000000..21b01fd
--- /dev/null
@@ -0,0 +1,65 @@
+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.has.length, 2);
+
+shouldThrow(() => {
+    Reflect.has("hello", 42);
+}, `TypeError: Reflect.has requires the first argument be an object`);
+
+var object = { hello: 42 };
+shouldBe(Reflect.has(object, 'hello'), true);
+shouldBe(Reflect.has(object, 'world'), false);
+shouldBe(Reflect.has(object, 'prototype'), false);
+shouldBe(Reflect.has(object, '__proto__'), true);
+shouldBe(Reflect.has(object, 'hasOwnProperty'), true);
+shouldBe(Reflect.deleteProperty(object, 'hello'), true);
+shouldBe(Reflect.has(object, 'hello'), false);
+
+shouldBe(Reflect.has([], 'length'), true);
+shouldBe(Reflect.has([0,1,2], 0), true);
+shouldBe(Reflect.has([0,1,2], 200), false);
+
+var object = {
+    [Symbol.iterator]: 42
+};
+shouldBe(Reflect.has(object, Symbol.iterator), true);
+shouldBe(Reflect.has(object, Symbol.unscopables), false);
+shouldBe(Reflect.deleteProperty(object, Symbol.iterator), true);
+shouldBe(Reflect.has(object, Symbol.iterator), false);
+
+var toPropertyKey = {
+    toString() {
+        throw new Error('toString called.');
+    }
+};
+
+shouldThrow(() => {
+    Reflect.has("hello", toPropertyKey);
+}, `TypeError: Reflect.has requires the first argument be an object`);
+
+shouldThrow(() => {
+    Reflect.has({}, toPropertyKey);
+}, `Error: toString called.`);
+
+var toPropertyKey = {
+    toString() {
+        return 'ok';
+    }
+};
+shouldBe(Reflect.has({ 'ok': 42 }, toPropertyKey), true);