Introduce ExceptionScope::assertNoException() and releaseAssertNoException().
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 May 2017 16:56:32 +0000 (16:56 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 May 2017 16:56:32 +0000 (16:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=171776

Reviewed by Keith Miller.

Source/JavaScriptCore:

Instead of ASSERT(!scope.exception()), we can now do scope.assertNoException().
Ditto for RELEASE_ASSERT and scope.releaseAssertNoException().

The advantage of using ExceptionScope::assertNoException() and
releaseAssertNoException() is that if the assertion fails, these utility
functions will print the stack trace for where the unexpected exception is
detected as well as where the unexpected exception was thrown from.  This makes
it much easier to debug the source of unhandled exceptions.

* debugger/Debugger.cpp:
(JSC::Debugger::pauseIfNeeded):
* dfg/DFGOperations.cpp:
* interpreter/Interpreter.cpp:
(JSC::eval):
(JSC::notifyDebuggerOfUnwinding):
(JSC::Interpreter::executeProgram):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::execute):
(JSC::Interpreter::debug):
* interpreter/ShadowChicken.cpp:
(JSC::ShadowChicken::functionsOnStack):
* jsc.cpp:
(GlobalObject::moduleLoaderResolve):
(GlobalObject::moduleLoaderFetch):
(functionGenerateHeapSnapshot):
(functionSamplingProfilerStackTraces):
(box):
(runWithScripts):
* runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::finishCreation):
* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::tryInitializeSpeciesWatchpoint):
* runtime/Completion.cpp:
(JSC::rejectPromise):
* runtime/ErrorInstance.cpp:
(JSC::ErrorInstance::sanitizedToString):
* runtime/ExceptionHelpers.cpp:
(JSC::createError):
* runtime/ExceptionScope.cpp:
(JSC::ExceptionScope::unexpectedExceptionMessage):
* runtime/ExceptionScope.h:
(JSC::ExceptionScope::assertNoException):
(JSC::ExceptionScope::releaseAssertNoException):
(JSC::ExceptionScope::unexpectedExceptionMessage):
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments<Type>::defineOwnProperty):
* runtime/IntlCollator.cpp:
(JSC::IntlCollator::createCollator):
(JSC::IntlCollator::resolvedOptions):
* runtime/IntlDateTimeFormat.cpp:
(JSC::IntlDateTimeFormat::resolvedOptions):
(JSC::IntlDateTimeFormat::format):
* runtime/IntlNumberFormat.cpp:
(JSC::IntlNumberFormat::createNumberFormat):
(JSC::IntlNumberFormat::resolvedOptions):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::putToPrimitiveByIndex):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::genericTypedArrayViewProtoFuncIncludes):
(JSC::genericTypedArrayViewProtoFuncIndexOf):
(JSC::genericTypedArrayViewProtoFuncLastIndexOf):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncHostPromiseRejectionTracker):
* runtime/JSModuleEnvironment.cpp:
(JSC::JSModuleEnvironment::getOwnPropertySlot):
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::finishCreation):
* runtime/JSModuleNamespaceObject.cpp:
(JSC::JSModuleNamespaceObject::finishCreation):
* runtime/JSONObject.cpp:
(JSC::Stringifier::toJSON):
* runtime/JSObject.cpp:
(JSC::JSObject::ordinaryToPrimitive):
* runtime/JSPropertyNameEnumerator.h:
(JSC::propertyNameEnumerator):
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorGetOwnPropertyDescriptors):
(JSC::objectConstructorDefineProperty):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncHasOwnProperty):
* runtime/ProgramExecutable.cpp:
(JSC::ProgramExecutable::initializeGlobalProperties):
* runtime/ReflectObject.cpp:
(JSC::reflectObjectDefineProperty):
* runtime/SamplingProfiler.cpp:
(JSC::SamplingProfiler::StackFrame::nameFromCallee):
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncRepeatCharacter):
* runtime/TemplateRegistry.cpp:
(JSC::TemplateRegistry::getTemplateObject):
* runtime/VM.cpp:
(JSC::VM::throwException):
* runtime/VM.h:
(JSC::VM::nativeStackTraceOfLastThrow):
(JSC::VM::clearException):
* wasm/WasmB3IRGenerator.cpp:
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):

Source/WebCore:

No new tests because there's no behavior change in functionality.  We're only
refactoring the code to use the new assertion utility function.

