test262: test262/test/built-ins/isNaN/toprimitive-not-callable-throws.js
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 16 Apr 2017 20:20:11 +0000 (20:20 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 16 Apr 2017 20:20:11 +0000 (20:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170888

Patch by Joseph Pecoraro <pecoraro@apple.com> on 2017-04-16
Reviewed by Saam Barati.

JSTests:

* stress/computed-accessor.js:
* stress/eval-in-arrow-function.js:
* stress/rest-elements.js:
* stress/string-object-define-own-property.js:
Remove unused shouldThrow.

* stress/symbol-toprimitive-errors.js: Added.
Check for ToPrimitive TypeErrors.

* test262.yaml:

Source/JavaScriptCore:

* runtime/ExceptionHelpers.h:
* runtime/ExceptionHelpers.cpp:
(JSC::createInvalidInstanceofParameterErrorHasInstanceValueNotFunction):
Fix up this function name.

* runtime/JSObject.cpp:
(JSC::callToPrimitiveFunction):
When called with @@isPrimitive, bail on undefined or null and
throw a type error if the value is not callable.

(JSC::JSObject::toPrimitive):
Use throw scope to check for exception.

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

JSTests/ChangeLog
JSTests/stress/computed-accessor.js
JSTests/stress/eval-in-arrow-function.js
JSTests/stress/rest-elements.js
JSTests/stress/string-object-define-own-property.js
JSTests/stress/symbol-toprimitive-errors.js [new file with mode: 0644]
JSTests/test262.yaml
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/ExceptionHelpers.h
Source/JavaScriptCore/runtime/JSObject.cpp

index d8d044a..c5d5881 100644 (file)
@@ -1,5 +1,23 @@
 2017-04-16  Joseph Pecoraro  <pecoraro@apple.com>
 
+        test262: test262/test/built-ins/isNaN/toprimitive-not-callable-throws.js
+        https://bugs.webkit.org/show_bug.cgi?id=170888
+
+        Reviewed by Saam Barati.
+
+        * stress/computed-accessor.js:
+        * stress/eval-in-arrow-function.js:
+        * stress/rest-elements.js:
+        * stress/string-object-define-own-property.js:
+        Remove unused shouldThrow.
+
+        * stress/symbol-toprimitive-errors.js: Added.
+        Check for ToPrimitive TypeErrors.
+
+        * test262.yaml:
+
+2017-04-16  Joseph Pecoraro  <pecoraro@apple.com>
+
         test262: test262/test/language/expressions/tagged-template/template-object.js
         https://bugs.webkit.org/show_bug.cgi?id=170878
 
index 6ef923d..8f50a61 100644 (file)
@@ -3,20 +3,6 @@ function shouldBe(actual, expected) {
         throw new Error(`bad value: ${String(actual)}`);
 }
 
-function shouldThrow(func, errorMessage) {
-    var errorThrown = false;
-    var error = null;
-    try {
-        func();
-    } catch (e) {
-        errorThrown = true;
-        error = e;
-    }
-    if (!errorThrown)
-        throw new Error('not thrown');
-    shouldBe(String(error), errorMessage);
-}
-
 // Class.
 (function () {
     {
index 0959115..4047286 100644 (file)
@@ -3,21 +3,6 @@ function shouldBe(actual, expected) {
         throw new Error(`bad value: ${String(actual)}`);
 }
 
-function shouldThrow(func, errorMessage) {
-    var errorThrown = false;
-    var error = null;
-    try {
-        func();
-    } catch (e) {
-        errorThrown = true;
-        error = e;
-    }
-    if (!errorThrown)
-        throw new Error('not thrown');
-    if (String(error) !== errorMessage)
-        throw new Error(`bad error: ${String(error)}`);
-}
-
 var global = this;
 for (var i = 0; i < 100; ++i) {
     (() => {
index 637afec..d8cc18b 100644 (file)
@@ -3,21 +3,6 @@ function shouldBe(actual, expected) {
         throw new Error('bad value: ' + actual);
 }
 
-function shouldThrow(func, errorMessage) {
-    var errorThrown = false;
-    var error = null;
-    try {
-        func();
-    } catch (e) {
-        errorThrown = true;
-        error = e;
-    }
-    if (!errorThrown)
-        throw new Error('not thrown');
-    if (String(error) !== errorMessage)
-        throw new Error(`bad error: ${String(error)}`);
-}
-
 function testSyntaxError(script, message) {
     var error = null;
     try {
index 2ed7113..522522e 100644 (file)
@@ -3,19 +3,6 @@ function shouldBe(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));
-}
-
 var string = new String("Cocoa");
 shouldBe(Reflect.defineProperty(string, 0, {
 }), true);
diff --git a/JSTests/stress/symbol-toprimitive-errors.js b/JSTests/stress/symbol-toprimitive-errors.js
new file mode 100644 (file)
index 0000000..56afea2
--- /dev/null
@@ -0,0 +1,46 @@
+function shouldBe(func, expected) {
+    let result = func();
+    if (result !== expected)
+        throw new Error("bad value");
+}
+
+function shouldThrow(func, errorType, message) {
+    let errorThrown = false;
+    let error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error("not thrown");
+    if (!(error instanceof errorType))
+        throw new Error("wrong error type thrown: " + error);
+    if (error.message !== message)
+        throw new Error("wrong message thrown: " + error.message);
+}
+
+shouldBe(() => isNaN({}), true);
+shouldBe(() => isNaN({[Symbol.toPrimitive]: undefined}), true);
+shouldBe(() => isNaN({[Symbol.toPrimitive]: null}), true);
+shouldBe(() => isNaN({[Symbol.toPrimitive]() { /* empty */ } }), true);
+shouldBe(() => isNaN({[Symbol.toPrimitive]() { return NaN } }), true);
+shouldBe(() => isNaN({[Symbol.toPrimitive]() { return 1 } }), false);
+
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: 1 }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: NaN }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: true }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: "string" }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: Symbol() }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: {} }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: [] }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]: /regex/ }) }, TypeError, "Symbol.toPrimitive is not a function, undefined, or null");
+
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { return this } }) }, TypeError, "Symbol.toPrimitive returned an object");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { return {} } }) }, TypeError, "Symbol.toPrimitive returned an object");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { return [] } }) }, TypeError, "Symbol.toPrimitive returned an object");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { return /regex/ } }) }, TypeError, "Symbol.toPrimitive returned an object");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { return function(){} } }) }, TypeError, "Symbol.toPrimitive returned an object");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { return Symbol() } }) }, TypeError, "Cannot convert a symbol to a number");
+shouldThrow(() => { isNaN({[Symbol.toPrimitive]() { throw new Error("Inner Error") } }) }, Error, "Inner Error");
index f72ae5f..5658075 100644 (file)
 - path: test262/test/built-ins/isFinite/toprimitive-get-abrupt.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
 - path: test262/test/built-ins/isFinite/toprimitive-not-callable-throws.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], []
 - path: test262/test/built-ins/isFinite/toprimitive-not-callable-throws.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
 - path: test262/test/built-ins/isFinite/toprimitive-result-is-object-throws.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], []
 - path: test262/test/built-ins/isFinite/toprimitive-result-is-object-throws.js
 - path: test262/test/built-ins/isNaN/toprimitive-get-abrupt.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
 - path: test262/test/built-ins/isNaN/toprimitive-not-callable-throws.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], []
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], []
 - path: test262/test/built-ins/isNaN/toprimitive-not-callable-throws.js
