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
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
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 () {
{
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) {
(() => {
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 {
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);
--- /dev/null
+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");
- 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
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
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);
}
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&);
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) {
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;
{
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;
}