* Modules/plugins/QuickTimePluginReplacement.mm:
(WebCore::QuickTimePluginReplacement::installReplacement):
* bindings/js/JSCryptoKeySerializationJWK.cpp:
(WebCore::getJSArrayFromJSON):
(WebCore::getStringFromJSON):
(WebCore::getBooleanFromJSON):
* bindings/js/JSCustomElementRegistryCustom.cpp:
(WebCore::JSCustomElementRegistry::whenDefined):
* bindings/js/JSDOMExceptionHandling.cpp:
(WebCore::propagateExceptionSlowPath):
(WebCore::throwNotSupportedError):
(WebCore::throwInvalidStateError):
(WebCore::throwSecurityError):
(WebCore::throwDOMSyntaxError):
(WebCore::throwDataCloneError):
(WebCore::throwIndexSizeError):
(WebCore::throwTypeMismatchError):
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::makeThisTypeErrorForBuiltins):
(WebCore::makeGetterTypeErrorForBuiltins):
* bindings/js/JSDOMGlobalObjectTask.cpp:
* bindings/js/JSDOMPromise.h:
(WebCore::callPromiseFunction):
* bindings/js/JSDOMWindowBase.cpp:
(WebCore::JSDOMWindowMicrotaskCallback::call):
* bindings/js/JSMainThreadExecState.h:
(WebCore::JSMainThreadExecState::~JSMainThreadExecState):
* bindings/js/ReadableStreamDefaultController.cpp:
(WebCore::ReadableStreamDefaultController::isControlledReadableStreamLocked):
* bindings/js/ReadableStreamDefaultController.h:
(WebCore::ReadableStreamDefaultController::enqueue):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneDeserializer::readTerminal):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateSerializerFunction):
* bindings/scripts/test/JS/JSTestNode.cpp:
(WebCore::JSTestNode::serialize):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::JSTestObj::serialize):
* bindings/scripts/test/JS/JSTestSerialization.cpp:
(WebCore::JSTestSerialization::serialize):
* bindings/scripts/test/JS/JSTestSerializationInherit.cpp:
(WebCore::JSTestSerializationInherit::serialize):
* bindings/scripts/test/JS/JSTestSerializationInheritFinal.cpp:
(WebCore::JSTestSerializationInheritFinal::serialize):
* contentextensions/ContentExtensionParser.cpp:
(WebCore::ContentExtensions::getTypeFlags):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
(WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
(WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):
* html/HTMLPlugInImageElement.cpp:
(WebCore::HTMLPlugInImageElement::didAddUserAgentShadowRoot):

Source/WTF:

1. Add an option to skip some number of top frames when capturing the StackTrace.
2. Add an option to use an indentation string when dumping the StackTrace.

* wtf/StackTrace.cpp:
(WTF::StackTrace::captureStackTrace):
(WTF::StackTrace::dump):
* wtf/StackTrace.h:

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

63 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/debugger/Debugger.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/ShadowChicken.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/ErrorInstance.cpp
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/ExceptionScope.cpp
Source/JavaScriptCore/runtime/ExceptionScope.h
Source/JavaScriptCore/runtime/GenericArgumentsInlines.h
Source/JavaScriptCore/runtime/IntlCollator.cpp
Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
Source/JavaScriptCore/runtime/IntlNumberFormat.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp
Source/JavaScriptCore/runtime/JSModuleLoader.cpp
Source/JavaScriptCore/runtime/JSModuleNamespaceObject.cpp
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/JavaScriptCore/runtime/ProgramExecutable.cpp
Source/JavaScriptCore/runtime/ReflectObject.cpp
Source/JavaScriptCore/runtime/SamplingProfiler.cpp
Source/JavaScriptCore/runtime/StringPrototype.cpp
Source/JavaScriptCore/runtime/TemplateRegistry.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/StackTrace.cpp
Source/WTF/wtf/StackTrace.h
Source/WebCore/ChangeLog
Source/WebCore/Modules/plugins/QuickTimePluginReplacement.mm
Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp
Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
Source/WebCore/bindings/js/JSDOMPromise.h
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSMainThreadExecState.h
Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp
Source/WebCore/bindings/js/ReadableStreamDefaultController.h
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestSerialization.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestSerializationInherit.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestSerializationInheritFinal.cpp
Source/WebCore/contentextensions/ContentExtensionParser.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLPlugInImageElement.cpp

index 547871a..b884b06 100644 (file)
@@ -1,3 +1,114 @@
+2017-05-08  Mark Lam  <mark.lam@apple.com>
+
+        Introduce ExceptionScope::assertNoException() and releaseAssertNoException().
+        https://bugs.webkit.org/show_bug.cgi?id=171776
+
+        Reviewed by Keith Miller.
+
+        Instead of ASSERT(!scope.exception()), we can now do scope.assertNoException().
+        Ditto for RELEASE_ASSERT and scope.releaseAssertNoException().  
+
+        The advantage of using ExceptionScope::assertNoException() and
+        releaseAssertNoException() is that if the assertion fails, these utility
+        functions will print the stack trace for where the unexpected exception is
+        detected as well as where the unexpected exception was thrown from.  This makes
+        it much easier to debug the source of unhandled exceptions.
+
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::pauseIfNeeded):
+        * dfg/DFGOperations.cpp:
+        * interpreter/Interpreter.cpp:
+        (JSC::eval):
+        (JSC::notifyDebuggerOfUnwinding):
+        (JSC::Interpreter::executeProgram):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::debug):
+        * interpreter/ShadowChicken.cpp:
+        (JSC::ShadowChicken::functionsOnStack):
+        * jsc.cpp:
+        (GlobalObject::moduleLoaderResolve):
+        (GlobalObject::moduleLoaderFetch):
+        (functionGenerateHeapSnapshot):
+        (functionSamplingProfilerStackTraces):
+        (box):
+        (runWithScripts):
+        * runtime/AbstractModuleRecord.cpp:
+        (JSC::AbstractModuleRecord::finishCreation):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::ArrayPrototype::tryInitializeSpeciesWatchpoint):
+        * runtime/Completion.cpp:
+        (JSC::rejectPromise):
+        * runtime/ErrorInstance.cpp:
+        (JSC::ErrorInstance::sanitizedToString):
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::createError):
+        * runtime/ExceptionScope.cpp:
+        (JSC::ExceptionScope::unexpectedExceptionMessage):
+        * runtime/ExceptionScope.h:
+        (JSC::ExceptionScope::assertNoException):
+        (JSC::ExceptionScope::releaseAssertNoException):
+        (JSC::ExceptionScope::unexpectedExceptionMessage):
+        * runtime/GenericArgumentsInlines.h:
+        (JSC::GenericArguments<Type>::defineOwnProperty):
+        * runtime/IntlCollator.cpp:
+        (JSC::IntlCollator::createCollator):
+        (JSC::IntlCollator::resolvedOptions):
+        * runtime/IntlDateTimeFormat.cpp:
+        (JSC::IntlDateTimeFormat::resolvedOptions):
+        (JSC::IntlDateTimeFormat::format):
+        * runtime/IntlNumberFormat.cpp:
+        (JSC::IntlNumberFormat::createNumberFormat):
+        (JSC::IntlNumberFormat::resolvedOptions):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::putToPrimitiveByIndex):
+        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
+        (JSC::genericTypedArrayViewProtoFuncIncludes):
+        (JSC::genericTypedArrayViewProtoFuncIndexOf):
+        (JSC::genericTypedArrayViewProtoFuncLastIndexOf):
+        (JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncHostPromiseRejectionTracker):
+        * runtime/JSModuleEnvironment.cpp:
+        (JSC::JSModuleEnvironment::getOwnPropertySlot):
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::finishCreation):
+        * runtime/JSModuleNamespaceObject.cpp:
+        (JSC::JSModuleNamespaceObject::finishCreation):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::toJSON):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::ordinaryToPrimitive):
+        * runtime/JSPropertyNameEnumerator.h:
+        (JSC::propertyNameEnumerator):
+        * runtime/ObjectConstructor.cpp:
+        (JSC::objectConstructorGetOwnPropertyDescriptors):
+        (JSC::objectConstructorDefineProperty):
+        * runtime/ObjectPrototype.cpp:
+        (JSC::objectProtoFuncHasOwnProperty):
+        * runtime/ProgramExecutable.cpp:
+        (JSC::ProgramExecutable::initializeGlobalProperties):
+        * runtime/ReflectObject.cpp:
+        (JSC::reflectObjectDefineProperty):
+        * runtime/SamplingProfiler.cpp:
+        (JSC::SamplingProfiler::StackFrame::nameFromCallee):
+        * runtime/StringPrototype.cpp:
+        (JSC::stringProtoFuncRepeatCharacter):
+        * runtime/TemplateRegistry.cpp:
+        (JSC::TemplateRegistry::getTemplateObject):
+        * runtime/VM.cpp:
+        (JSC::VM::throwException):
+        * runtime/VM.h:
+        (JSC::VM::nativeStackTraceOfLastThrow):
+        (JSC::VM::clearException):
+        * wasm/WasmB3IRGenerator.cpp:
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::create):
+
 2017-05-06  Bill Ming  <mbbill@gmail.com>
 
         Fix 32bit Windows build by giving correct parameters to MASM
index fe9e3ef..8f39901 100644 (file)
@@ -741,7 +741,7 @@ void Debugger::pauseIfNeeded(CallFrame* callFrame)
     {
         PauseReasonDeclaration reason(*this, didHitBreakpoint ? PausedForBreakpoint : m_reasonForPause);
         handlePause(vmEntryGlobalObject, m_reasonForPause);
-        RELEASE_ASSERT(!scope.exception());
+        scope.releaseAssertNoException();
     }
 
     m_pausingBreakpointID = noBreakpointID;