-  cmd: runTest262 :fail, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
+  cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], [:strict]
 - path: test262/test/built-ins/isNaN/toprimitive-result-is-object-throws.js
   cmd: runTest262 :normal, "NoException", ["../../../harness/assert.js", "../../../harness/sta.js"], []
 - path: test262/test/built-ins/isNaN/toprimitive-result-is-object-throws.js
index 4bbad47..d5a3a42 100644 (file)
@@ -1,5 +1,25 @@
 2017-04-16  Joseph Pecoraro  <pecoraro@apple.com>
 
+        test262: test262/test/built-ins/isNaN/toprimitive-not-callable-throws.js
+        https://bugs.webkit.org/show_bug.cgi?id=170888
+
+        Reviewed by Saam Barati.
+
+        * runtime/ExceptionHelpers.h:
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::createInvalidInstanceofParameterErrorHasInstanceValueNotFunction):
+        Fix up this function name.
+
+        * runtime/JSObject.cpp:
+        (JSC::callToPrimitiveFunction):
+        When called with @@isPrimitive, bail on undefined or null and
+        throw a type error if the value is not callable.
+
+        (JSC::JSObject::toPrimitive):
+        Use throw scope to check for exception.
+
+2017-04-16  Joseph Pecoraro  <pecoraro@apple.com>
+
         test262: test262/test/language/expressions/tagged-template/template-object.js
         https://bugs.webkit.org/show_bug.cgi?id=170878
 
