We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / runtime / DatePrototype.cpp
index 9936515..5ead376 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004-2008, 2016 Apple Inc. All rights reserved.
  *  Copyright (C) 2008, 2009 Torch Mobile, Inc. All rights reserved.
  *  Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
  *
@@ -42,7 +42,6 @@
 #include <time.h>
 #include <wtf/Assertions.h>
 #include <wtf/MathExtras.h>
-#include <wtf/StringExtras.h>
 
 #if HAVE(LANGINFO_H)
 #include <langinfo.h>
@@ -151,13 +150,13 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance*, double timeInMil
     bool useCustomFormat = false;
     String customFormatString;
 
-    String arg0String = exec->argument(0).toString(exec)->value(exec);
+    String arg0String = exec->argument(0).toWTFString(exec);
     if (arg0String == "custom" && !exec->argument(1).isUndefined()) {
         useCustomFormat = true;
-        customFormatString = exec->argument(1).toString(exec)->value(exec);
+        customFormatString = exec->argument(1).toWTFString(exec);
     } else if (format == LocaleDateAndTime && !exec->argument(1).isUndefined()) {
         dateStyle = styleFromArgString(arg0String, dateStyle);
-        timeStyle = styleFromArgString(exec->argument(1).toString(exec)->value(exec), timeStyle);
+        timeStyle = styleFromArgString(exec->argument(1).toWTFString(exec), timeStyle);
     } else if (format != LocaleTime && !exec->argument(0).isUndefined())
         dateStyle = styleFromArgString(arg0String, dateStyle);
     else if (format != LocaleDate && !exec->argument(0).isUndefined())
@@ -312,7 +311,7 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, doubl
 {
     const GregorianDateTime* gregorianDateTime = dateObject->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return jsNontrivialString(exec, ASCIILiteral("Invalid Date"));
+        return jsNontrivialString(exec, "Invalid Date"_s);
     return formatLocaleDate(exec, *gregorianDateTime, format);
 }
 
@@ -320,17 +319,18 @@ static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, doubl
 
 static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format, bool asUTCVariant)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = asUTCVariant
         ? thisDateObj->gregorianDateTimeUTC(exec)
         : thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
-        return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date"))));
+        return JSValue::encode(jsNontrivialString(exec, String("Invalid Date"_s)));
 
     return JSValue::encode(jsNontrivialString(exec, formatDateTime(*gregorianDateTime, format, asUTCVariant)));
 }
@@ -341,6 +341,9 @@ static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format
 // Format of member function: f([hour,] [min,] [sec,] [ms])
 static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms, GregorianDateTime* t)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     double milliseconds = 0;
     bool ok = true;
     int idx = 0;
@@ -354,6 +357,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
     if (maxArgs >= 4 && idx < numArgs) {
         t->setHour(0);
         double hours = exec->uncheckedArgument(idx++).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(hours);
         milliseconds += hours * msPerHour;
     }
@@ -362,6 +366,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
     if (maxArgs >= 3 && idx < numArgs && ok) {
         t->setMinute(0);
         double minutes = exec->uncheckedArgument(idx++).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(minutes);
         milliseconds += minutes * msPerMinute;
     }
@@ -370,6 +375,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
     if (maxArgs >= 2 && idx < numArgs && ok) {
         t->setSecond(0);
         double seconds = exec->uncheckedArgument(idx++).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(seconds);
         milliseconds += seconds * msPerSecond;
     }
@@ -380,6 +386,7 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
     // milliseconds
     if (idx < numArgs) {
         double millis = exec->uncheckedArgument(idx).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(millis);
         milliseconds += millis;
     } else
@@ -395,6 +402,9 @@ static bool fillStructuresUsingTimeArgs(ExecState* exec, int maxArgs, double* ms
 // Format of member function: f([years,] [months,] [days])
 static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms, GregorianDateTime *t)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     int idx = 0;
     bool ok = true;
     int numArgs = exec->argumentCount();