index 139ab1b..133696b 100644 (file)
@@ -1750,9 +1750,9 @@ JSCell* JIT_OPERATION operationStrCat2(ExecState* exec, EncodedJSValue a, Encode
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSString* str1 = JSValue::decode(a).toString(exec);
-    ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
+    scope.assertNoException(); // Impossible, since we must have been given primitives.
     JSString* str2 = JSValue::decode(b).toString(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     scope.release();
     return jsString(exec, str1, str2);
@@ -1765,11 +1765,11 @@ JSCell* JIT_OPERATION operationStrCat3(ExecState* exec, EncodedJSValue a, Encode
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSString* str1 = JSValue::decode(a).toString(exec);
-    ASSERT(!scope.exception()); // Impossible, since we must have been given primitives.
+    scope.assertNoException(); // Impossible, since we must have been given primitives.
     JSString* str2 = JSValue::decode(b).toString(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     JSString* str3 = JSValue::decode(c).toString(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     scope.release();
     return jsString(exec, str1, str2, str3);
index 8881667..fa61eb9 100644 (file)
@@ -152,7 +152,7 @@ JSValue eval(CallFrame* callFrame)
         }
         
         // If the literal parser bailed, it should not have thrown exceptions.
-        ASSERT(!scope.exception());
+        scope.assertNoException();
 
         VariableEnvironment variablesUnderTDZ;
         JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ);
@@ -593,7 +593,7 @@ ALWAYS_INLINE static void notifyDebuggerOfUnwinding(VM& vm, CallFrame* callFrame
             debugger->unwindEvent(callFrame);
         else
             debugger->didExecuteProgram(callFrame);
-        ASSERT_UNUSED(catchScope, !catchScope.exception());
+        catchScope.assertNoException();
     }
 }
 
@@ -751,7 +751,7 @@ JSValue Interpreter::executeProgram(const SourceCode& source, CallFrame* callFra
     ASSERT(throwScope.exception() || program);
     RETURN_IF_EXCEPTION(throwScope, { });
 
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
     if (vm.isCollectorBusyOnCurrentThread())
@@ -902,7 +902,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     VM& vm = callFrame->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     ASSERT(!vm.isCollectorBusyOnCurrentThread());
     if (vm.isCollectorBusyOnCurrentThread())
         return jsNull();
@@ -967,7 +967,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     VM& vm = callFrame->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     ASSERT(!vm.isCollectorBusyOnCurrentThread());
     // We throw in this case because we have to return something "valid" but we're
     // already in an invalid state.
@@ -1036,7 +1036,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
 {
     VM& vm = *scope->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
-    ASSERT_UNUSED(throwScope, !throwScope.exception());
+    throwScope.assertNoException();
     
     if (vm.isCollectorBusyOnCurrentThread())
         return CallFrameClosure();
@@ -1088,7 +1088,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(scope->vm() == &callFrame->vm());
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
     if (vm.isCollectorBusyOnCurrentThread())
@@ -1231,7 +1231,7 @@ JSValue Interpreter::execute(ModuleProgramExecutable* executable, CallFrame* cal
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ASSERT(scope->vm() == &callFrame->vm());
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     ASSERT(!vm.isCollectorBusyOnCurrentThread());
     RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
     if (vm.isCollectorBusyOnCurrentThread())
@@ -1284,7 +1284,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookType debugHo
         return;
 
     ASSERT(callFrame->codeBlock()->hasDebuggerRequests());
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
 
     switch (debugHookType) {
         case DidEnterCallFrame:
@@ -1309,7 +1309,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookType debugHo
             debugger->didReachBreakpoint(callFrame);
             break;
     }
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 }
 
 } // namespace JSC
index 197b79f..0f7e9cb 100644 (file)
@@ -457,7 +457,7 @@ JSArray* ShadowChicken::functionsOnStack(ExecState* exec)
         vm, exec,
         [&] (const Frame& frame) -> bool {
             result->push(exec, frame.callee);
-            RELEASE_ASSERT(!scope.exception()); // This function is only called from tests.
+            scope.releaseAssertNoException(); // This function is only called from tests.
             return true;
         });
     
index 52b84ff..6c52944 100644 (file)
@@ -1608,7 +1608,7 @@ JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObjec
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     const Identifier key = keyValue.toPropertyKey(exec);
     if (UNLIKELY(scope.exception())) {
         JSValue exception = scope.exception();
@@ -1645,7 +1645,7 @@ JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObjec
     if (!directoryName)
         return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
     auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     return result;
 }
 
@@ -1735,7 +1735,7 @@ JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject,
         return deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
 
     auto result = deferred->resolve(exec, JSSourceCode::create(exec->vm(), makeSource(stringFromUTF(utf8), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     return result;
 }
 
@@ -3014,7 +3014,7 @@ EncodedJSValue JSC_HOST_CALL functionGenerateHeapSnapshot(ExecState* exec)
 
     String jsonString = snapshotBuilder.json();
     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     return result;
 }
 
@@ -3053,7 +3053,7 @@ EncodedJSValue JSC_HOST_CALL functionSamplingProfilerStackTraces(ExecState* exec
 
     String jsonString = vm.samplingProfiler()->stackTracesAsJSON();
     EncodedJSValue result = JSValue::encode(JSONParse(exec, jsonString));
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     return result;
 }
 #endif // ENABLE(SAMPLING_PROFILER)
@@ -3101,9 +3101,9 @@ static JSValue box(ExecState* exec, VM& vm, JSValue wasmValue)
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     JSString* type = asString(wasmValue.get(exec, makeIdentifier(vm, "type")));
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     JSValue value = wasmValue.get(exec, makeIdentifier(vm, "value"));
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     auto unboxString = [&] (const char* hexFormat, const char* decFormat, auto& result) {
         if (!value.isString())
@@ -3489,7 +3489,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
 
             if (isModule) {
                 promise = loadAndEvaluateModule(globalObject->globalExec(), fileName);
-                RELEASE_ASSERT(!scope.exception());
+                scope.releaseAssertNoException();
             } else {
                 if (!fetchScriptFromLocalFileSystem(fileName, scriptBuffer))
                     return false; // fail early so we can catch missing files
@@ -3518,12 +3518,12 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr
             });
 
             promise->then(globalObject->globalExec(), fulfillHandler, rejectHandler);
-            RELEASE_ASSERT(!scope.exception());
+            scope.releaseAssertNoException();
             vm.drainMicrotasks();
         } else {
             NakedPtr<Exception> evaluationException;
             JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
-            ASSERT(!scope.exception());
+            scope.assertNoException();
             if (evaluationException)
                 returnValue = evaluationException->value();
             checkException(globalObject, isLastFile, evaluationException, returnValue, uncaughtExceptionName, alwaysDumpUncaughtException, dump, success);
index f8854e2..ddcc5ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -59,7 +59,7 @@ void AbstractModuleRecord::finishCreation(ExecState* exec, VM& vm)
 
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSMap* map = JSMap::create(exec, vm, globalObject()->mapStructure());
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     m_dependenciesMap.set(vm, this, map);
     putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("dependenciesMap")), m_dependenciesMap.get());
 }