index f18fc5d..cdc7c08 100644 (file)
@@ -269,7 +269,7 @@ JSObject* createInvalidInstanceofParameterErrorNotFunction(ExecState* exec, JSVa
     return createError(exec, value, makeString(" is not a function"), invalidParameterInstanceofNotFunctionSourceAppender);
 }
 
-JSObject* createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(ExecState* exec, JSValue value)
+JSObject* createInvalidInstanceofParameterErrorHasInstanceValueNotFunction(ExecState* exec, JSValue value)
 {
     return createError(exec, value, makeString("[Symbol.hasInstance] is not a function, undefined, or null"), invalidParameterInstanceofhasInstanceValueNotFunctionSourceAppender);
 }
index 0cfca9c..08e9d18 100644 (file)
@@ -49,7 +49,7 @@ JSObject* createNotAnObjectError(ExecState*, JSValue);
 JSObject* createInvalidFunctionApplyParameterError(ExecState*, JSValue);
 JSObject* createInvalidInParameterError(ExecState*, JSValue);
 JSObject* createInvalidInstanceofParameterErrorNotFunction(ExecState*, JSValue);
-JSObject* createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(ExecState*, JSValue);
+JSObject* createInvalidInstanceofParameterErrorHasInstanceValueNotFunction(ExecState*, JSValue);
 JSObject* createNotAConstructorError(ExecState*, JSValue);
 JSObject* createNotAFunctionError(ExecState*, JSValue);
 JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const String&);
index 887df92..3730e2c 100644 (file)
@@ -1897,12 +1897,15 @@ static ALWAYS_INLINE JSValue callToPrimitiveFunction(ExecState* exec, const JSOb
 
     JSValue function = object->get(exec, propertyName);
     RETURN_IF_EXCEPTION(scope, scope.exception());
-    if (function.isUndefined() && mode == TypeHintMode::TakesHint)
+    if (function.isUndefinedOrNull() && mode == TypeHintMode::TakesHint)
         return JSValue();
     CallData callData;
     CallType callType = getCallData(function, callData);
-    if (callType == CallType::None)
+    if (callType == CallType::None) {
+        if (mode == TypeHintMode::TakesHint)
+            throwTypeError(exec, scope, ASCIILiteral("Symbol.toPrimitive is not a function, undefined, or null"));
         return scope.exception();
+    }
 
     MarkedArgumentBuffer callArgs;
     if (mode == TypeHintMode::TakesHint) {
@@ -1972,7 +1975,11 @@ JSValue JSObject::defaultValue(const JSObject* object, ExecState* exec, Preferre
 
 JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSValue value = callToPrimitiveFunction<TypeHintMode::TakesHint>(exec, this, exec->propertyNames().toPrimitiveSymbol, preferredType);
+    RETURN_IF_EXCEPTION(scope, { });
     if (value)
         return value;
 
@@ -2017,13 +2024,12 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue hasInstanceVa
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    
 
     if (!hasInstanceValue.isUndefinedOrNull() && hasInstanceValue != exec->lexicalGlobalObject()->functionProtoHasInstanceSymbolFunction()) {
         CallData callData;
         CallType callType = JSC::getCallData(hasInstanceValue, callData);
         if (callType == CallType::None) {
-            throwException(exec, scope, createInvalidInstanceofParameterErrorhasInstanceValueNotFunction(exec, this));
+            throwException(exec, scope, createInvalidInstanceofParameterErrorHasInstanceValueNotFunction(exec, this));
             return false;
         }