@@ -406,18 +416,21 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms
     // years
     if (maxArgs >= 3 && idx < numArgs) {
         double years = exec->uncheckedArgument(idx++).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(years);
         t->setYear(toInt32(years));
     }
     // months
     if (maxArgs >= 2 && idx < numArgs && ok) {
         double months = exec->uncheckedArgument(idx++).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(months);
         t->setMonth(toInt32(months));
     }
     // days
     if (idx < numArgs && ok) {
         double days = exec->uncheckedArgument(idx++).toIntegerPreserveNaN(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         ok = std::isfinite(days);
         t->setMonthDay(0);
         *ms += days * msPerDay;
@@ -426,7 +439,7 @@ static bool fillStructuresUsingDateArgs(ExecState *exec, int maxArgs, double *ms
     return ok;
 }
 
-const ClassInfo DatePrototype::s_info = {"Object", &JSNonFinalObject::s_info, &dateTable, CREATE_METHOD_TABLE(DatePrototype)};
+const ClassInfo DatePrototype::s_info = {"Object", &JSNonFinalObject::s_info, &dateTable, nullptr, CREATE_METHOD_TABLE(DatePrototype)};
 
 /* Source for DatePrototype.lut.h
 @begin dateTable
@@ -487,22 +500,22 @@ DatePrototype::DatePrototype(VM& vm, Structure* structure)
 void DatePrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
 {
     Base::finishCreation(vm);
-    ASSERT(inherits(info()));
+    ASSERT(inherits(vm, info()));
 
-    Identifier toUTCStringName = Identifier::fromString(&vm, ASCIILiteral("toUTCString"));
+    Identifier toUTCStringName = Identifier::fromString(&vm, "toUTCString"_s);
     JSFunction* toUTCStringFunction = JSFunction::create(vm, globalObject, 0, toUTCStringName.string(), dateProtoFuncToUTCString);
-    putDirectWithoutTransition(vm, toUTCStringName, toUTCStringFunction, DontEnum);
-    putDirectWithoutTransition(vm, Identifier::fromString(&vm, ASCIILiteral("toGMTString")), toUTCStringFunction, DontEnum);
+    putDirectWithoutTransition(vm, toUTCStringName, toUTCStringFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    putDirectWithoutTransition(vm, Identifier::fromString(&vm, "toGMTString"_s), toUTCStringFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
 #if ENABLE(INTL)
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleString", datePrototypeToLocaleStringCodeGenerator, DontEnum);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleDateString", datePrototypeToLocaleDateStringCodeGenerator, DontEnum);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleTimeString", datePrototypeToLocaleTimeStringCodeGenerator, DontEnum);
-#else
-    UNUSED_PARAM(globalObject);
-#endif // ENABLE(INTL)
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleString", datePrototypeToLocaleStringCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleDateString", datePrototypeToLocaleDateStringCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("toLocaleTimeString", datePrototypeToLocaleTimeStringCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+#endif
+
+    JSFunction* toPrimitiveFunction = JSFunction::create(vm, globalObject, 1, "[Symbol.toPrimitive]"_s, dateProtoFuncToPrimitiveSymbol, NoIntrinsic);
+    putDirectWithoutTransition(vm, vm.propertyNames->toPrimitiveSymbol, toPrimitiveFunction, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
 
-    JSC_NATIVE_FUNCTION(vm.propertyNames->toPrimitiveSymbol, dateProtoFuncToPrimitiveSymbol, DontEnum | ReadOnly, 1);
     // The constructor will be added later, after DateConstructor has been built.
 }
 
@@ -522,17 +535,19 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
     
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     if (!std::isfinite(thisDateObj->internalNumber()))
-        return throwVMError(exec, createRangeError(exec, ASCIILiteral("Invalid Date")));
+        return throwVMError(exec, scope, createRangeError(exec, "Invalid Date"_s));
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
-        return JSValue::encode(jsNontrivialString(exec, String(ASCIILiteral("Invalid Date"))));
+        return JSValue::encode(jsNontrivialString(exec, String("Invalid Date"_s)));
     // Maximum amount of space we need in buffer: 7 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds)
     // 6 for formatting and one for null termination = 28. We add one extra character to allow us to force null termination.
     char buffer[28];
@@ -568,71 +583,83 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime));
 }
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate));
 }
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime));
 }
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToPrimitiveSymbol(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
     if (!thisValue.isObject())
-        return throwVMTypeError(exec, "Date.prototype[Symbol.toPrimitive] expected |this| to be an object.");
+        return throwVMTypeError(exec, scope, "Date.prototype[Symbol.toPrimitive] expected |this| to be an object.");
     JSObject* thisObject = jsCast<JSObject*>(thisValue);
 
     if (!exec->argumentCount())
-        return throwVMTypeError(exec, "Date.prototype[Symbol.toPrimitive] expected a first argument.");
+        return throwVMTypeError(exec, scope, "Date.prototype[Symbol.toPrimitive] expected a first argument.");
 
     JSValue hintValue = exec->uncheckedArgument(0);
     PreferredPrimitiveType type = toPreferredPrimitiveType(exec, hintValue);
-    if (exec->hadException())
-        return JSValue::encode(JSValue());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     if (type == NoPreference)
         type = PreferString;
 
+    scope.release();
     return JSValue::encode(thisObject->ordinaryToPrimitive(exec, type));
 }
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    return JSValue::encode(asDateInstance(thisValue)->internalValue());
+    return JSValue::encode(thisDateObj->internalValue());
 }
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -642,11 +669,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -656,11 +684,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -670,11 +699,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -684,11 +714,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -698,11 +729,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -712,11 +744,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -726,11 +759,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -740,11 +774,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -754,11 +789,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -768,11 +804,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -782,11 +819,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -796,11 +834,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -810,11 +849,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
@@ -824,11 +864,13 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     double milli = thisDateObj->internalNumber();
     if (std::isnan(milli))
         return JSValue::encode(jsNaN());
@@ -840,11 +882,13 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     double milli = thisDateObj->internalNumber();
     if (std::isnan(milli))
         return JSValue::encode(jsNaN());
@@ -856,11 +900,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -870,28 +915,31 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     double milli = timeClip(exec->argument(0).toNumber(exec));
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSValue result = jsNumber(milli);
-    thisDateObj->setInternalValue(exec->vm(), result);
+    thisDateObj->setInternalValue(vm, result);
     return JSValue::encode(result);
 }
 
 static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse, WTF::TimeType inputTimeType)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue);
     double milli = thisDateObj->internalNumber();
-    VM& vm = exec->vm();
-    
+
     if (!exec->argumentCount() || std::isnan(milli)) {
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
@@ -909,7 +957,9 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
 
     GregorianDateTime gregorianDateTime;
     gregorianDateTime.copyFrom(*other);
-    if (!fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
+    bool success = fillStructuresUsingTimeArgs(exec, numArgsToUse, &ms, &gregorianDateTime);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    if (!success) {
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
         return JSValue::encode(result);
@@ -923,18 +973,19 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
 
 static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse, WTF::TimeType inputTimeType)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue);
     if (!exec->argumentCount()) {
         JSValue result = jsNaN();
-        thisDateObj->setInternalValue(exec->vm(), result);
+        thisDateObj->setInternalValue(vm, result);
         return JSValue::encode(result);
     }
 
-    VM& vm = exec->vm();
     double milli = thisDateObj->internalNumber();
     double ms = 0; 
 
@@ -951,7 +1002,9 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,
         gregorianDateTime.copyFrom(*other);
     }
     
-    if (!fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime)) {
+    bool success = fillStructuresUsingDateArgs(exec, numArgsToUse, &ms, &gregorianDateTime);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    if (!success) {
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
         return JSValue::encode(result);
@@ -1035,12 +1088,13 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetUTCFullYear(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
-    VM& vm = exec->vm();
-    DateInstance* thisDateObj = asDateInstance(thisValue);
     if (!exec->argumentCount()) { 
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
@@ -1063,6 +1117,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
     }
 
     double year = exec->argument(0).toIntegerPreserveNaN(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     if (!std::isfinite(year)) {
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
@@ -1078,11 +1133,12 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(DateInstance::info()))
-        return throwVMTypeError(exec);
-
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
+        return throwVMTypeError(exec, scope);
 
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
@@ -1094,31 +1150,29 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
     JSObject* object = jsCast<JSObject*>(thisValue.toThis(exec, NotStrictMode));
-    if (exec->hadException())
-        return JSValue::encode(jsNull());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     JSValue timeValue = object->toPrimitive(exec, PreferNumber);
-    if (exec->hadException())
-        return JSValue::encode(jsNull());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     if (timeValue.isNumber() && !(timeValue.isInt32() || std::isfinite(timeValue.asDouble())))
         return JSValue::encode(jsNull());
 
-    JSValue toISOValue = object->get(exec, exec->vm().propertyNames->toISOString);
-    if (exec->hadException())
-        return JSValue::encode(jsNull());
+    JSValue toISOValue = object->get(exec, vm.propertyNames->toISOString);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     CallData callData;
-    CallType callType = getCallData(toISOValue, callData);
+    CallType callType = getCallData(vm, toISOValue, callData);
     if (callType == CallType::None)
-        return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString is not a function")));
+        return throwVMTypeError(exec, scope, "toISOString is not a function"_s);
 
-    JSValue result = call(exec, asObject(toISOValue), callType, callData, object, exec->emptyList());
-    if (exec->hadException())
-        return JSValue::encode(jsNull());
+    JSValue result = call(exec, asObject(toISOValue), callType, callData, object, *vm.emptyList);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     if (result.isObject())
-        return throwVMError(exec, createTypeError(exec, ASCIILiteral("toISOString did not return a primitive value")));
+        return throwVMTypeError(exec, scope, "toISOString did not return a primitive value"_s);
     return JSValue::encode(result);
 }