index a185d97..be6a863 100644 (file)
@@ -1395,7 +1395,7 @@ void ArrayPrototype::tryInitializeSpeciesWatchpoint(ExecState* exec)
 
     PropertySlot constructorSlot(this, PropertySlot::InternalMethodType::VMInquiry);
     this->getOwnPropertySlot(this, exec, vm.propertyNames->constructor, constructorSlot);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     if (constructorSlot.slotBase() != this
         || !constructorSlot.isCacheableValue()
         || constructorSlot.getValue(exec, vm.propertyNames->constructor) != arrayConstructor) {
@@ -1409,7 +1409,7 @@ void ArrayPrototype::tryInitializeSpeciesWatchpoint(ExecState* exec)
 
     PropertySlot speciesSlot(arrayConstructor, PropertySlot::InternalMethodType::VMInquiry);
     arrayConstructor->getOwnPropertySlot(arrayConstructor, exec, vm.propertyNames->speciesSymbol, speciesSlot);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     if (speciesSlot.slotBase() != arrayConstructor
         || !speciesSlot.isCacheableGetter()
         || speciesSlot.getterSetter() != globalObject->speciesGetterSetter()) {
index 1be8cf8..bd17798 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2007, 2013, 2016 Apple Inc.
+ *  Copyright (C) 2003-2017 Apple Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -145,7 +145,7 @@ static JSInternalPromise* rejectPromise(ExecState* exec, JSGlobalObject* globalO
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_CATCH_SCOPE(vm);
-    ASSERT(scope.exception());
+    scope.assertNoException();
     JSValue exception = scope.exception()->value();
     scope.clearException();
     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
index b2eec4e..4006c59 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2003, 2008, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -189,7 +189,7 @@ String ErrorInstance::sanitizedToString(ExecState* exec)
         }
         currentObj = obj->getPrototypeDirect();
     }
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     String nameString;
     if (!nameValue)
@@ -204,7 +204,7 @@ String ErrorInstance::sanitizedToString(ExecState* exec)
     PropertySlot messageSlot(this, PropertySlot::InternalMethodType::VMInquiry);
     if (JSObject::getOwnPropertySlot(this, exec, messagePropertName, messageSlot) && messageSlot.isValue())
         messageValue = messageSlot.getValue(exec, messagePropertName);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     String messageString;
     if (!messageValue)
index ef775bf..b5539df 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -259,7 +259,7 @@ JSObject* createError(ExecState* exec, JSValue value, const String& message, Err
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     String errorMessage = makeString(errorDescriptionForValue(exec, value)->value(exec), ' ', message);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     JSObject* exception = createTypeError(exec, errorMessage, appender, runtimeTypeForValue(value));
     ASSERT(exception->isErrorInstance());
     return exception;
index 0a86a39..2e64787 100644 (file)
@@ -27,6 +27,8 @@
 #include "ExceptionScope.h"
 
 #include "Exception.h"
+#include <wtf/StackTrace.h>
+#include <wtf/StringPrintStream.h>
 
 namespace JSC {
     
@@ -47,6 +49,23 @@ ExceptionScope::~ExceptionScope()
     m_vm.m_topExceptionScope = m_previousScope;
 }
 
+CString ExceptionScope::unexpectedExceptionMessage()
+{
+    StringPrintStream out;
+
+    out.println("Unexpected exception observed at:");
+    auto currentStack = std::unique_ptr<StackTrace>(StackTrace::captureStackTrace(25, 1));
+    currentStack->dump(out, "    ");
+
+    if (!m_vm.nativeStackTraceOfLastThrow())
+        return CString();
+    
+    out.println("The exception was thrown from:");
+    m_vm.nativeStackTraceOfLastThrow()->dump(out, "    ");
+
+    return out.toCString();
+}
+
 #endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
     
 } // namespace JSC
index 583a040..7df8e02 100644 (file)
@@ -38,13 +38,18 @@ public:
     VM& vm() const { return m_vm; }
     unsigned recursionDepth() const { return m_recursionDepth; }
     Exception* exception() { return m_vm.exception(); }
-    
+
+    ALWAYS_INLINE void assertNoException() { ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
+    ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
+
 protected:
     ExceptionScope(VM&, ExceptionEventLocation);
     ExceptionScope(const ExceptionScope&) = delete;
     ExceptionScope(ExceptionScope&&) = default;
     ~ExceptionScope();
 
+    JS_EXPORT_PRIVATE CString unexpectedExceptionMessage();
+
     VM& m_vm;
     ExceptionScope* m_previousScope;
     ExceptionEventLocation m_location;
@@ -57,6 +62,10 @@ class ExceptionScope {
 public:
     ALWAYS_INLINE VM& vm() const { return m_vm; }
     ALWAYS_INLINE Exception* exception() { return m_vm.exception(); }
+    ALWAYS_INLINE CString unexpectedExceptionMessage() { return { }; }
+
+    ALWAYS_INLINE void assertNoException() { ASSERT(!exception()); }
+    ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT(!exception()); }
 
 protected:
     ALWAYS_INLINE ExceptionScope(VM& vm)
index 0c33bbb..7aa9e9e 100644 (file)
@@ -227,7 +227,7 @@ bool GenericArguments<Type>::defineOwnProperty(JSObject* object, ExecState* exec
                     JSValue value = thisObject->getIndexQuickly(index);
                     ASSERT(value);
                     object->putDirectMayBeIndex(exec, ident, value);
-                    ASSERT(!scope.exception());
+                    scope.assertNoException();
 
                     thisObject->setModifiedArgumentDescriptor(vm, index);
                 }
index 29c9b78..9b88468 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
  * Copyright (C) 2015 Sukolsak Sakshuwong (sukolsak@gmail.com)
- * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -343,7 +343,7 @@ void IntlCollator::createCollator(ExecState& state)
 
     if (!m_initializedCollator) {
         initializeCollator(state, jsUndefined(), jsUndefined());
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
     UErrorCode status = U_ZERO_ERROR;
@@ -475,7 +475,7 @@ JSObject* IntlCollator::resolvedOptions(ExecState& state)
 
     if (!m_initializedCollator) {
         initializeCollator(state, jsUndefined(), jsUndefined());
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
     JSObject* options = constructEmptyObject(&state);
index 13e36a8..e5655fc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -832,7 +832,7 @@ JSObject* IntlDateTimeFormat::resolvedOptions(ExecState& exec)
     // Note: In this version of the ECMAScript 2015 Internationalization API, the timeZone property will be the name of the default time zone if no timeZone property was provided in the options object provided to the Intl.DateTimeFormat constructor. The previous version left the timeZone property undefined in this case.
     if (!m_initializedDateTimeFormat) {
         initializeDateTimeFormat(exec, jsUndefined(), jsUndefined());
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
     JSObject* options = constructEmptyObject(&exec);
@@ -881,7 +881,7 @@ JSValue IntlDateTimeFormat::format(ExecState& exec, double value)
     // 12.3.4 FormatDateTime abstract operation (ECMA-402 2.0)
     if (!m_initializedDateTimeFormat) {
         initializeDateTimeFormat(exec, jsUndefined(), jsUndefined());
-        ASSERT(!scope.exception());
+        scope.assertNoException();
     }
 
     // 1. If x is not a finite Number, then throw a RangeError exception.
index 14e0e65..6b09e15 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
  * Copyright (C) 2016 Sukolsak Sakshuwong (sukolsak@gmail.com)
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -358,7 +358,7 @@ void IntlNumberFormat::createNumberFormat(ExecState& state)
 
     if (!m_initializedNumberFormat) {
         initializeNumberFormat(state, jsUndefined(), jsUndefined());
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
     UNumberFormatStyle style;
@@ -486,7 +486,7 @@ JSObject* IntlNumberFormat::resolvedOptions(ExecState& state)
 
     if (!m_initializedNumberFormat) {
         initializeNumberFormat(state, jsUndefined(), jsUndefined());
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
     JSObject* options = constructEmptyObject(&state);
index 59fe4e7..3663528 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003, 2007-2008, 2012, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -207,10 +207,9 @@ bool JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSVa
     }
     
     JSObject* prototype = synthesizePrototype(exec);
-    if (UNLIKELY(!prototype)) {
-        ASSERT(scope.exception());
+    ASSERT(!prototype == !!scope.exception());
+    if (UNLIKELY(!prototype))
         return false;
-    }
     bool putResult = false;
     if (prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow, putResult))
         return putResult;
index 2cbcad3..91479a4 100644 (file)
@@ -206,7 +206,7 @@ EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncIncludes(VM& vm, Exec
     if (!targetOption)
         return JSValue::encode(jsBoolean(false));
 
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     RELEASE_ASSERT(!thisObject->isNeutered());
 
     if (std::isnan(static_cast<double>(*targetOption))) {
@@ -250,7 +250,7 @@ EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncIndexOf(VM& vm, ExecS
     auto targetOption = ViewClass::toAdaptorNativeFromValueWithoutCoercion(valueToFind);
     if (!targetOption)
         return JSValue::encode(jsNumber(-1));
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     RELEASE_ASSERT(!thisObject->isNeutered());
 
     for (; index < length; ++index) {
@@ -341,7 +341,7 @@ EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncLastIndexOf(VM& vm, E
         return JSValue::encode(jsNumber(-1));
 
     typename ViewClass::ElementType* array = thisObject->typedVector();
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     RELEASE_ASSERT(!thisObject->isNeutered());
 
     for (; index >= 0; --index) {
@@ -531,9 +531,9 @@ EncodedJSValue JSC_HOST_CALL genericTypedArrayViewPrivateFuncSubarrayCreate(VM&v
     ASSERT(exec->argument(0).isNumber());
     ASSERT(exec->argument(1).isUndefined() || exec->argument(1).isNumber());
     unsigned begin = argumentClampedIndexFromStartOrEnd(exec, 0, thisLength);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     unsigned end = argumentClampedIndexFromStartOrEnd(exec, 1, thisLength, thisLength);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     RELEASE_ASSERT(!thisObject->isNeutered());
 
index a4ab87c..e3b7a8a 100644 (file)
@@ -743,20 +743,20 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
     JSFunction* privateFuncConcatSlowPath = JSFunction::createBuiltinFunction(vm, arrayPrototypeConcatSlowPathCodeGenerator(vm), this);
 
     JSObject* regExpProtoFlagsGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->flags);
-    ASSERT_UNUSED(catchScope, !catchScope.exception());
+    catchScope.assertNoException();
     JSObject* regExpProtoGlobalGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->global);
-    ASSERT(!catchScope.exception());
+    catchScope.assertNoException();
     m_regExpProtoGlobalGetter.set(vm, this, regExpProtoGlobalGetterObject);
     JSObject* regExpProtoIgnoreCaseGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->ignoreCase);
-    ASSERT(!catchScope.exception());
+    catchScope.assertNoException();
     JSObject* regExpProtoMultilineGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->multiline);
-    ASSERT(!catchScope.exception());
+    catchScope.assertNoException();
     JSObject* regExpProtoSourceGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->source);
-    ASSERT(!catchScope.exception());
+    catchScope.assertNoException();
     JSObject* regExpProtoStickyGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->sticky);
-    ASSERT(!catchScope.exception());
+    catchScope.assertNoException();
     JSObject* regExpProtoUnicodeGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->unicode);
-    ASSERT(!catchScope.exception());
+    catchScope.assertNoException();
     m_regExpProtoUnicodeGetter.set(vm, this, regExpProtoUnicodeGetterObject);
     JSObject* builtinRegExpExec = asObject(m_regExpPrototype->getDirect(vm, vm.propertyNames->exec).asCell());
     m_regExpProtoExec.set(vm, this, builtinRegExpExec);
@@ -913,10 +913,10 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct
             PropertySlot slot(base, PropertySlot::InternalMethodType::Get);
             bool result = base->getOwnPropertySlot(base, exec, ident, slot);
             ASSERT_UNUSED(result, result);
-            ASSERT(!catchScope.exception());
+            catchScope.assertNoException();
             RELEASE_ASSERT(slot.isCacheableValue());
             JSValue functionValue = slot.getValue(exec, ident);
-            ASSERT(!catchScope.exception());
+            catchScope.assertNoException();
             ASSERT(jsDynamicCast<JSFunction*>(vm, functionValue));
 
             ObjectPropertyCondition condition = generateConditionForSelfEquivalence(m_vm, nullptr, base, ident.impl());
index 6b021b4..36ee6d3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
- *  Copyright (C) 2003-2009, 2012, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
  *  Copyright (C) 2007 Maks Orlovich
  *
@@ -753,7 +753,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncHostPromiseRejectionTracker(ExecState* ex
     ASSERT(operationValue.isNumber());
     auto operation = static_cast<JSPromiseRejectionOperation>(operationValue.toUInt32(exec));
     ASSERT(operation == JSPromiseRejectionOperation::Reject || operation == JSPromiseRejectionOperation::Handle);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     globalObject->globalObjectMethodTable()->promiseRejectionTracker(globalObject, exec, promise, operation);
     RETURN_IF_EXCEPTION(scope, { });
index 80fedeb..5be8a64 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -91,7 +91,7 @@ bool JSModuleEnvironment::getOwnPropertySlot(JSObject* cell, ExecState* exec, Pr
         ASSERT_UNUSED(result, result);
         ASSERT(redirectSlot.isValue());
         JSValue value = redirectSlot.getValue(exec, resolution.localName);
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
         slot.setValue(thisObject, redirectSlot.attributes(), value);
         return true;
     }
index bbf3e42..d61a8e3 100644 (file)
@@ -63,7 +63,7 @@ void JSModuleLoader::finishCreation(ExecState* exec, VM& vm, JSGlobalObject* glo
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
     JSMap* map = JSMap::create(exec, vm, globalObject->mapStructure());
-    RELEASE_ASSERT(!scope.exception());
+    scope.releaseAssertNoException();
     putDirect(vm, Identifier::fromString(&vm, "registry"), map);
 }
 
index bfdb003..439f950 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -80,7 +80,7 @@ void JSModuleNamespaceObject::finishCreation(ExecState* exec, JSGlobalObject*, A
     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-isextensible
     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-preventextensions
     methodTable(vm)->preventExtensions(this, exec);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
 }
 
 void JSModuleNamespaceObject::destroy(JSCell* cell)
index 0dbcd8f..09e9023 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -287,7 +287,7 @@ ALWAYS_INLINE JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFu
 {
     VM& vm = m_exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     if (!value.isObject())
         return value;
     
index 961ab2b..cf14237 100644 (file)
@@ -1963,7 +1963,7 @@ JSValue JSObject::ordinaryToPrimitive(ExecState* exec, PreferredPrimitiveType hi
             return value;
     }
 
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     return throwTypeError(exec, scope, ASCIILiteral("No default value"));
 }
index 5e12359..145557a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -117,12 +117,12 @@ inline JSPropertyNameEnumerator* propertyNameEnumerator(ExecState* exec, JSObjec
 
     if (structure->canAccessPropertiesQuicklyForEnumeration() && indexedLength == base->getArrayLength()) {
         base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, EnumerationMode());
-        ASSERT(!scope.exception());
+        scope.assertNoException();
 
         numberStructureProperties = propertyNames.size();
 
         base->methodTable(vm)->getGenericPropertyNames(base, exec, propertyNames, EnumerationMode());
-        ASSERT(!scope.exception());
+        scope.assertNoException();
     } else {
         // Generic property names vector contains all indexed property names.
         // So disable indexed property enumeration phase by setting |indexedLength| to 0.
index 00884f2..c73e11a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -235,7 +235,7 @@ JSValue objectConstructorGetOwnPropertyDescriptors(ExecState* exec, JSObject* ob
 
         PutPropertySlot slot(descriptors);
         descriptors->putOwnDataPropertyMayBeIndex(exec, propertyName, fromDescriptor, slot);
-        ASSERT(!scope.exception());
+        scope.assertNoException();
     }
 
     return descriptors;
@@ -419,7 +419,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
     if (!success)
         return JSValue::encode(jsNull());
     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     obj->methodTable(vm)->defineOwnProperty(obj, exec, propertyName, descriptor, true);
     scope.release();
     return JSValue::encode(obj);
index c03dc0a..909dc45 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- *  Copyright (C) 2008, 2011, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2008-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -105,7 +105,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
     HasOwnPropertyCache* hasOwnPropertyCache = vm.ensureHasOwnPropertyCache();
     if (std::optional<bool> result = hasOwnPropertyCache->get(structure, propertyName)) {
         ASSERT(*result == thisObject->hasOwnProperty(exec, propertyName));
-        ASSERT(!scope.exception());
+        scope.assertNoException();
         return JSValue::encode(jsBoolean(*result));
     }
 
index 3408db6..17f89f5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010, 2013, 2015-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -177,7 +177,7 @@ JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callF
     for (auto& entry : variableDeclarations) {
         ASSERT(entry.value.isVar());
         globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get()));
-        ASSERT(!throwScope.exception());
+        throwScope.assertNoException();
     }
 
     {
index cd2fc3e..34b8269 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -147,7 +147,7 @@ EncodedJSValue JSC_HOST_CALL reflectObjectDefineProperty(ExecState* exec)
     if (UNLIKELY(!success))
         return encodedJSValue();
     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     // Reflect.defineProperty should not throw an error when the defineOwnProperty operation fails.
     bool shouldThrow = false;
index 90ddd22..7cd873e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -719,7 +719,7 @@ String SamplingProfiler::StackFrame::nameFromCallee(VM& vm)
         PropertySlot slot(callee, PropertySlot::InternalMethodType::VMInquiry);
         PropertyName propertyName(ident);
         bool hasProperty = callee->getPropertySlot(exec, propertyName, slot);
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
         if (hasProperty) {
             if (slot.isValue()) {
                 JSValue nameValue = slot.getValue(exec, propertyName);
index 0ff77f6..b80cfc9 100644 (file)
@@ -818,7 +818,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncRepeatCharacter(ExecState* exec)
 
     auto viewWithString = string->viewWithUnderlyingString(*exec);
     StringView view = viewWithString.view;
-    ASSERT(view.length() == 1 && !scope.exception());
+    ASSERT(view.length() == 1);
+    scope.assertNoException();
     UChar character = view[0];
     scope.release();
     if (!(character & ~0xff))
index 9b85160..9fffbf6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>.
- * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -70,7 +70,7 @@ JSArray* TemplateRegistry::getTemplateObject(ExecState* exec, JSTemplateRegistry
     }
 
     objectConstructorFreeze(exec, rawObject);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     templateObject->putDirect(vm, vm.propertyNames->raw, rawObject, ReadOnly | DontEnum | DontDelete);
 
@@ -79,7 +79,7 @@ JSArray* TemplateRegistry::getTemplateObject(ExecState* exec, JSTemplateRegistry
     templateObject->putDirect(vm, vm.propertyNames->builtinNames().templateRegistryKeyPrivateName(), templateKeyObject, ReadOnly | DontEnum | DontDelete);
 
     objectConstructorFreeze(exec, templateObject);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     m_templateMap.set(&templateKey, templateObject);
 
index 0ecc3cf..95325a4 100644 (file)
@@ -614,6 +614,10 @@ void VM::throwException(ExecState* exec, Exception* exception)
     interpreter->notifyDebuggerOfExceptionToBeThrown(*this, exec, exception);
 
     setException(exception);
+
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    m_nativeStackTraceOfLastThrow = std::unique_ptr<StackTrace>(StackTrace::captureStackTrace(25));
+#endif
 }
 
 JSValue VM::throwException(ExecState* exec, JSValue thrownValue)
index fcace65..f9840c8 100644 (file)
 #include <wtf/ListHashSet.h>
 #endif
 
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+#include <wtf/StackTrace.h>
+#endif
+
 namespace WTF {
 class SimpleStats;
 } // namespace WTF
@@ -674,6 +678,10 @@ public:
     void notifyNeedTermination() { m_traps.fireTrap(VMTraps::NeedTermination); }
     void notifyNeedWatchdogCheck() { m_traps.fireTrap(VMTraps::NeedWatchdogCheck); }
 
+#if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
+    StackTrace* nativeStackTraceOfLastThrow() const { return m_nativeStackTraceOfLastThrow.get(); }
+#endif
+
 private:
     friend class LLIntOffsetsExtractor;
 
@@ -706,6 +714,7 @@ private:
     {
 #if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
         m_needExceptionCheck = false;
+        m_nativeStackTraceOfLastThrow = nullptr;
 #endif
         m_exception = nullptr;
     }
@@ -752,6 +761,7 @@ private:
     ExceptionEventLocation m_simulatedThrowPointLocation;
     unsigned m_simulatedThrowPointRecursionDepth { 0 };
     mutable bool m_needExceptionCheck { false };
+    std::unique_ptr<StackTrace> m_nativeStackTraceOfLastThrow;
 #endif
 
     bool m_failNextNewCodeBlock { false };
index b1ab158..d894e83 100644 (file)
@@ -504,7 +504,7 @@ auto B3IRGenerator::addGrowMemory(ExpressionType delta, ExpressionType& result)
         // grow() does not require ExecState* if it doesn't throw exceptions.
         ExecState* exec = nullptr; 
         PageCount result = wasmMemory->grow(vm, exec, static_cast<uint32_t>(delta), shouldThrowExceptionsOnFailure);
-        RELEASE_ASSERT(!scope.exception());
+        scope.releaseAssertNoException();
         if (!result)
             return -1;
 
index c71ffad..3f8c3de 100644 (file)
@@ -292,7 +292,7 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JS
             default:
                 RELEASE_ASSERT_NOT_REACHED();
             }
-            ASSERT(!throwScope.exception());
+            throwScope.assertNoException();
             break;
         }
         }
@@ -330,7 +330,7 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JS
                 moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum());
             // We should always be able to allocate a JSWebAssemblyTable we've defined.
             // If it's defined to be too large, we should have thrown a validation error.
-            ASSERT(!throwScope.exception());
+            throwScope.assertNoException();
             ASSERT(table);
             instance->m_table.set(vm, instance, table);
         }
index 26e7226..129dacb 100644 (file)
@@ -1,3 +1,18 @@
+2017-05-08  Mark Lam  <mark.lam@apple.com>
+
+        Introduce ExceptionScope::assertNoException() and releaseAssertNoException().
+        https://bugs.webkit.org/show_bug.cgi?id=171776
+
+        Reviewed by Keith Miller.
+
+        1. Add an option to skip some number of top frames when capturing the StackTrace.
+        2. Add an option to use an indentation string when dumping the StackTrace.
+
+        * wtf/StackTrace.cpp:
+        (WTF::StackTrace::captureStackTrace):
+        (WTF::StackTrace::dump):
+        * wtf/StackTrace.h:
+
 2017-05-05  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [WTF] Use memoryFootprint for MemoryUsage retrieval in Linux
index 1ee7441..7310059 100644 (file)
@@ -44,17 +44,18 @@ ALWAYS_INLINE size_t StackTrace::instanceSize(int capacity)
     return sizeof(StackTrace) + (capacity - 1) * sizeof(void*);
 }
 
-StackTrace* StackTrace::captureStackTrace(int maxFrames)
+StackTrace* StackTrace::captureStackTrace(int maxFrames, int framesToSkip)
 {
     maxFrames = std::max(1, maxFrames);
     size_t sizeToAllocate = instanceSize(maxFrames);
     StackTrace* trace = new (NotNull, fastMalloc(sizeToAllocate)) StackTrace();
 
-    static const int framesToSkip = 2;
+    // Skip 2 additional frames i.e. StackTrace::captureStackTrace and WTFGetBacktrace.
+    framesToSkip += 2;
     int numberOfFrames = maxFrames + framesToSkip;
 
     WTFGetBacktrace(&trace->m_skippedFrame0, &numberOfFrames);
-    ASSERT(numberOfFrames > framesToSkip);
+    RELEASE_ASSERT(numberOfFrames >= framesToSkip);
     trace->m_size = numberOfFrames - framesToSkip;
     trace->m_capacity = maxFrames;
 
@@ -80,7 +81,7 @@ auto StackTrace::demangle(void* pc) -> std::optional<DemangleEntry>
     return std::nullopt;
 }
 
-void StackTrace::dump(PrintStream& out) const
+void StackTrace::dump(PrintStream& out, const char* indentString) const
 {
     const auto* stack = this->stack();
 #if HAVE(BACKTRACE_SYMBOLS)
@@ -89,6 +90,8 @@ void StackTrace::dump(PrintStream& out) const
         return;
 #endif
 
+    if (!indentString)
+        indentString = "";
     for (int i = 0; i < m_size; ++i) {
         const char* mangledName = nullptr;
         const char* cxaDemangled = nullptr;
@@ -103,9 +106,9 @@ void StackTrace::dump(PrintStream& out) const
 #endif
         const int frameNumber = i + 1;
         if (mangledName || cxaDemangled)
-            out.printf("%-3d %p %s\n", frameNumber, stack[i], cxaDemangled ? cxaDemangled : mangledName);
+            out.printf("%s%-3d %p %s\n", indentString, frameNumber, stack[i], cxaDemangled ? cxaDemangled : mangledName);
         else
-            out.printf("%-3d %p\n", frameNumber, stack[i]);
+            out.printf("%s%-3d %p\n", indentString, frameNumber, stack[i]);
     }
 
 #if HAVE(BACKTRACE_SYMBOLS)
index 3882596..70724d9 100644 (file)
@@ -36,7 +36,7 @@ class PrintStream;
 class StackTrace {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    static StackTrace* captureStackTrace(int maxFrames);
+    static StackTrace* captureStackTrace(int maxFrames, int framesToSkip = 0);
 
     // Borrowed stack trace.
     StackTrace(void** stack, int size)
@@ -71,7 +71,7 @@ public:
 
     WTF_EXPORT_PRIVATE static std::optional<DemangleEntry> demangle(void*);
 
-    WTF_EXPORT_PRIVATE void dump(PrintStream&) const;
+    WTF_EXPORT_PRIVATE void dump(PrintStream&, const char* indentString = nullptr) const;
 
 private:
     inline static size_t instanceSize(int capacity);
index 5ae1a34..b8457b2 100644 (file)
@@ -1,3 +1,67 @@
+2017-05-08  Mark Lam  <mark.lam@apple.com>
+
+        Introduce ExceptionScope::assertNoException() and releaseAssertNoException().
+        https://bugs.webkit.org/show_bug.cgi?id=171776
+
+        Reviewed by Keith Miller.
+
+        No new tests because there's no behavior change in functionality.  We're only
+        refactoring the code to use the new assertion utility function.
+
+        * Modules/plugins/QuickTimePluginReplacement.mm:
+        (WebCore::QuickTimePluginReplacement::installReplacement):
+        * bindings/js/JSCryptoKeySerializationJWK.cpp:
+        (WebCore::getJSArrayFromJSON):
+        (WebCore::getStringFromJSON):
+        (WebCore::getBooleanFromJSON):
+        * bindings/js/JSCustomElementRegistryCustom.cpp:
+        (WebCore::JSCustomElementRegistry::whenDefined):
+        * bindings/js/JSDOMExceptionHandling.cpp:
+        (WebCore::propagateExceptionSlowPath):
+        (WebCore::throwNotSupportedError):
+        (WebCore::throwInvalidStateError):
+        (WebCore::throwSecurityError):
+        (WebCore::throwDOMSyntaxError):
+        (WebCore::throwDataCloneError):
+        (WebCore::throwIndexSizeError):
+        (WebCore::throwTypeMismatchError):
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::makeThisTypeErrorForBuiltins):
+        (WebCore::makeGetterTypeErrorForBuiltins):
+        * bindings/js/JSDOMGlobalObjectTask.cpp:
+        * bindings/js/JSDOMPromise.h:
+        (WebCore::callPromiseFunction):
+        * bindings/js/JSDOMWindowBase.cpp:
+        (WebCore::JSDOMWindowMicrotaskCallback::call):
+        * bindings/js/JSMainThreadExecState.h:
+        (WebCore::JSMainThreadExecState::~JSMainThreadExecState):
+        * bindings/js/ReadableStreamDefaultController.cpp:
+        (WebCore::ReadableStreamDefaultController::isControlledReadableStreamLocked):
+        * bindings/js/ReadableStreamDefaultController.h:
+        (WebCore::ReadableStreamDefaultController::enqueue):
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneDeserializer::readTerminal):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateSerializerFunction):
+        * bindings/scripts/test/JS/JSTestNode.cpp:
+        (WebCore::JSTestNode::serialize):
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        (WebCore::JSTestObj::serialize):
+        * bindings/scripts/test/JS/JSTestSerialization.cpp:
+        (WebCore::JSTestSerialization::serialize):
+        * bindings/scripts/test/JS/JSTestSerializationInherit.cpp:
+        (WebCore::JSTestSerializationInherit::serialize):
+        * bindings/scripts/test/JS/JSTestSerializationInheritFinal.cpp:
+        (WebCore::JSTestSerializationInheritFinal::serialize):
+        * contentextensions/ContentExtensionParser.cpp:
+        (WebCore::ContentExtensions::getTypeFlags):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::didAddUserAgentShadowRoot):
+        (WebCore::HTMLMediaElement::updateMediaControlsAfterPresentationModeChange):
+        (WebCore::HTMLMediaElement::getCurrentMediaControlsStatus):
+        * html/HTMLPlugInImageElement.cpp:
+        (WebCore::HTMLPlugInImageElement::didAddUserAgentShadowRoot):
+
 2017-05-08  Chris Dumez  <cdumez@apple.com>
 
         Move 'style' from Element to HTMLElement / SVGElement and make it settable
index f429c2c..73dcc0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -200,7 +200,7 @@ bool QuickTimePluginReplacement::installReplacement(ShadowRoot& root)
     if (replacementFunction.isUndefinedOrNull())
         return false;
     JSC::JSObject* replacementObject = replacementFunction.toObject(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     JSC::CallData callData;
     JSC::CallType callType = replacementObject->methodTable()->getCallData(replacementObject, callData);
     if (callType == JSC::CallType::None)
@@ -233,7 +233,7 @@ bool QuickTimePluginReplacement::installReplacement(ShadowRoot& root)
     value = replacement.get(exec, JSC::Identifier::fromString(exec, "scriptObject"));
     if (!scope.exception() && !value.isUndefinedOrNull()) {
         m_scriptObject = value.toObject(exec);
-        ASSERT(!scope.exception());
+        scope.assertNoException();
     }
 
     if (!m_scriptObject) {
index 92317c2..8063cb3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -62,7 +62,7 @@ static bool getJSArrayFromJSON(ExecState* exec, JSObject* json, const char* key,
         return false;
 
     JSValue value = slot.getValue(exec, identifier);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     if (!isJSArray(value)) {
         throwTypeError(exec, scope, String::format("Expected an array for \"%s\" JSON key",  key));
         return false;
@@ -85,7 +85,7 @@ static bool getStringFromJSON(ExecState* exec, JSObject* json, const char* key,
         return false;
 
     JSValue jsValue = slot.getValue(exec, identifier);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     if (!jsValue.getString(exec, result)) {
         // Can get an out of memory exception.
         RETURN_IF_EXCEPTION(scope, false);
@@ -108,7 +108,7 @@ static bool getBooleanFromJSON(ExecState* exec, JSObject* json, const char* key,
         return false;
 
     JSValue jsValue = slot.getValue(exec, identifier);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     if (!jsValue.isBoolean()) {
         throwTypeError(exec, scope, String::format("Expected a boolean value for \"%s\" JSON key",  key));
         return false;
index cf9e96d..c661abf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -206,7 +206,7 @@ JSValue JSCustomElementRegistry::whenDefined(ExecState& state)
 
     if (UNLIKELY(scope.exception())) {
         rejectPromiseWithExceptionIfAny(state, *globalObject(), *promiseDeferred);
-        ASSERT(!scope.exception());
+        scope.assertNoException();
         return promiseDeferred->promise();
     }
 
index 585553d..daf0f01 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- *  Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  *  Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
  *  Copyright (C) 2013 Michael Pruett <michael@68k.org>
  *
@@ -205,7 +205,7 @@ JSValue createDOMException(ExecState& state, Exception&& exception)
 
 void propagateExceptionSlowPath(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception)
 {
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     throwException(&state, throwScope, createDOMException(state, WTFMove(exception)));
 }
     
@@ -248,27 +248,27 @@ void reportDeprecatedSetterError(JSC::ExecState& state, const char* interfaceNam
 
 void throwNotSupportedError(JSC::ExecState& state, JSC::ThrowScope& scope)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     throwException(&state, scope, createDOMException(&state, NOT_SUPPORTED_ERR));
 }
 
 void throwNotSupportedError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* message)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     String messageString(message);
     throwException(&state, scope, createDOMException(&state, NOT_SUPPORTED_ERR, &messageString));
 }
 
 void throwInvalidStateError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* message)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     String messageString(message);
     throwException(&state, scope, createDOMException(&state, INVALID_STATE_ERR, &messageString));
 }
 
 void throwSecurityError(JSC::ExecState& state, JSC::ThrowScope& scope, const String& message)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     throwException(&state, scope, createDOMException(&state, SECURITY_ERR, message));
 }
 
@@ -379,25 +379,25 @@ JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::ExecState& state, const
 
 void throwDOMSyntaxError(JSC::ExecState& state, JSC::ThrowScope& scope)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     throwException(&state, scope, createDOMException(&state, SYNTAX_ERR));
 }
 
 void throwDataCloneError(JSC::ExecState& state, JSC::ThrowScope& scope)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     throwException(&state, scope, createDOMException(&state, DATA_CLONE_ERR));
 }
 
 void throwIndexSizeError(JSC::ExecState& state, JSC::ThrowScope& scope)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     throwException(&state, scope, createDOMException(&state, INDEX_SIZE_ERR));
 }
 
 void throwTypeMismatchError(JSC::ExecState& state, JSC::ThrowScope& scope)
 {
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     throwException(&state, scope, createDOMException(&state, TYPE_MISMATCH_ERR));
 }
 
index 5bd06c7..a5f4ec9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -81,9 +81,9 @@ EncodedJSValue JSC_HOST_CALL makeThisTypeErrorForBuiltins(ExecState* execState)
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     auto interfaceName = execState->uncheckedArgument(0).getString(execState);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     auto functionName = execState->uncheckedArgument(1).getString(execState);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     return JSValue::encode(createTypeError(execState, makeThisTypeErrorMessage(interfaceName.utf8().data(), functionName.utf8().data())));
 }
 
@@ -95,9 +95,9 @@ EncodedJSValue JSC_HOST_CALL makeGetterTypeErrorForBuiltins(ExecState* execState
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     auto interfaceName = execState->uncheckedArgument(0).getString(execState);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     auto attributeName = execState->uncheckedArgument(1).getString(execState);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     return JSValue::encode(createTypeError(execState, makeGetterTypeErrorMessage(interfaceName.utf8().data(), attributeName.utf8().data())));
 }
 
index 0be2696..5317780 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -66,7 +66,7 @@ public:
             JSMainThreadExecState::runTask(exec, m_task);
         else
             m_task->run(exec);
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
 private:
index ef1049e..890d6e6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -235,7 +235,7 @@ inline JSC::JSValue callPromiseFunction(JSC::ExecState& state)
     promiseFunction(state, DeferredPromise::create(globalObject, *promiseDeferred));
 
     rejectPromiseWithExceptionIfAny(state, globalObject, *promiseDeferred);
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     return promiseDeferred->promise();
 }
 
index 390fcb8..9c48a8c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
  *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
- *  Copyright (C) 2003-2009, 2014, 2016 Apple Inc. All rights reseved.
+ *  Copyright (C) 2003-2017 Apple Inc. All rights reseved.
  *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
  *  Copyright (c) 2015 Canon Inc. All rights reserved.
  *
@@ -216,7 +216,7 @@ public:
 
         JSMainThreadExecState::runTask(exec, m_task);
 
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
     }
 
 private:
index 617e65a..dbc30e3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -133,7 +133,7 @@ private:
         JSC::VM& vm = s_mainThreadState->vm();
         auto scope = DECLARE_CATCH_SCOPE(vm);
         ASSERT(isMainThread());
-        ASSERT_UNUSED(scope, !scope.exception());
+        scope.assertNoException();
 
         JSC::ExecState* state = s_mainThreadState;
         bool didExitJavaScript = s_mainThreadState && !m_previousState;
index 4aa612e..0389bf7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2016 Canon Inc.
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted, provided that the following conditions
@@ -78,7 +78,7 @@ bool ReadableStreamDefaultController::isControlledReadableStreamLocked() const
 
     auto& clientData = *static_cast<JSVMClientData*>(vm.clientData);
     auto readableStream = m_jsController->get(&state, clientData.builtinNames().controlledReadableStreamPrivateName());
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
 
     auto* isLocked = globalObject.builtinInternalFunctions().readableStreamInternals().m_isReadableStreamLockedFunction.get();
     ASSERT(isLocked);
@@ -86,7 +86,7 @@ bool ReadableStreamDefaultController::isControlledReadableStreamLocked() const
     JSC::MarkedArgumentBuffer arguments;
     arguments.append(readableStream);
     auto result = callFunction(state, isLocked, JSC::jsUndefined(), arguments);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
 
     return result.isTrue();
 }
index 6087266..3634c4b 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2016 Canon Inc.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted, provided that the following conditions
@@ -102,7 +103,7 @@ inline bool ReadableStreamDefaultController::enqueue(RefPtr<JSC::ArrayBuffer>&&
     auto chunk = JSC::Uint8Array::create(WTFMove(buffer), 0, length);
     ASSERT(chunk);
     enqueue(state, toJS(&state, &globalObject, chunk.get()));
-    ASSERT_UNUSED(scope, !scope.exception());
+    scope.assertNoException();
     return true;
 }
 
index 61ab8e1..8e66156 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2009-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -2542,7 +2542,7 @@ private:
             // Since we are cloning a JSWebAssemblyModule, it's impossible for that
             // module to not have been a valid module. Therefore, createStub should
             // not trow.
-            RELEASE_ASSERT(!scope.exception());
+            scope.releaseAssertNoException();
             m_gcBuffer.append(result);
             return result;
         }
index 103bef8..dc8f706 100644 (file)
@@ -4552,7 +4552,7 @@ sub GenerateSerializerFunction
         my $name = $attribute->name;
         my $getFunctionName = GetAttributeGetterName($interface, $className, $attribute);
         push(@implContent, "    auto ${name}Value = ${getFunctionName}Getter(*state, *thisObject, throwScope);\n");
-        push(@implContent, "    ASSERT(!throwScope.exception());\n");
+        push(@implContent, "    throwScope.assertNoException();\n");
         push(@implContent, "    result->putDirect(vm, Identifier::fromString(&vm, \"${name}\"), ${name}Value);\n");
         push(@implContent, "\n");
     }
index 6a7ab3a..1d5b087 100644 (file)
@@ -343,7 +343,7 @@ JSC::JSObject* JSTestNode::serialize(ExecState* state, JSTestNode* thisObject, T
     auto* result = constructEmptyObject(state);
 
     auto nameValue = jsTestNodeNameGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "name"), nameValue);
 
     return result;
index 7aa1758..01b79cd 100644 (file)
@@ -8784,19 +8784,19 @@ JSC::JSObject* JSTestObj::serialize(ExecState* state, JSTestObj* thisObject, Thr
     auto* result = constructEmptyObject(state);
 
     auto createValue = jsTestObjCreateGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "create"), createValue);
 
     auto readOnlyStringAttrValue = jsTestObjReadOnlyStringAttrGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "readOnlyStringAttr"), readOnlyStringAttrValue);
 
     auto enumAttrValue = jsTestObjEnumAttrGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "enumAttr"), enumAttrValue);
 
     auto longAttrValue = jsTestObjLongAttrGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "longAttr"), longAttrValue);
 
     return result;
index 85c488d..0b5448a 100644 (file)
@@ -406,23 +406,23 @@ JSC::JSObject* JSTestSerialization::serialize(ExecState* state, JSTestSerializat
     auto* result = constructEmptyObject(state);
 
     auto firstStringAttributeValue = jsTestSerializationFirstStringAttributeGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "firstStringAttribute"), firstStringAttributeValue);
 
     auto secondLongAttributeValue = jsTestSerializationSecondLongAttributeGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "secondLongAttribute"), secondLongAttributeValue);
 
     auto fourthUnrestrictedDoubleAttributeValue = jsTestSerializationFourthUnrestrictedDoubleAttributeGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "fourthUnrestrictedDoubleAttribute"), fourthUnrestrictedDoubleAttributeValue);
 
     auto fifthLongAttributeValue = jsTestSerializationFifthLongAttributeGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "fifthLongAttribute"), fifthLongAttributeValue);
 
     auto sixthTypedefAttributeValue = jsTestSerializationSixthTypedefAttributeGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "sixthTypedefAttribute"), sixthTypedefAttributeValue);
 
     return result;
index b4ee299..12410f5 100644 (file)
@@ -207,7 +207,7 @@ JSC::JSObject* JSTestSerializationInherit::serialize(ExecState* state, JSTestSer
     auto* result = JSTestSerialization::serialize(state, thisObject, throwScope);
 
     auto inheritLongAttributeValue = jsTestSerializationInheritInheritLongAttributeGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "inheritLongAttribute"), inheritLongAttributeValue);
 
     return result;
index d7cfd3d..e626723 100644 (file)
@@ -245,7 +245,7 @@ JSC::JSObject* JSTestSerializationInheritFinal::serialize(ExecState* state, JSTe
     auto* result = JSTestSerializationInherit::serialize(state, thisObject, throwScope);
 
     auto finalLongAttributeBarValue = jsTestSerializationInheritFinalFinalLongAttributeBarGetter(*state, *thisObject, throwScope);
-    ASSERT(!throwScope.exception());
+    throwScope.assertNoException();
     result->putDirect(vm, Identifier::fromString(&vm, "finalLongAttributeBar"), finalLongAttributeBarValue);
 
     return result;
index 1f78236..c2d2c58 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -106,7 +106,7 @@ static std::error_code getTypeFlags(ExecState& exec, const JSValue& typeValue, R
         return { };
 
     const JSObject* object = typeValue.toObject(&exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     if (!isJSArray(object))
         return ContentExtensionError::JSONInvalidTriggerFlagsArray;
 
index 89f8edb..aa2bf97 100644 (file)
@@ -6810,7 +6810,7 @@ void HTMLMediaElement::didAddUserAgentShadowRoot(ShadowRoot* root)
     argList.append(mediaControlsHostJSWrapper);
 
     JSC::JSObject* function = functionValue.toObject(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     JSC::CallData callData;
     JSC::CallType callType = function->methodTable()->getCallData(function, callData);
     if (callType == JSC::CallType::None)
@@ -6824,7 +6824,7 @@ void HTMLMediaElement::didAddUserAgentShadowRoot(ShadowRoot* root)
 
     // Connect the Media, MediaControllerHost, and Controller so the GC knows about their relationship
     JSC::JSObject* mediaJSWrapperObject = mediaJSWrapper.toObject(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     JSC::Identifier controlsHost = JSC::Identifier::fromString(&exec->vm(), "controlsHost");
     
     ASSERT(!mediaJSWrapperObject->hasProperty(exec, controlsHost));
@@ -6894,7 +6894,7 @@ void HTMLMediaElement::updateMediaControlsAfterPresentationModeChange()
         return;
 
     JSC::JSObject* function = functionValue.toObject(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     JSC::CallData callData;
     JSC::CallType callType = function->methodTable()->getCallData(function, callData);
     if (callType == JSC::CallType::None)
@@ -6936,7 +6936,7 @@ String HTMLMediaElement::getCurrentMediaControlsStatus()
         return emptyString();
 
     JSC::JSObject* function = functionValue.toObject(exec);
-    ASSERT(!scope.exception());
+    scope.assertNoException();
     JSC::CallData callData;
     JSC::CallType callType = function->methodTable()->getCallData(function, callData);
     JSC::MarkedArgumentBuffer argList;
index b30dba3..b864705 100644 (file)
@@ -366,8 +366,8 @@ void HTMLPlugInImageElement::didAddUserAgentShadowRoot(ShadowRoot* root)
 
     // It is expected the JS file provides a createOverlay(shadowRoot, title, subtitle) function.
     auto* overlay = globalObject.get(&state, JSC::Identifier::fromString(&state, "createOverlay")).toObject(&state);
+    ASSERT(!overlay == !!scope.exception());
     if (!overlay) {
-        ASSERT(scope.exception());
         scope.clearException();
         return;
     }