Fix all ExceptionScope verification failures in JavaScriptCore.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Sep 2017 06:23:39 +0000 (06:23 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Sep 2017 06:23:39 +0000 (06:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=176662
<rdar://problem/34352085>

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

1. Introduced EXCEPTION_ASSERT macros so that we can enable exception scope
   verification for release builds too (though this requires manually setting
   ENABLE_EXCEPTION_SCOPE_VERIFICATION to 1 in Platform.h).

   This is useful because it allows us to run the tests more quickly to check
   if any regressions have occurred.  Debug builds run so much slower and not
   good for a quick turn around.  Debug builds are necessary though to get
   trace information without inlining by the C++ compiler.  This is necessary to
   diagnose where the missing exception check is.

2. Repurposed the JSC_dumpSimulatedThrows=true options to capture and dump the last
   simulated throw when an exception scope verification fails.

   Previously, this option dumps the stack trace on all simulated throws.  That
   turned out to not be very useful, and slows down the debugging process.
   Instead, the new implementation captures the stack trace and only dumps it
   if we have a verification failure.

3. Fixed missing exception checks and book-keeping needed to allow the JSC tests
   to pass with JSC_validateExceptionChecks=true.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::executeOSRExit):
* dfg/DFGOperations.cpp:
* interpreter/Interpreter.cpp:
(JSC::eval):
(JSC::loadVarargs):
(JSC::Interpreter::unwind):
(JSC::Interpreter::executeProgram):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
(JSC::Interpreter::execute):
(JSC::Interpreter::executeModuleProgram):
* jit/JITOperations.cpp:
(JSC::getByVal):
* jsc.cpp:
(WTF::CustomGetter::customGetterAcessor):
(GlobalObject::moduleLoaderImportModule):
(GlobalObject::moduleLoaderResolve):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::getByVal):
(JSC::LLInt::setUpCall):
* parser/Parser.h:
(JSC::Parser::popScopeInternal):
* runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::hostResolveImportedModule):
(JSC::AbstractModuleRecord::resolveImport):
(JSC::AbstractModuleRecord::resolveExportImpl):
(JSC::getExportedNames):
(JSC::AbstractModuleRecord::getModuleNamespace):
* runtime/ArrayPrototype.cpp:
(JSC::getProperty):
(JSC::unshift):
(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncReverse):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSlice):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
(JSC::arrayProtoFuncIndexOf):
(JSC::arrayProtoFuncLastIndexOf):
(JSC::concatAppendOne):
(JSC::arrayProtoPrivateFuncConcatMemcpy):
(JSC::arrayProtoPrivateFuncAppendMemcpy):
* runtime/CatchScope.h:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/DatePrototype.cpp:
(JSC::dateProtoFuncSetTime):
(JSC::setNewValueFromTimeArgs):
* runtime/DirectArguments.h:
(JSC::DirectArguments::length const):
* runtime/ErrorPrototype.cpp:
(JSC::errorProtoFuncToString):
* runtime/ExceptionFuzz.cpp:
(JSC::doExceptionFuzzing):
* runtime/ExceptionScope.h:
(JSC::ExceptionScope::needExceptionCheck):
(JSC::ExceptionScope::assertNoException):
* runtime/GenericArgumentsInlines.h:
(JSC::GenericArguments<Type>::defineOwnProperty):
* runtime/HashMapImpl.h:
(JSC::HashMapImpl::rehash):
* runtime/IntlDateTimeFormat.cpp:
(JSC::IntlDateTimeFormat::formatToParts):
* runtime/JSArray.cpp:
(JSC::JSArray::defineOwnProperty):
(JSC::JSArray::put):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::putToPrimitive):
(JSC::JSValue::putToPrimitiveByIndex):
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::toIndex const):
(JSC::JSValue::get const):
(JSC::JSValue::getPropertySlot const):
(JSC::JSValue::equalSlowCaseInline):
* runtime/JSGenericTypedArrayViewConstructorInlines.h:
(JSC::constructGenericTypedArrayViewFromIterator):
(JSC::constructGenericTypedArrayViewWithArguments):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::set):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::put):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::decode):
(JSC::globalFuncEval):
(JSC::globalFuncProtoGetter):
(JSC::globalFuncProtoSetter):
(JSC::globalFuncImportModule):
* runtime/JSInternalPromise.cpp:
(JSC::JSInternalPromise::then):
* runtime/JSInternalPromiseDeferred.cpp:
(JSC::JSInternalPromiseDeferred::create):
* runtime/JSJob.cpp:
(JSC::JSJobMicrotask::run):
* runtime/JSModuleEnvironment.cpp:
(JSC::JSModuleEnvironment::getOwnPropertySlot):
(JSC::JSModuleEnvironment::put):
(JSC::JSModuleEnvironment::deleteProperty):
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::provide):
(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::linkAndEvaluateModule):
(JSC::JSModuleLoader::requestImportModule):
* runtime/JSModuleRecord.cpp:
(JSC::JSModuleRecord::link):
(JSC::JSModuleRecord::instantiateDeclarations):
* runtime/JSONObject.cpp:
(JSC::Stringifier::stringify):
(JSC::Stringifier::toJSON):
(JSC::JSONProtoFuncParse):
* runtime/JSObject.cpp:
(JSC::JSObject::calculatedClassName):
(JSC::ordinarySetSlow):
(JSC::JSObject::putInlineSlow):
(JSC::JSObject::ordinaryToPrimitive const):
(JSC::JSObject::toPrimitive const):
(JSC::JSObject::hasInstance):
(JSC::JSObject::getPropertyNames):
(JSC::JSObject::toNumber const):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
(JSC::validateAndApplyPropertyDescriptor):
(JSC::JSObject::defineOwnNonIndexProperty):
(JSC::JSObject::getGenericPropertyNames):
* runtime/JSObject.h:
(JSC::JSObject::get const):
* runtime/JSObjectInlines.h:
(JSC::JSObject::getPropertySlot const):
(JSC::JSObject::getPropertySlot):
(JSC::JSObject::getNonIndexPropertySlot):
(JSC::JSObject::putInlineForJSObject):
* runtime/JSPromiseConstructor.cpp:
(JSC::constructPromise):
* runtime/JSPromiseDeferred.cpp:
(JSC::JSPromiseDeferred::create):
* runtime/JSScope.cpp:
(JSC::abstractAccess):
(JSC::JSScope::resolve):
(JSC::JSScope::resolveScopeForHoistingFuncDeclInEval):
(JSC::JSScope::abstractResolve):
* runtime/LiteralParser.cpp:
(JSC::LiteralParser<CharType>::tryJSONPParse):
(JSC::LiteralParser<CharType>::parse):
* runtime/Lookup.h:
(JSC::putEntry):
* runtime/MapConstructor.cpp:
(JSC::constructMap):
* runtime/NumberPrototype.cpp:
(JSC::numberProtoFuncToString):
* runtime/ObjectConstructor.cpp:
(JSC::objectConstructorSetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyDescriptors):
(JSC::objectConstructorAssign):
(JSC::objectConstructorValues):
(JSC::toPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
(JSC::defineProperties):
(JSC::objectConstructorDefineProperties):
(JSC::ownPropertyKeys):
* runtime/ObjectPrototype.cpp:
(JSC::objectProtoFuncHasOwnProperty):
(JSC::objectProtoFuncIsPrototypeOf):
(JSC::objectProtoFuncLookupGetter):
(JSC::objectProtoFuncLookupSetter):
(JSC::objectProtoFuncToLocaleString):
(JSC::objectProtoFuncToString):
* runtime/Options.h:
* runtime/ParseInt.h:
(JSC::toStringView):
* runtime/ProxyObject.cpp:
(JSC::performProxyGet):
(JSC::ProxyObject::performPut):
* runtime/ReflectObject.cpp:
(JSC::reflectObjectDefineProperty):
* runtime/RegExpConstructor.cpp:
(JSC::toFlags):
(JSC::regExpCreate):
(JSC::constructRegExp):
* runtime/RegExpObject.cpp:
(JSC::collectMatches):
* runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncTestFast):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncMatchFast):
(JSC::regExpProtoFuncToString):
(JSC::regExpProtoFuncSplitFast):
* runtime/ScriptExecutable.cpp:
(JSC::ScriptExecutable::newCodeBlockFor):
(JSC::ScriptExecutable::prepareForExecutionImpl):
* runtime/SetConstructor.cpp:
(JSC::constructSet):
* runtime/ThrowScope.cpp:
(JSC::ThrowScope::simulateThrow):
* runtime/VM.cpp:
(JSC::VM::verifyExceptionCheckNeedIsSatisfied):
* runtime/VM.h:
* runtime/WeakMapPrototype.cpp:
(JSC::protoFuncWeakMapSet):
* runtime/WeakSetPrototype.cpp:
(JSC::protoFuncWeakSetAdd):
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::WebAssemblyModuleConstructor::createModule):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
* wasm/js/WebAssemblyPrototype.cpp:
(JSC::reject):
(JSC::webAssemblyCompileFunc):
(JSC::resolve):
(JSC::webAssemblyInstantiateFunc):

Source/WebCore:

No new tests because this is covered by existing tests with the JSC_validateExceptionChecks=true enabled.

* bindings/js/JSCustomElementInterface.cpp:
(WebCore::JSCustomElementInterface::tryToConstructCustomElement):
* bindings/js/JSCustomElementRegistryCustom.cpp:
(WebCore::whenDefinedPromise):
* bindings/js/JSDOMConvertRecord.h:
* bindings/js/JSDOMMapLike.cpp:
(WebCore::createBackingMap):
* bindings/js/JSDOMPromiseDeferred.cpp:
(WebCore::DeferredPromise::callFunction):
(WebCore::DeferredPromise::reject):
* bindings/js/JSDOMPromiseDeferred.h:
(WebCore::callPromiseFunction):

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

72 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/dfg/DFGOSRExit.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/CatchScope.h
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/DatePrototype.cpp
Source/JavaScriptCore/runtime/DirectArguments.h
Source/JavaScriptCore/runtime/ErrorPrototype.cpp
Source/JavaScriptCore/runtime/ExceptionFuzz.cpp
Source/JavaScriptCore/runtime/ExceptionScope.h
Source/JavaScriptCore/runtime/GenericArgumentsInlines.h
Source/JavaScriptCore/runtime/HashMapImpl.h
Source/JavaScriptCore/runtime/IntlDateTimeFormat.cpp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValueInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
Source/JavaScriptCore/runtime/JSInternalPromise.cpp
Source/JavaScriptCore/runtime/JSInternalPromiseDeferred.cpp
Source/JavaScriptCore/runtime/JSJob.cpp
Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp
Source/JavaScriptCore/runtime/JSModuleLoader.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.cpp
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSObjectInlines.h
Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp
Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp
Source/JavaScriptCore/runtime/JSScope.cpp
Source/JavaScriptCore/runtime/LiteralParser.cpp
Source/JavaScriptCore/runtime/Lookup.h
Source/JavaScriptCore/runtime/MapConstructor.cpp
Source/JavaScriptCore/runtime/NumberPrototype.cpp
Source/JavaScriptCore/runtime/ObjectConstructor.cpp
Source/JavaScriptCore/runtime/ObjectPrototype.cpp
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/ParseInt.h
Source/JavaScriptCore/runtime/ProxyObject.cpp
Source/JavaScriptCore/runtime/ReflectObject.cpp
Source/JavaScriptCore/runtime/RegExpConstructor.cpp
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/RegExpObjectInlines.h
Source/JavaScriptCore/runtime/RegExpPrototype.cpp
Source/JavaScriptCore/runtime/ScriptExecutable.cpp
Source/JavaScriptCore/runtime/SetConstructor.cpp
Source/JavaScriptCore/runtime/ThrowScope.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/runtime/WeakMapPrototype.cpp
Source/JavaScriptCore/runtime/WeakSetPrototype.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSCustomElementInterface.cpp
Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
Source/WebCore/bindings/js/JSDOMConvertRecord.h
Source/WebCore/bindings/js/JSDOMMapLike.cpp
Source/WebCore/bindings/js/JSDOMPromiseDeferred.cpp
Source/WebCore/bindings/js/JSDOMPromiseDeferred.h

index c918c1c..2c28c34 100644 (file)
@@ -1,3 +1,256 @@
+2017-09-10  Mark Lam  <mark.lam@apple.com>
+
+        Fix all ExceptionScope verification failures in JavaScriptCore.
+        https://bugs.webkit.org/show_bug.cgi?id=176662
+        <rdar://problem/34352085>
+
+        Reviewed by Filip Pizlo.
+
+        1. Introduced EXCEPTION_ASSERT macros so that we can enable exception scope
+           verification for release builds too (though this requires manually setting
+           ENABLE_EXCEPTION_SCOPE_VERIFICATION to 1 in Platform.h).
+
+           This is useful because it allows us to run the tests more quickly to check
+           if any regressions have occurred.  Debug builds run so much slower and not
+           good for a quick turn around.  Debug builds are necessary though to get
+           trace information without inlining by the C++ compiler.  This is necessary to
+           diagnose where the missing exception check is.
+
+        2. Repurposed the JSC_dumpSimulatedThrows=true options to capture and dump the last
+           simulated throw when an exception scope verification fails.
+
+           Previously, this option dumps the stack trace on all simulated throws.  That
+           turned out to not be very useful, and slows down the debugging process.
+           Instead, the new implementation captures the stack trace and only dumps it
+           if we have a verification failure.
+
+        3. Fixed missing exception checks and book-keeping needed to allow the JSC tests
+           to pass with JSC_validateExceptionChecks=true.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::OSRExit::executeOSRExit):
+        * dfg/DFGOperations.cpp:
+        * interpreter/Interpreter.cpp:
+        (JSC::eval):
+        (JSC::loadVarargs):
+        (JSC::Interpreter::unwind):
+        (JSC::Interpreter::executeProgram):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeModuleProgram):
+        * jit/JITOperations.cpp:
+        (JSC::getByVal):
+        * jsc.cpp:
+        (WTF::CustomGetter::customGetterAcessor):
+        (GlobalObject::moduleLoaderImportModule):
+        (GlobalObject::moduleLoaderResolve):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::getByVal):
+        (JSC::LLInt::setUpCall):
+        * parser/Parser.h:
+        (JSC::Parser::popScopeInternal):
+        * runtime/AbstractModuleRecord.cpp:
+        (JSC::AbstractModuleRecord::hostResolveImportedModule):
+        (JSC::AbstractModuleRecord::resolveImport):
+        (JSC::AbstractModuleRecord::resolveExportImpl):
+        (JSC::getExportedNames):
+        (JSC::AbstractModuleRecord::getModuleNamespace):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::getProperty):
+        (JSC::unshift):
+        (JSC::arrayProtoFuncToString):
+        (JSC::arrayProtoFuncToLocaleString):
+        (JSC::arrayProtoFuncJoin):
+        (JSC::arrayProtoFuncPop):
+        (JSC::arrayProtoFuncPush):
+        (JSC::arrayProtoFuncReverse):
+        (JSC::arrayProtoFuncShift):
+        (JSC::arrayProtoFuncSlice):
+        (JSC::arrayProtoFuncSplice):
+        (JSC::arrayProtoFuncUnShift):
+        (JSC::arrayProtoFuncIndexOf):
+        (JSC::arrayProtoFuncLastIndexOf):
+        (JSC::concatAppendOne):
+        (JSC::arrayProtoPrivateFuncConcatMemcpy):
+        (JSC::arrayProtoPrivateFuncAppendMemcpy):
+        * runtime/CatchScope.h:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/DatePrototype.cpp:
+        (JSC::dateProtoFuncSetTime):
+        (JSC::setNewValueFromTimeArgs):
+        * runtime/DirectArguments.h:
+        (JSC::DirectArguments::length const):
+        * runtime/ErrorPrototype.cpp:
+        (JSC::errorProtoFuncToString):
+        * runtime/ExceptionFuzz.cpp:
+        (JSC::doExceptionFuzzing):
+        * runtime/ExceptionScope.h:
+        (JSC::ExceptionScope::needExceptionCheck):
+        (JSC::ExceptionScope::assertNoException):
+        * runtime/GenericArgumentsInlines.h:
+        (JSC::GenericArguments<Type>::defineOwnProperty):
+        * runtime/HashMapImpl.h:
+        (JSC::HashMapImpl::rehash):
+        * runtime/IntlDateTimeFormat.cpp:
+        (JSC::IntlDateTimeFormat::formatToParts):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::defineOwnProperty):
+        (JSC::JSArray::put):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::putToPrimitive):
+        (JSC::JSValue::putToPrimitiveByIndex):
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::toIndex const):
+        (JSC::JSValue::get const):
+        (JSC::JSValue::getPropertySlot const):
+        (JSC::JSValue::equalSlowCaseInline):
+        * runtime/JSGenericTypedArrayViewConstructorInlines.h:
+        (JSC::constructGenericTypedArrayViewFromIterator):
+        (JSC::constructGenericTypedArrayViewWithArguments):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView<Adaptor>::set):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::put):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::decode):
+        (JSC::globalFuncEval):
+        (JSC::globalFuncProtoGetter):
+        (JSC::globalFuncProtoSetter):
+        (JSC::globalFuncImportModule):
+        * runtime/JSInternalPromise.cpp:
+        (JSC::JSInternalPromise::then):
+        * runtime/JSInternalPromiseDeferred.cpp:
+        (JSC::JSInternalPromiseDeferred::create):
+        * runtime/JSJob.cpp:
+        (JSC::JSJobMicrotask::run):
+        * runtime/JSModuleEnvironment.cpp:
+        (JSC::JSModuleEnvironment::getOwnPropertySlot):
+        (JSC::JSModuleEnvironment::put):
+        (JSC::JSModuleEnvironment::deleteProperty):
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::provide):
+        (JSC::JSModuleLoader::loadAndEvaluateModule):
+        (JSC::JSModuleLoader::loadModule):
+        (JSC::JSModuleLoader::linkAndEvaluateModule):
+        (JSC::JSModuleLoader::requestImportModule):
+        * runtime/JSModuleRecord.cpp:
+        (JSC::JSModuleRecord::link):
+        (JSC::JSModuleRecord::instantiateDeclarations):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::stringify):
+        (JSC::Stringifier::toJSON):
+        (JSC::JSONProtoFuncParse):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::calculatedClassName):
+        (JSC::ordinarySetSlow):
+        (JSC::JSObject::putInlineSlow):
+        (JSC::JSObject::ordinaryToPrimitive const):
+        (JSC::JSObject::toPrimitive const):
+        (JSC::JSObject::hasInstance):
+        (JSC::JSObject::getPropertyNames):
+        (JSC::JSObject::toNumber const):
+        (JSC::JSObject::defineOwnIndexedProperty):
+        (JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
+        (JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
+        (JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
+        (JSC::validateAndApplyPropertyDescriptor):
+        (JSC::JSObject::defineOwnNonIndexProperty):
+        (JSC::JSObject::getGenericPropertyNames):
+        * runtime/JSObject.h:
+        (JSC::JSObject::get const):
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::getPropertySlot const):
+        (JSC::JSObject::getPropertySlot):
+        (JSC::JSObject::getNonIndexPropertySlot):
+        (JSC::JSObject::putInlineForJSObject):
+        * runtime/JSPromiseConstructor.cpp:
+        (JSC::constructPromise):
+        * runtime/JSPromiseDeferred.cpp:
+        (JSC::JSPromiseDeferred::create):
+        * runtime/JSScope.cpp:
+        (JSC::abstractAccess):
+        (JSC::JSScope::resolve):
+        (JSC::JSScope::resolveScopeForHoistingFuncDeclInEval):
+        (JSC::JSScope::abstractResolve):
+        * runtime/LiteralParser.cpp:
+        (JSC::LiteralParser<CharType>::tryJSONPParse):
+        (JSC::LiteralParser<CharType>::parse):
+        * runtime/Lookup.h:
+        (JSC::putEntry):
+        * runtime/MapConstructor.cpp:
+        (JSC::constructMap):
+        * runtime/NumberPrototype.cpp:
+        (JSC::numberProtoFuncToString):
+        * runtime/ObjectConstructor.cpp:
+        (JSC::objectConstructorSetPrototypeOf):
+        (JSC::objectConstructorGetOwnPropertyDescriptor):
+        (JSC::objectConstructorGetOwnPropertyDescriptors):
+        (JSC::objectConstructorAssign):
+        (JSC::objectConstructorValues):
+        (JSC::toPropertyDescriptor):
+        (JSC::objectConstructorDefineProperty):
+        (JSC::defineProperties):
+        (JSC::objectConstructorDefineProperties):
+        (JSC::ownPropertyKeys):
+        * runtime/ObjectPrototype.cpp:
+        (JSC::objectProtoFuncHasOwnProperty):
+        (JSC::objectProtoFuncIsPrototypeOf):
+        (JSC::objectProtoFuncLookupGetter):
+        (JSC::objectProtoFuncLookupSetter):
+        (JSC::objectProtoFuncToLocaleString):
+        (JSC::objectProtoFuncToString):
+        * runtime/Options.h:
+        * runtime/ParseInt.h:
+        (JSC::toStringView):
+        * runtime/ProxyObject.cpp:
+        (JSC::performProxyGet):
+        (JSC::ProxyObject::performPut):
+        * runtime/ReflectObject.cpp:
+        (JSC::reflectObjectDefineProperty):
+        * runtime/RegExpConstructor.cpp:
+        (JSC::toFlags):
+        (JSC::regExpCreate):
+        (JSC::constructRegExp):
+        * runtime/RegExpObject.cpp:
+        (JSC::collectMatches):
+        * runtime/RegExpObjectInlines.h:
+        (JSC::RegExpObject::execInline):
+        (JSC::RegExpObject::matchInline):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncTestFast):
+        (JSC::regExpProtoFuncExec):
+        (JSC::regExpProtoFuncMatchFast):
+        (JSC::regExpProtoFuncToString):
+        (JSC::regExpProtoFuncSplitFast):
+        * runtime/ScriptExecutable.cpp:
+        (JSC::ScriptExecutable::newCodeBlockFor):
+        (JSC::ScriptExecutable::prepareForExecutionImpl):
+        * runtime/SetConstructor.cpp:
+        (JSC::constructSet):
+        * runtime/ThrowScope.cpp:
+        (JSC::ThrowScope::simulateThrow):
+        * runtime/VM.cpp:
+        (JSC::VM::verifyExceptionCheckNeedIsSatisfied):
+        * runtime/VM.h:
+        * runtime/WeakMapPrototype.cpp:
+        (JSC::protoFuncWeakMapSet):
+        * runtime/WeakSetPrototype.cpp:
+        (JSC::protoFuncWeakSetAdd):
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::WebAssemblyModuleConstructor::createModule):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        * wasm/js/WebAssemblyPrototype.cpp:
+        (JSC::reject):
+        (JSC::webAssemblyCompileFunc):
+        (JSC::resolve):
+        (JSC::webAssemblyInstantiateFunc):
+
 2017-09-08  Filip Pizlo  <fpizlo@apple.com>
 
         Error should compute .stack and friends lazily
index 3702ab3..bd64bf0 100644 (file)
@@ -623,6 +623,8 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             int localScopeDepth = pc[5].u.operand;
 
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization);
+            RETURN_IF_EXCEPTION(throwScope, false);
+
             instructions[i + 4].u.operand = op.type;
             instructions[i + 5].u.operand = op.depth;
             if (op.lexicalEnvironment) {
@@ -657,6 +659,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
 
             const Identifier& ident = identifier(pc[3].u.operand);
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, getPutInfo.resolveType(), InitializationMode::NotInitialization);
+            RETURN_IF_EXCEPTION(throwScope, false);
 
             instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
             if (op.type == ModuleVar)
@@ -692,6 +695,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
             int localScopeDepth = pc[5].u.operand;
             instructions[i + 5].u.pointer = nullptr;
             ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Put, getPutInfo.resolveType(), getPutInfo.initializationMode());
+            RETURN_IF_EXCEPTION(throwScope, false);
 
             instructions[i + 4].u.operand = GetPutInfo(getPutInfo.resolveMode(), op.type, getPutInfo.initializationMode()).operand();
             if (op.type == GlobalVar || op.type == GlobalVarWithVarInjectionChecks || op.type == GlobalLexicalVar || op.type == GlobalLexicalVarWithVarInjectionChecks)
@@ -726,6 +730,7 @@ bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, Unlink
                 // Even though type profiling may be profiling either a Get or a Put, we can always claim a Get because
                 // we're abstractly "read"ing from a JSScope.
                 ResolveOp op = JSScope::abstractResolve(m_globalObject->globalExec(), localScopeDepth, scope, ident, Get, type, InitializationMode::NotInitialization);
+                RETURN_IF_EXCEPTION(throwScope, false);
 
                 if (op.type == ClosureVar || op.type == ModuleVar)
                     symbolTable = op.lexicalEnvironment->symbolTable();
index 06f8234..a5cd9a1 100644 (file)
@@ -344,7 +344,7 @@ void OSRExit::executeOSRExit(Context& context)
     OSRExit& exit = dfgJITCode->osrExit[exitIndex];
 
     ASSERT(!vm.callFrameForCatch || exit.m_kind == GenericUnwind);
-    ASSERT_UNUSED(scope, !exit.isExceptionHandler() || !!scope.exception());
+    EXCEPTION_ASSERT_UNUSED(scope, !!scope.exception() || !exit.isExceptionHandler());
 
     if (UNLIKELY(!exit.exitState)) {
         // We only need to execute this block once for each OSRExit record. The computed
index 4e6919e..03b7333 100644 (file)
@@ -915,7 +915,7 @@ EncodedJSValue JIT_OPERATION operationRegExpExec(ExecState* exec, JSGlobalObject
     JSValue argument = JSValue::decode(encodedArgument);
 
     JSString* input = argument.toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !input);
+    EXCEPTION_ASSERT(!!scope.exception() == !input);
     if (!input)
         return encodedJSValue();
     scope.release();
@@ -937,7 +937,7 @@ EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGloba
         return throwVMTypeError(exec, scope);
 
     JSString* input = argument.toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !input);
+    EXCEPTION_ASSERT(!!scope.exception() == !input);
     if (!input)
         return JSValue::encode(jsUndefined());
     scope.release();
@@ -1032,7 +1032,7 @@ size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject*
     }
 
     JSString* input = argument.toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !input);
+    EXCEPTION_ASSERT(!!scope.exception() == !input);
     if (!input)
         return false;
     scope.release();
@@ -2193,11 +2193,13 @@ JSCell* JIT_OPERATION operationNewArrayWithSpreadSlow(ExecState* exec, void* buf
             // We are spreading.
             for (unsigned i = 0; i < array->size(); i++) {
                 result->putDirectIndex(exec, index, array->get(i));
+                RETURN_IF_EXCEPTION(scope, nullptr);
                 ++index;
             }
         } else {
             // We are not spreading.
             result->putDirectIndex(exec, index, value);
+            RETURN_IF_EXCEPTION(scope, nullptr);
             ++index;
         }
     }
index 9f92db3..1353e10 100644 (file)
@@ -161,7 +161,7 @@ JSValue eval(CallFrame* callFrame)
         VariableEnvironment variablesUnderTDZ;
         JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ);
         eval = DirectEvalExecutable::create(callFrame, makeSource(programSource, callerCodeBlock->source()->sourceOrigin()), callerCodeBlock->isStrictMode(), derivedContextType, isArrowFunctionContext, evalContextType, &variablesUnderTDZ);
-        ASSERT(!!scope.exception() == !eval);
+        EXCEPTION_ASSERT(!!scope.exception() == !eval);
         if (!eval)
             return jsUndefined();
 
@@ -251,31 +251,40 @@ void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue
 {
     if (UNLIKELY(!arguments.isCell()) || !length)
         return;
-    
+
+    VM& vm = callFrame->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSCell* cell = arguments.asCell();
 
     switch (cell->type()) {
     case DirectArgumentsType:
+        scope.release();
         jsCast<DirectArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
         return;
     case ScopedArgumentsType:
+        scope.release();
         jsCast<ScopedArguments*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
         return;
     case JSFixedArrayType:
+        scope.release();
         jsCast<JSFixedArray*>(cell)->copyToArguments(callFrame, firstElementDest, offset, length);
         return;
     default: {
         ASSERT(arguments.isObject());
         JSObject* object = jsCast<JSObject*>(cell);
         if (isJSArray(object)) {
+            scope.release();
             jsCast<JSArray*>(object)->copyToArguments(callFrame, firstElementDest, offset, length);
             return;
         }
         unsigned i;
         for (i = 0; i < length && object->canGetIndexQuickly(i + offset); ++i)
             callFrame->r(firstElementDest + i) = object->getIndexQuickly(i + offset);
-        for (; i < length; ++i)
-            callFrame->r(firstElementDest + i) = object->get(callFrame, i + offset);
+        for (; i < length; ++i) {
+            JSValue value = object->get(callFrame, i + offset);
+            RETURN_IF_EXCEPTION(scope, void());
+            callFrame->r(firstElementDest + i) = value;
+        }
         return;
     } }
 }
@@ -710,7 +719,7 @@ NEVER_INLINE HandlerInfo* Interpreter::unwind(VM& vm, CallFrame*& callFrame, Exc
     if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell()))
         exceptionValue = jsNull();
 
-    ASSERT_UNUSED(scope, scope.exception() && (!Options::exceptionStackTraceLimit() || scope.exception()->stack().size()));
+    EXCEPTION_ASSERT_UNUSED(scope, scope.exception() && (!Options::exceptionStackTraceLimit() || scope.exception()->stack().size()));
 
     // Calculate an exception handler vPC, unwinding call frames as necessary.
     HandlerInfo* handler = nullptr;
@@ -767,7 +776,7 @@ JSValue Interpreter::executeProgram(const SourceCode& source, CallFrame* callFra
     auto throwScope = DECLARE_THROW_SCOPE(vm);
 
     ProgramExecutable* program = ProgramExecutable::create(callFrame, source);
-    ASSERT(throwScope.exception() || program);
+    EXCEPTION_ASSERT(throwScope.exception() || program);
     RETURN_IF_EXCEPTION(throwScope, { });
 
     throwScope.assertNoException();
@@ -882,7 +891,7 @@ failedJSONP:
 
     // Compile source to bytecode if necessary:
     JSObject* error = program->initializeGlobalProperties(vm, callFrame, scope);
-    ASSERT(!throwScope.exception() || !error);
+    EXCEPTION_ASSERT(!throwScope.exception() || !error);
     if (UNLIKELY(error))
         return checkedReturn(throwException(callFrame, throwScope, error));
 
@@ -890,7 +899,7 @@ failedJSONP:
     {
         CodeBlock* tempCodeBlock;
         JSObject* error = program->prepareForExecution<ProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
         if (UNLIKELY(error))
             return checkedReturn(error);
         codeBlock = jsCast<ProgramCodeBlock*>(tempCodeBlock);
@@ -948,7 +957,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     if (isJSCall) {
         // Compile the callee:
         JSObject* compileError = callData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(function), scope, CodeForCall, newCodeBlock);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
         if (UNLIKELY(!!compileError))
             return checkedReturn(compileError);
 
@@ -1015,7 +1024,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     if (isJSConstruct) {
         // Compile the callee:
         JSObject* compileError = constructData.js.functionExecutable->prepareForExecution<FunctionExecutable>(vm, jsCast<JSFunction*>(constructor), scope, CodeForConstruct, newCodeBlock);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
         if (UNLIKELY(!!compileError))
             return checkedReturn(compileError);
 
@@ -1063,7 +1072,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
     // Compile the callee:
     CodeBlock* newCodeBlock;
     JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, function, scope, CodeForCall, newCodeBlock);
-    ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
+    EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
     if (UNLIKELY(error))
         return CallFrameClosure();
     newCodeBlock->m_shouldAlwaysBeInlined = false;
@@ -1146,7 +1155,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
     {
         CodeBlock* tempCodeBlock;
         JSObject* compileError = eval->prepareForExecution<EvalExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
         if (UNLIKELY(!!compileError))
             return checkedReturn(compileError);
         codeBlock = jsCast<EvalCodeBlock*>(tempCodeBlock);
@@ -1199,11 +1208,13 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
                 PutPropertySlot slot(variableObject);
                 // We need create this variables because it will be used to emits code by bytecode generator
                 variableObject->methodTable(vm)->put(variableObject, callFrame, function->name(), jsUndefined(), slot);
+                RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
             }
         } else {
             for (unsigned i = 0; i < numTopLevelFunctionDecls; ++i) {
                 FunctionExecutable* function = codeBlock->functionDecl(i);
                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, function->name());
+                RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
                 if (resolvedScope.isUndefined())
                     return checkedReturn(throwSyntaxError(callFrame, throwScope, makeString("Can't create duplicate variable in eval: '", String(function->name().impl()), "'")));
                 PutPropertySlot slot(variableObject);
@@ -1215,8 +1226,11 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
             for (unsigned i = 0; i < numFunctionHoistingCandidates; ++i) {
                 const Identifier& ident = codeBlock->functionHoistingCandidate(i);
                 JSValue resolvedScope = JSScope::resolveScopeForHoistingFuncDeclInEval(callFrame, scope, ident);
+                RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
                 if (!resolvedScope.isUndefined()) {
-                    if (!variableObject->hasProperty(callFrame, ident)) {
+                    bool hasProperty = variableObject->hasProperty(callFrame, ident);
+                    RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
+                    if (!hasProperty) {
                         PutPropertySlot slot(variableObject);
                         variableObject->methodTable(vm)->put(variableObject, callFrame, ident, jsUndefined(), slot);
                         RETURN_IF_EXCEPTION(throwScope, checkedReturn(throwScope.exception()));
@@ -1264,7 +1278,7 @@ JSValue Interpreter::executeModuleProgram(ModuleProgramExecutable* executable, C
     {
         CodeBlock* tempCodeBlock;
         JSObject* compileError = executable->prepareForExecution<ModuleProgramExecutable>(vm, nullptr, scope, CodeForCall, tempCodeBlock);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(compileError));
         if (UNLIKELY(!!compileError))
             return checkedReturn(compileError);
         codeBlock = jsCast<ModuleProgramCodeBlock*>(tempCodeBlock);
index a043a5d..99841de 100644 (file)
@@ -353,6 +353,7 @@ EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stu
 
     Identifier ident = Identifier::fromUid(vm, key);
     LOG_IC((ICEvent::OperationIn, base->classInfo(*vm), ident));
+    scope.release();
     return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
 }
 
@@ -553,17 +554,22 @@ static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript,
         uint32_t i = subscript.asUInt32();
         if (baseValue.isObject()) {
             JSObject* object = asObject(baseValue);
-            if (object->canSetIndexQuickly(i))
+            if (object->canSetIndexQuickly(i)) {
                 object->setIndexQuickly(vm, i, value);
-            else {
-                // FIXME: This will make us think that in-bounds typed array accesses are actually
-                // out-of-bounds.
-                // https://bugs.webkit.org/show_bug.cgi?id=149886
-                byValInfo->arrayProfile->setOutOfBounds();
-                object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
+                return;
             }
-        } else
-            baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
+
+            // FIXME: This will make us think that in-bounds typed array accesses are actually
+            // out-of-bounds.
+            // https://bugs.webkit.org/show_bug.cgi?id=149886
+            byValInfo->arrayProfile->setOutOfBounds();
+            scope.release();
+            object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
+            return;
+        }
+
+        scope.release();
+        baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
         return;
     }
 
@@ -603,6 +609,7 @@ static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue s
             break;
         }
 
+        scope.release();
         baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
         return;
     }
@@ -612,6 +619,7 @@ static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue s
         uint32_t subscriptAsUInt32 = static_cast<uint32_t>(subscriptAsDouble);
         if (subscriptAsDouble == subscriptAsUInt32 && isIndex(subscriptAsUInt32)) {
             byValInfo->tookSlowPath = true;
+            scope.release();
             baseObject->putDirectIndex(callFrame, subscriptAsUInt32, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
             return;
         }
@@ -623,6 +631,7 @@ static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue s
 
     if (std::optional<uint32_t> index = parseIndex(property)) {
         byValInfo->tookSlowPath = true;
+        scope.release();
         baseObject->putDirectIndex(callFrame, index.value(), value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
         return;
     }
@@ -957,7 +966,7 @@ SlowPathReturnType JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLi
 
         CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, callee, scope, kind, *codeBlockSlot);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
         if (error) {
             return encodeResult(
                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
@@ -1016,7 +1025,7 @@ void JIT_OPERATION operationLinkDirectCall(ExecState* exec, CallLinkInfo* callLi
         RELEASE_ASSERT(isCall(kind) || functionExecutable->constructAbility() != ConstructAbility::CannotConstruct);
         
         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, callee, scope, kind, codeBlock);
-        ASSERT_UNUSED(throwScope, throwScope.exception() == reinterpret_cast<Exception*>(error));
+        EXCEPTION_ASSERT_UNUSED(throwScope, throwScope.exception() == reinterpret_cast<Exception*>(error));
         if (error)
             return;
         ArityCheckMode arity;
@@ -1043,8 +1052,10 @@ inline SlowPathReturnType virtualForWithFunction(
 
     JSValue calleeAsValue = execCallee->guaranteedJSValueCallee();
     calleeAsFunctionCell = getJSFunction(calleeAsValue);
-    if (UNLIKELY(!calleeAsFunctionCell))
+    if (UNLIKELY(!calleeAsFunctionCell)) {
+        throwScope.release();
         return handleHostCall(execCallee, calleeAsValue, callLinkInfo);
+    }
     
     JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
     JSScope* scope = function->scopeUnchecked();
@@ -1061,7 +1072,7 @@ inline SlowPathReturnType virtualForWithFunction(
 
         CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(*vm, function, scope, kind, *codeBlockSlot);
-        ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
+        EXCEPTION_ASSERT(throwScope.exception() == reinterpret_cast<Exception*>(error));
         if (error) {
             return encodeResult(
                 vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress(),
@@ -1593,6 +1604,7 @@ static void putAccessorByVal(ExecState* exec, JSObject* base, JSValue subscript,
     auto propertyKey = subscript.toPropertyKey(exec);
     RETURN_IF_EXCEPTION(scope, void());
 
+    scope.release();
     if (accessorType == AccessorType::Getter)
         base->putGetter(exec, propertyKey, accessor, attribute);
     else
@@ -1760,6 +1772,7 @@ static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, B
         if (isJSString(baseValue)) {
             if (asString(baseValue)->canGetIndex(i)) {
                 ctiPatchCallByReturnAddress(returnAddress, FunctionPtr(operationGetByValString));
+                scope.release();
                 return asString(baseValue)->getIndex(exec, i);
             }
             byValInfo->arrayProfile->setOutOfBounds();
@@ -1776,6 +1789,7 @@ static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, B
             }
         }
 
+        scope.release();
         return baseValue.get(exec, i);
     }
 
@@ -1788,6 +1802,7 @@ static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, B
     if (byValInfo->stubInfo && (!isStringOrSymbol(subscript) || byValInfo->cachedId != property))
         byValInfo->tookSlowPath = true;
 
+    scope.release();
     return baseValue.get(exec, property);
 }
 
@@ -1979,20 +1994,22 @@ EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSV
     JSValue result;
     if (LIKELY(subscript.isUInt32())) {
         uint32_t i = subscript.asUInt32();
-        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
-            result = asString(baseValue)->getIndex(exec, i);
-        else {
-            result = baseValue.get(exec, i);
-            if (!isJSString(baseValue)) {
-                ASSERT(exec->bytecodeOffset());
-                ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
-            }
+        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
+            scope.release();
+            return JSValue::encode(asString(baseValue)->getIndex(exec, i));
+        }
+        result = baseValue.get(exec, i);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        if (!isJSString(baseValue)) {
+            ASSERT(exec->bytecodeOffset());
+            ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
         }
     } else {
         baseValue.requireObjectCoercible(exec);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
         auto property = subscript.toPropertyKey(exec);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        scope.release();
         result = baseValue.get(exec, property);
     }
 
@@ -2011,9 +2028,11 @@ size_t JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encoded
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
+    RETURN_IF_EXCEPTION(scope, false);
     if (!baseObj)
         return false;
     bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, Identifier::fromUid(&vm, uid));
+    RETURN_IF_EXCEPTION(scope, false);
     if (!couldDelete && exec->codeBlock()->isStrictMode())
         throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     return couldDelete;
@@ -2031,6 +2050,7 @@ size_t JIT_OPERATION operationDeleteByVal(ExecState* exec, EncodedJSValue encode
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
+    RETURN_IF_EXCEPTION(scope, false);
     JSValue key = JSValue::decode(encodedKey);
     if (!baseObj)
         return false;
@@ -2040,11 +2060,11 @@ size_t JIT_OPERATION operationDeleteByVal(ExecState* exec, EncodedJSValue encode
     if (key.getUInt32(index))
         couldDelete = baseObj->methodTable(vm)->deletePropertyByIndex(baseObj, exec, index);
     else {
-        RETURN_IF_EXCEPTION(scope, false);
         Identifier property = key.toPropertyKey(exec);
         RETURN_IF_EXCEPTION(scope, false);
         couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, property);
     }
+    RETURN_IF_EXCEPTION(scope, false);
     if (!couldDelete && exec->codeBlock()->isStrictMode())
         throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     return couldDelete;
@@ -2197,6 +2217,7 @@ EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction*
     // ModuleVar is always converted to ClosureVar for get_from_scope.
     ASSERT(getPutInfo.resolveType() != ModuleVar);
 
+    throwScope.release();
     return JSValue::encode(scope->getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
         if (!found) {
             if (getPutInfo.resolveMode() == ThrowIfNotFound)
@@ -2248,6 +2269,7 @@ void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
     }
 
     bool hasProperty = scope->hasProperty(exec, ident);
+    EXCEPTION_ASSERT(!throwScope.exception() || !hasProperty);
     if (hasProperty
         && scope->isGlobalLexicalEnvironment()
         && !isInitialization(getPutInfo.initializationMode())) {
@@ -2520,6 +2542,7 @@ ALWAYS_INLINE static EncodedJSValue unprofiledMul(VM& vm, ExecState* exec, Encod
 
     double a = op1.toNumber(exec);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    scope.release();
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a * b));
 }
@@ -2621,8 +2644,7 @@ ALWAYS_INLINE static EncodedJSValue unprofiledNegate(ExecState* exec, EncodedJSV
     
     JSValue operand = JSValue::decode(encodedOperand);
     double number = operand.toNumber(exec);
-    if (UNLIKELY(scope.exception()))
-        return JSValue::encode(JSValue());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     return JSValue::encode(jsNumber(-number));
 }
 
@@ -2635,8 +2657,7 @@ ALWAYS_INLINE static EncodedJSValue profiledNegate(ExecState* exec, EncodedJSVal
     JSValue operand = JSValue::decode(encodedOperand);
     arithProfile.observeLHS(operand);
     double number = operand.toNumber(exec);
-    if (UNLIKELY(scope.exception()))
-        return JSValue::encode(JSValue());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     JSValue result = jsNumber(-number);
     arithProfile.observeResult(result);
@@ -2672,8 +2693,7 @@ EncodedJSValue JIT_OPERATION operationArithNegateProfiledOptimize(ExecState* exe
 #endif
     
     double number = operand.toNumber(exec);
-    if (UNLIKELY(scope.exception()))
-        return JSValue::encode(JSValue());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSValue result = jsNumber(-number);
     arithProfile->observeResult(result);
     return JSValue::encode(result);
@@ -2696,8 +2716,7 @@ EncodedJSValue JIT_OPERATION operationArithNegateOptimize(ExecState* exec, Encod
 #endif
 
     double number = operand.toNumber(exec);
-    if (UNLIKELY(scope.exception()))
-        return JSValue::encode(JSValue());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     return JSValue::encode(jsNumber(-number));
 }
 
@@ -2709,6 +2728,7 @@ ALWAYS_INLINE static EncodedJSValue unprofiledSub(VM& vm, ExecState* exec, Encod
 
     double a = op1.toNumber(exec);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    scope.release();
     double b = op2.toNumber(exec);
     return JSValue::encode(jsNumber(a - b));
 }
index fb76552..757f408 100644 (file)
@@ -413,6 +413,7 @@ private:
         if (!thisObject)
             return throwVMTypeError(exec, scope);
         bool shouldThrow = thisObject->get(exec, PropertyName(Identifier::fromString(exec, "shouldThrow"))).toBoolean(exec);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
         if (shouldThrow)
             return throwVMTypeError(exec, scope);
         return JSValue::encode(jsNumber(100));
@@ -1656,7 +1657,9 @@ JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* global
     if (!directoryName)
         return rejectPromise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
 
-    return JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), jsUndefined());
+    auto result = JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), jsUndefined());
+    scope.releaseAssertNoException();
+    return result;
 }
 
 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
@@ -1673,14 +1676,18 @@ JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObjec
         return deferred->reject(exec, exception);
     }
 
-    if (key.isSymbol())
-        return deferred->resolve(exec, keyValue);
-
+    if (key.isSymbol()) {
+        auto result = deferred->resolve(exec, keyValue);
+        scope.releaseAssertNoException();
+        return result;
+    }
     if (referrerValue.isUndefined()) {
         auto directoryName = currentWorkingDirectory();
         if (!directoryName)
             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
-        return deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+        auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+        scope.releaseAssertNoException();
+        return result;
     }
 
     const Identifier referrer = referrerValue.toPropertyKey(exec);
@@ -1694,7 +1701,9 @@ JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObjec
         auto directoryName = currentWorkingDirectory();
         if (!directoryName)
             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
-        return deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+        auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
+        scope.releaseAssertNoException();
+        return result;
     }
 
     // If the referrer exists, we assume that the referrer is the correct absolute path.
@@ -2712,6 +2721,7 @@ EncodedJSValue JSC_HOST_CALL functionDollarAgentReceiveBroadcast(ExecState* exec
     MarkedArgumentBuffer args;
     args.append(jsBuffer);
     args.append(jsNumber(message->index()));
+    scope.release();
     return JSValue::encode(call(exec, callback, callType, callData, jsNull(), args));
 }
 
index 225106b..735e71b 100644 (file)
@@ -819,8 +819,10 @@ static ALWAYS_INLINE JSValue getByVal(VM& vm, ExecState* exec, JSValue baseValue
     
     if (subscript.isUInt32()) {
         uint32_t i = subscript.asUInt32();
-        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
+        if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
+            scope.release();
             return asString(baseValue)->getIndex(exec, i);
+        }
         scope.release();
         return baseValue.get(exec, i);
     }
@@ -1331,7 +1333,7 @@ inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code
 
         CodeBlock** codeBlockSlot = execCallee->addressOfCodeBlock();
         JSObject* error = functionExecutable->prepareForExecution<FunctionExecutable>(vm, callee, scope, kind, *codeBlockSlot);
-        ASSERT(throwScope.exception() == error);
+        EXCEPTION_ASSERT(throwScope.exception() == error);
         if (UNLIKELY(error))
             LLINT_CALL_THROW(exec, error);
         codeBlock = *codeBlockSlot;
index b1ead71..11a697f 100644 (file)
@@ -1176,7 +1176,7 @@ private:
 
     void popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)
     {
-        ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
+        EXCEPTION_ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1);
         ASSERT(m_scopeStack.size() > 1);
         m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables);
         
index c39a167..b03ace2 100644 (file)
@@ -146,13 +146,20 @@ static JSValue identifierToJSValue(ExecState* exec, const Identifier& identifier
 
 AbstractModuleRecord* AbstractModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue moduleNameValue = identifierToJSValue(exec, moduleName);
     JSValue pair = m_dependenciesMap->JSMap::get(exec, moduleNameValue);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    scope.release();
     return jsCast<AbstractModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value")));
 }
 
 auto AbstractModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     std::optional<ImportEntry> optionalImportEntry = tryGetImportEntry(localName.impl());
     if (!optionalImportEntry)
         return Resolution::notFound();
@@ -162,6 +169,7 @@ auto AbstractModuleRecord::resolveImport(ExecState* exec, const Identifier& loca
         return Resolution::notFound();
 
     AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
+    RETURN_IF_EXCEPTION(scope, Resolution::error());
     return importedModule->resolveExport(exec, importEntry.importName);
 }
 
@@ -236,6 +244,9 @@ void AbstractModuleRecord::cacheResolution(UniquedStringImpl* exportName, const
 
 auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery& root) -> Resolution
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport
 
     // How to avoid C++ recursion in this function:
@@ -496,6 +507,7 @@ auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery
         // If the "default" name is not resolved in the current module, we need to throw an error and stop resolution immediately,
         // Rationale to this error: A default export cannot be provided by an export *.
         VM& vm = exec->vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
         if (query.exportName == vm.propertyNames->defaultKeyword.impl())
             return false;
 
@@ -514,6 +526,7 @@ auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery
         for (auto iterator = query.moduleRecord->starExportEntries().rbegin(), end = query.moduleRecord->starExportEntries().rend(); iterator != end; ++iterator) {
             const RefPtr<UniquedStringImpl>& starModuleName = *iterator;
             AbstractModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));
+            RETURN_IF_EXCEPTION(scope, false);
             pendingTasks.append(Task { ResolveQuery(importedModuleRecord, query.exportName.get()), Type::Query });
         }
         return true;
@@ -576,7 +589,9 @@ auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery
             if (!optionalExportEntry) {
                 // If there is no matched exported binding in the current module,
                 // we need to look into the stars.
-                if (!resolveNonLocal(task.query))
+                bool success = resolveNonLocal(task.query);
+                EXCEPTION_ASSERT(!scope.exception() || !success);
+                if (!success)
                     return Resolution::error();
                 continue;
             }
@@ -595,6 +610,7 @@ auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery
 
             case ExportEntry::Type::Indirect: {
                 AbstractModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName);
+                RETURN_IF_EXCEPTION(scope, Resolution::error());
 
                 // When the imported module does not produce any resolved binding, we need to look into the stars in the *current*
                 // module. To do this, we append the `IndirectFallback` task to the task queue.
@@ -614,7 +630,9 @@ auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery
             if (resolution.type == Resolution::Type::NotFound) {
                 // Indirect export entry does not produce any resolved binding.
                 // So we will investigate the stars.
-                if (!resolveNonLocal(task.query))
+                bool success = resolveNonLocal(task.query);
+                EXCEPTION_ASSERT(!scope.exception() || !success);
+                if (!success)
                     return Resolution::error();
                 continue;
             }
@@ -663,6 +681,8 @@ auto AbstractModuleRecord::resolveExport(ExecState* exec, const Identifier& expo
 static void getExportedNames(ExecState* exec, AbstractModuleRecord* root, IdentifierSet& exportedNames)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     HashSet<AbstractModuleRecord*> exportStarSet;
     Vector<AbstractModuleRecord*, 8> pendingModules;
 
@@ -682,6 +702,7 @@ static void getExportedNames(ExecState* exec, AbstractModuleRecord* root, Identi
 
         for (const auto& starModuleName : moduleRecord->starExportEntries()) {
             AbstractModuleRecord* requestedModuleRecord = moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));
+            RETURN_IF_EXCEPTION(scope, void());
             pendingModules.append(requestedModuleRecord);
         }
     }
@@ -699,11 +720,13 @@ JSModuleNamespaceObject* AbstractModuleRecord::getModuleNamespace(ExecState* exe
     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
     IdentifierSet exportedNames;
     getExportedNames(exec, this, exportedNames);
+    RETURN_IF_EXCEPTION(scope, nullptr);
 
     Vector<std::pair<Identifier, Resolution>> resolutions;
     for (auto& name : exportedNames) {
         Identifier ident = Identifier::fromUid(exec, name.get());
         const Resolution resolution = resolveExport(exec, ident);
+        RETURN_IF_EXCEPTION(scope, nullptr);
         switch (resolution.type) {
         case Resolution::Type::NotFound:
             throwSyntaxError(exec, scope, makeString("Exported binding name '", String(name.get()), "' is not found."));
@@ -722,8 +745,10 @@ JSModuleNamespaceObject* AbstractModuleRecord::getModuleNamespace(ExecState* exe
         }
     }
 
-    m_moduleNamespaceObject.set(vm, this, JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, WTFMove(resolutions)));
-    return m_moduleNamespaceObject.get();
+    auto* moduleNamespaceObject = JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, WTFMove(resolutions));
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
+    return moduleNamespaceObject;
 }
 
 static String printableName(const RefPtr<UniquedStringImpl>& uid)
index 2e2d563..8f7117b 100644 (file)
@@ -160,7 +160,7 @@ static ALWAYS_INLINE JSValue getProperty(ExecState* exec, JSObject* object, unsi
     // somewhere in the prototype chain.
     PropertySlot slot(object, PropertySlot::InternalMethodType::HasProperty);
     bool hasProperty = object->getPropertySlot(exec, index, slot);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (!hasProperty)
         return { };
     if (UNLIKELY(slot.isTaintedByOpaqueObject())) {
@@ -229,6 +229,7 @@ static ALWAYS_INLINE std::pair<SpeciesConstructResult, JSObject*> speciesConstru
         // Fast path in the normal case where the user has not set an own constructor and the Array.prototype.constructor is normal.
         // We need prototype check for subclasses of Array, which are Array objects but have a different prototype by default.
         bool isValid = speciesWatchpointIsValid(exec, thisObject);
+        scope.assertNoException();
         if (LIKELY(isValid))
             return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
 
@@ -354,7 +355,7 @@ void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned curre
         JSArray* array = asArray(thisObj);
         if (array->length() == length) {
             bool handled = array->unshiftCount<shiftCountMode>(exec, header, count);
-            ASSERT(!scope.exception() || handled);
+            EXCEPTION_ASSERT(!scope.exception() || handled);
             if (handled)
                 return;
         }
@@ -419,7 +420,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
     unsigned length = thisArray->length();
 
     StringRecursionChecker checker(exec, thisArray);
-    ASSERT(!scope.exception() || checker.earlyReturnValue());
+    EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
@@ -452,7 +453,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     StringRecursionChecker checker(exec, thisObject);
-    ASSERT(!scope.exception() || checker.earlyReturnValue());
+    EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
@@ -665,12 +666,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec)
 
     // 1. Let O be ? ToObject(this value).
     JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObject);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
     if (UNLIKELY(!thisObject))
         return encodedJSValue();
 
     StringRecursionChecker checker(exec, thisObject);
-    ASSERT(!scope.exception() || checker.earlyReturnValue());
+    EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
@@ -732,7 +733,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
     }
 
     JSObject* thisObj = thisValue.toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     unsigned length = toLength(exec, thisObj);
@@ -771,7 +772,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec)
     }
     
     JSObject* thisObj = thisValue.toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     unsigned length = toLength(exec, thisObj);
@@ -801,7 +802,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSObject* thisObject = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObject);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
     if (UNLIKELY(!thisObject))
         return encodedJSValue();
 
@@ -893,7 +894,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncShift(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     unsigned length = toLength(exec, thisObj);
@@ -920,7 +921,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return { };
     unsigned length = toLength(exec, thisObj);
@@ -935,7 +936,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSlice(ExecState* exec)
 
     std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, end - begin);
     // We can only get an exception if we call some user function.
-    ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
+    EXCEPTION_ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
     if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
         return { };
 
@@ -976,7 +977,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     unsigned length = toLength(exec, thisObj);
@@ -984,7 +985,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
 
     if (!exec->argumentCount()) {
         std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, 0);
-        ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
+        EXCEPTION_ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
         if (UNLIKELY(speciesResult.first == SpeciesConstructResult::Exception))
             return encodedJSValue();
 
@@ -1019,7 +1020,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec)
     }
 
     std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(exec, thisObj, actualDeleteCount);
-    ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
+    EXCEPTION_ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
     if (speciesResult.first == SpeciesConstructResult::Exception)
         return JSValue::encode(jsUndefined());
 
@@ -1074,7 +1075,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncUnShift(ExecState* exec)
     // 15.4.4.13
 
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     double doubleLength = toLength(exec, thisObj);
@@ -1105,13 +1106,14 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
 
     // 15.4.4.14
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     unsigned length = toLength(exec, thisObj);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSValue searchElement = exec->argument(0);
     for (; index < length; ++index) {
         JSValue e = getProperty(exec, thisObj, index);
@@ -1133,7 +1135,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec)
 
     // 15.4.4.15
     JSObject* thisObj = exec->thisValue().toThis(exec, StrictMode).toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
     unsigned length = toLength(exec, thisObj);
@@ -1223,12 +1225,12 @@ static EncodedJSValue concatAppendOne(ExecState* exec, VM& vm, JSArray* first, J
     }
 
     bool success = result->appendMemcpy(exec, vm, 0, first);
-    ASSERT(!success || !scope.exception());
+    EXCEPTION_ASSERT(!scope.exception() || !success);
     if (!success) {
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
         bool success = moveElements(exec, vm, result, 0, first, firstArraySize);
-        ASSERT(!scope.exception() == success);
+        EXCEPTION_ASSERT(!scope.exception() == success);
         if (UNLIKELY(!success))
             return encodedJSValue();
     }
@@ -1256,6 +1258,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec)
 
     // We need to check the species constructor here since checking it in the JS wrapper is too expensive for the non-optimizing tiers.
     bool isValid = speciesWatchpointIsValid(exec, firstArray);
+    scope.assertNoException();
     if (UNLIKELY(!isValid))
         return JSValue::encode(jsNull());
 
@@ -1290,11 +1293,11 @@ EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncConcatMemcpy(ExecState* exec)
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
         bool success = moveElements(exec, vm, result, 0, firstArray, firstArraySize);
-        ASSERT(!scope.exception() == success);
+        EXCEPTION_ASSERT(!scope.exception() == success);
         if (UNLIKELY(!success))
             return encodedJSValue();
         success = moveElements(exec, vm, result, firstArraySize, secondArray, secondArraySize);
-        ASSERT(!scope.exception() == success);
+        EXCEPTION_ASSERT(!scope.exception() == success);
         if (UNLIKELY(!success))
             return encodedJSValue();
 
@@ -1351,11 +1354,12 @@ EncodedJSValue JSC_HOST_CALL arrayProtoPrivateFuncAppendMemcpy(ExecState* exec)
     ASSERT(startValue.isAnyInt() && startValue.asAnyInt() >= 0 && startValue.asAnyInt() <= std::numeric_limits<unsigned>::max());
     unsigned startIndex = static_cast<unsigned>(startValue.asAnyInt());
     bool success = resultArray->appendMemcpy(exec, vm, startIndex, otherArray);
-    ASSERT(!success || !scope.exception());
-    if (!success) {
-        RETURN_IF_EXCEPTION(scope, encodedJSValue());
-        moveElements(exec, vm, resultArray, startIndex, otherArray, otherArray->length());
-    }
+    EXCEPTION_ASSERT(!scope.exception() || !success);
+    if (success)
+        return JSValue::encode(jsUndefined());
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    scope.release();
+    moveElements(exec, vm, resultArray, startIndex, otherArray, otherArray->length());
     return JSValue::encode(jsUndefined());
 }
 
index 1f2a8e7..31a7f40 100644 (file)
@@ -68,4 +68,11 @@ public:
 
 #endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
 
+#define CLEAR_AND_RETURN_IF_EXCEPTION(scope__, value__) do { \
+        if (UNLIKELY((scope__).exception())) { \
+            (scope__).clearException(); \
+            return value__; \
+        } \
+    } while (false)
+
 } // namespace JSC
index fe753ea..2289ad1 100644 (file)
@@ -1044,11 +1044,13 @@ SLOW_PATH_DECL(slow_path_new_array_with_spread)
             for (unsigned i = 0; i < array->size(); i++) {
                 RELEASE_ASSERT(array->get(i));
                 result->putDirectIndex(exec, index, array->get(i));
+                CHECK_EXCEPTION();
                 ++index;
             }
         } else {
             // We are not spreading.
             result->putDirectIndex(exec, index, value);
+            CHECK_EXCEPTION();
             ++index;
         }
     }
index 247a899..f16c59c 100644 (file)
@@ -927,6 +927,7 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
     DateInstance* thisDateObj = asDateInstance(thisValue); 
 
     double milli = timeClip(exec->argument(0).toNumber(exec));
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSValue result = jsNumber(milli);
     thisDateObj->setInternalValue(vm, result);
     return JSValue::encode(result);
@@ -960,7 +961,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);
index 81773a5..be8957e 100644 (file)
@@ -76,7 +76,11 @@ public:
     {
         if (UNLIKELY(m_mappedArguments)) {
             VM& vm = exec->vm();
-            return get(exec, vm.propertyNames->length).toUInt32(exec);
+            auto scope = DECLARE_THROW_SCOPE(vm);
+            JSValue value = get(exec, vm.propertyNames->length);
+            RETURN_IF_EXCEPTION(scope, 0);
+            scope.release();
+            return value.toUInt32(exec);
         }
         return m_length;
     }
index 38777c6..0cd7d96 100644 (file)
@@ -80,7 +80,7 @@ EncodedJSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec)
 
     // Guard against recursion!
     StringRecursionChecker checker(exec, thisObj);
-    ASSERT(!scope.exception() || checker.earlyReturnValue());
+    EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
index d688811..67c49d0 100644 (file)
@@ -56,7 +56,7 @@ void doExceptionFuzzing(ExecState* exec, ThrowScope& scope, const char* where, v
         // exception). However, ExceptionFuzz works by intentionally throwing its own exception
         // even when one may already exist. This is ok for ExceptionFuzz testing, but we need
         // to placate the exception check verifier here.
-        ASSERT(scope.exception() || !scope.exception());
+        EXCEPTION_ASSERT(scope.exception() || !scope.exception());
 
         throwException(exec, scope, createError(exec, ASCIILiteral("Exception Fuzz")));
     }
index 31553c8..080ea59 100644 (file)
@@ -32,14 +32,18 @@ namespace JSC {
 class Exception;
     
 #if ENABLE(EXCEPTION_SCOPE_VERIFICATION)
-    
+
+#define EXCEPTION_ASSERT(assertion) RELEASE_ASSERT(assertion)
+#define EXCEPTION_ASSERT_UNUSED(variable, assertion) RELEASE_ASSERT(assertion)
+#define EXCEPTION_ASSERT_WITH_MESSAGE(assertion, message) RELEASE_ASSERT_WITH_MESSAGE(assertion, message)
+
 class ExceptionScope {
 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 assertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
     ALWAYS_INLINE void releaseAssertNoException() { RELEASE_ASSERT_WITH_MESSAGE(!exception(), "%s", unexpectedExceptionMessage().data()); }
 
 protected:
@@ -55,9 +59,13 @@ protected:
     ExceptionEventLocation m_location;
     unsigned m_recursionDepth;
 };
-    
+
 #else // not ENABLE(EXCEPTION_SCOPE_VERIFICATION)
     
+#define EXCEPTION_ASSERT(x) ASSERT(x)
+#define EXCEPTION_ASSERT_UNUSED(variable, assertion) ASSERT_UNUSED(variable, assertion)
+#define EXCEPTION_ASSERT_WITH_MESSAGE(assertion, message) ASSERT_WITH_MESSAGE(assertion, message)
+
 class ExceptionScope {
 public:
     ALWAYS_INLINE VM& vm() const { return m_vm; }
@@ -77,7 +85,7 @@ protected:
 
     VM& m_vm;
 };
-    
+
 #endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
 
 #define RETURN_IF_EXCEPTION(scope__, value__) do { \
index ed4e96c..8099a19 100644 (file)
@@ -243,6 +243,7 @@ bool GenericArguments<Type>::defineOwnProperty(JSObject* object, ExecState* exec
                         JSValue value = thisObject->getIndexQuickly(index);
                         ASSERT(value);
                         object->putDirectMayBeIndex(exec, ident, value);
+                        scope.assertNoException();
                     }
                     thisObject->unmapArgument(vm, index);
                     thisObject->setModifiedArgumentDescriptor(vm, index);
index eadc56a..cb4dcaa 100644 (file)
@@ -636,7 +636,7 @@ private:
         HashMapBucketType** buffer = this->buffer();
         while (iter != end) {
             uint32_t index = jsMapHash(exec, vm, iter->key()) & mask;
-            ASSERT_WITH_MESSAGE(!scope.exception(), "All keys should already be hashed before, so this should not throw because it won't resolve ropes.");
+            EXCEPTION_ASSERT_WITH_MESSAGE(!scope.exception(), "All keys should already be hashed before, so this should not throw because it won't resolve ropes.");
             {
                 HashMapBucketType* bucket = buffer[index];
                 while (!isEmpty(bucket)) {
index 01f240b..7ef0008 100644 (file)
@@ -1019,6 +1019,7 @@ JSValue IntlDateTimeFormat::formatToParts(ExecState& exec, double value)
             part->putDirect(vm, typePropertyName, literalString);
             part->putDirect(vm, vm.propertyNames->value, value);
             parts->push(&exec, part);
+            RETURN_IF_EXCEPTION(scope, { });
         }
         previousEndIndex = endIndex;
 
@@ -1029,6 +1030,7 @@ JSValue IntlDateTimeFormat::formatToParts(ExecState& exec, double value)
             part->putDirect(vm, typePropertyName, type);
             part->putDirect(vm, vm.propertyNames->value, value);
             parts->push(&exec, part);
+            RETURN_IF_EXCEPTION(scope, { });
         }
     }
 
index 9c16b28..f435559 100644 (file)
@@ -165,8 +165,11 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName
         // b. Let newLenDesc be a copy of Desc.
         // c. Let newLen be ToUint32(Desc.[[Value]]).
         unsigned newLen = descriptor.value().toUInt32(exec);
+        RETURN_IF_EXCEPTION(scope, false);
         // d. If newLen is not equal to ToNumber( Desc.[[Value]]), throw a RangeError exception.
-        if (newLen != descriptor.value().toNumber(exec)) {
+        double valueAsNumber = descriptor.value().toNumber(exec);
+        RETURN_IF_EXCEPTION(scope, false);
+        if (newLen != valueAsNumber) {
             JSC::throwException(exec, scope, createRangeError(exec, ASCIILiteral("Invalid array length")));
             return false;
         }
@@ -198,7 +201,7 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName
         // l.ii. Let deleteSucceeded be the result of calling the [[Delete]] internal method of A passing ToString(oldLen) and false as arguments.
         // l.iii. If deleteSucceeded is false, then
         bool success = array->setLength(exec, newLen, throwException);
-        ASSERT(!scope.exception() || !success);
+        EXCEPTION_ASSERT(!scope.exception() || !success);
         if (!success) {
             // 1. Set newLenDesc.[[Value] to oldLen+1.
             // 2. If newWritable is false, set newLenDesc.[[Writable] to false.
@@ -272,7 +275,9 @@ bool JSArray::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSVa
             return false;
         unsigned newLength = value.toUInt32(exec);
         RETURN_IF_EXCEPTION(scope, false);
-        if (value.toNumber(exec) != static_cast<double>(newLength)) {
+        double valueAsNumber = value.toNumber(exec);
+        RETURN_IF_EXCEPTION(scope, false);
+        if (valueAsNumber != static_cast<double>(newLength)) {
             throwException(exec, scope, createRangeError(exec, ASCIILiteral("Invalid array length")));
             return false;
         }
index 2deb8dd..cc0d374 100644 (file)
@@ -150,11 +150,14 @@ bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    if (std::optional<uint32_t> index = parseIndex(propertyName))
+    if (std::optional<uint32_t> index = parseIndex(propertyName)) {
+        scope.release();
         return putToPrimitiveByIndex(exec, index.value(), value, slot.isStrictMode());
+    }
 
     // Check if there are any setters or getters in the prototype chain
     JSObject* obj = synthesizePrototype(exec);
+    EXCEPTION_ASSERT(!!scope.exception() == !obj);
     if (UNLIKELY(!obj))
         return false;
     JSValue prototype;
@@ -176,8 +179,10 @@ bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
                 return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
 
             JSValue gs = obj->getDirect(offset);
-            if (gs.isGetterSetter())
+            if (gs.isGetterSetter()) {
+                scope.release();
                 return callSetter(exec, *this, gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
+            }
 
             if (gs.isCustomGetterSetter())
                 return callCustomSetter(exec, gs, attributes & CustomAccessor, obj, slot.thisValue(), value);
@@ -207,11 +212,13 @@ bool JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSVa
     }
     
     JSObject* prototype = synthesizePrototype(exec);
-    ASSERT(!prototype == !!scope.exception());
+    EXCEPTION_ASSERT(!!scope.exception() == !prototype);
     if (UNLIKELY(!prototype))
         return false;
     bool putResult = false;
-    if (prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow, putResult))
+    bool success = prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow, putResult);
+    RETURN_IF_EXCEPTION(scope, false);
+    if (success)
         return putResult;
     
     return typeError(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
index ff46040..a27f6a1 100644 (file)
@@ -59,7 +59,7 @@ inline uint32_t JSValue::toIndex(ExecState* exec, const char* errorName) const
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     double d = toNumber(exec);
-
+    RETURN_IF_EXCEPTION(scope, 0);
     if (d <= -1) {
         throwException(exec, scope, createRangeError(exec, makeString(errorName, " cannot be negative")));
         return 0;
@@ -71,6 +71,7 @@ inline uint32_t JSValue::toIndex(ExecState* exec, const char* errorName) const
 
     if (isInt32())
         return asInt32();
+    scope.release();
     return JSC::toInt32(d);
 }
 
@@ -796,8 +797,13 @@ ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, PropertyName propertyName) c
 
 ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
 {
-    return getPropertySlot(exec, propertyName, slot) ? 
-        slot.getValue(exec, propertyName) : jsUndefined();
+    auto scope = DECLARE_THROW_SCOPE(exec->vm());
+    bool hasSlot = getPropertySlot(exec, propertyName, slot);
+    EXCEPTION_ASSERT(!scope.exception() || !hasSlot);
+    if (!hasSlot)
+        return jsUndefined();
+    scope.release();
+    return slot.getValue(exec, propertyName);
 }
 
 template<typename CallbackWhenNoException>
@@ -813,23 +819,31 @@ ALWAYS_INLINE typename std::result_of<CallbackWhenNoException(bool, PropertySlot
     auto scope = DECLARE_THROW_SCOPE(exec->vm());
     bool found = getPropertySlot(exec, propertyName, slot);
     RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
     return callback(found, slot);
 }
 
 ALWAYS_INLINE bool JSValue::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
 {
+    auto scope = DECLARE_THROW_SCOPE(exec->vm());
     // If this is a primitive, we'll need to synthesize the prototype -
     // and if it's a string there are special properties to check first.
     JSObject* object;
     if (UNLIKELY(!isObject())) {
-        if (isString() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
-            return true;
+        if (isString()) {
+            bool hasProperty = asString(*this)->getStringPropertySlot(exec, propertyName, slot);
+            RETURN_IF_EXCEPTION(scope, false);
+            if (hasProperty)
+                return true;
+        }
         object = synthesizePrototype(exec);
+        EXCEPTION_ASSERT(!!scope.exception() == !object);
         if (UNLIKELY(!object))
             return false;
     } else
         object = asObject(asCell());
-    
+
+    scope.release();
     return object->getPropertySlot(exec, propertyName, slot);
 }
 
@@ -841,21 +855,32 @@ ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
 
 ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
 {
+    auto scope = DECLARE_THROW_SCOPE(exec->vm());
     // If this is a primitive, we'll need to synthesize the prototype -
     // and if it's a string there are special properties to check first.
     JSObject* object;
     if (UNLIKELY(!isObject())) {
-        if (isString() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
-            return slot.getValue(exec, propertyName);
+        if (isString()) {
+            bool hasProperty = asString(*this)->getStringPropertySlot(exec, propertyName, slot);
+            RETURN_IF_EXCEPTION(scope, { });
+            if (hasProperty) {
+                scope.release();
+                return slot.getValue(exec, propertyName);
+            }
+        }
         object = synthesizePrototype(exec);
+        EXCEPTION_ASSERT(!!scope.exception() == !object);
         if (UNLIKELY(!object))
             return JSValue();
     } else
         object = asObject(asCell());
     
-    if (object->getPropertySlot(exec, propertyName, slot))
-        return slot.getValue(exec, propertyName);
-    return jsUndefined();
+    bool hasSlot = object->getPropertySlot(exec, propertyName, slot);
+    EXCEPTION_ASSERT(!scope.exception() || !hasSlot);
+    if (!hasSlot)
+        return jsUndefined();
+    scope.release();
+    return slot.getValue(exec, propertyName);
 }
 
 ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, uint64_t propertyName) const
@@ -921,8 +946,10 @@ ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSV
 
         bool s1 = v1.isString();
         bool s2 = v2.isString();
-        if (s1 && s2)
+        if (s1 && s2) {
+            scope.release();
             return asString(v1)->equal(exec, asString(v2));
+        }
 
         if (v1.isUndefinedOrNull()) {
             if (v2.isUndefinedOrNull())
@@ -968,7 +995,9 @@ ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSV
 
         if (s1 || s2) {
             double d1 = v1.toNumber(exec);
+            RETURN_IF_EXCEPTION(scope, false);
             double d2 = v2.toNumber(exec);
+            RETURN_IF_EXCEPTION(scope, false);
             return d1 == d2;
         }
 
index 0eae871..8c40792 100644 (file)
@@ -100,13 +100,13 @@ inline JSObject* constructGenericTypedArrayViewFromIterator(ExecState* exec, Str
     }
 
     ViewClass* result = ViewClass::createUninitialized(exec, structure, storage.size());
-    ASSERT(!!scope.exception() == !result);
+    EXCEPTION_ASSERT(!!scope.exception() == !result);
     if (UNLIKELY(!result))
         return nullptr;
 
     for (unsigned i = 0; i < storage.size(); ++i) {
         bool success = result->setIndex(exec, i, storage.at(i));
-        ASSERT(scope.exception() || success);
+        EXCEPTION_ASSERT(scope.exception() || success);
         if (!success)
             return nullptr;
     }
@@ -197,7 +197,7 @@ inline JSObject* constructGenericTypedArrayViewWithArguments(ExecState* exec, St
 
         
         ViewClass* result = ViewClass::createUninitialized(exec, structure, length);
-        ASSERT(!!scope.exception() == !result);
+        EXCEPTION_ASSERT(!!scope.exception() == !result);
         if (UNLIKELY(!result))
             return nullptr;
         
index 9114615..bff4b36 100644 (file)
@@ -252,7 +252,7 @@ bool JSGenericTypedArrayView<Adaptor>::set(
         
         RELEASE_ASSERT(other->canAccessRangeQuickly(objectOffset, length));
         bool success = validateRange(exec, offset, length);
-        ASSERT(!scope.exception() == success);
+        EXCEPTION_ASSERT(!scope.exception() == success);
         if (!success)
             return false;
 
@@ -300,7 +300,7 @@ bool JSGenericTypedArrayView<Adaptor>::set(
     case NotTypedArray:
     case TypeDataView: {
         bool success = validateRange(exec, offset, length);
-        ASSERT(!scope.exception() == success);
+        EXCEPTION_ASSERT(!scope.exception() == success);
         if (!success)
             return false;
 
@@ -309,7 +309,7 @@ bool JSGenericTypedArrayView<Adaptor>::set(
             JSValue value = object->get(exec, i + objectOffset);
             RETURN_IF_EXCEPTION(scope, false);
             bool success = setIndex(exec, offset + i, value);
-            ASSERT(!scope.exception() || !success);
+            EXCEPTION_ASSERT(!scope.exception() || !success);
             if (!success)
                 return false;
         }
index 5127aa3..a22f3cb 100644 (file)
@@ -1045,7 +1045,7 @@ bool JSGlobalObject::put(JSCell* cell, ExecState* exec, PropertyName propertyNam
     bool ignoreReadOnlyErrors = false;
     bool putResult = false;
     bool done = symbolTablePutTouchWatchpointSet(thisObject, exec, propertyName, value, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
-    ASSERT((!!scope.exception() == (done && !putResult)) || !shouldThrowReadOnlyError);
+    EXCEPTION_ASSERT((!!scope.exception() == (done && !putResult)) || !shouldThrowReadOnlyError);
     if (done)
         return putResult;
     scope.release();
index b46819b..3719197 100644 (file)
@@ -231,6 +231,7 @@ static JSValue decode(ExecState* exec, const CharType* characters, int length, c
         k++;
         builder.append(c);
     }
+    scope.release();
     return builder.build(exec);
 }
 
@@ -486,22 +487,26 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec)
     String s = asString(x)->value(exec);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
+    JSValue parsedObject;
     if (s.is8Bit()) {
         LiteralParser<LChar> preparser(exec, s.characters8(), s.length(), NonStrictJSON);
-        if (JSValue parsedObject = preparser.tryLiteralParse())
-            return JSValue::encode(parsedObject);
+        parsedObject = preparser.tryLiteralParse();
     } else {
         LiteralParser<UChar> preparser(exec, s.characters16(), s.length(), NonStrictJSON);
-        if (JSValue parsedObject = preparser.tryLiteralParse())
-            return JSValue::encode(parsedObject);
+        parsedObject = preparser.tryLiteralParse();
     }
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    if (parsedObject)
+        return JSValue::encode(parsedObject);
 
     SourceOrigin sourceOrigin = exec->callerSourceOrigin();
     JSGlobalObject* calleeGlobalObject = exec->jsCallee()->globalObject();
     EvalExecutable* eval = IndirectEvalExecutable::create(exec, makeSource(s, sourceOrigin), false, DerivedContextType::None, false, EvalContextType::None);
+    EXCEPTION_ASSERT(!!scope.exception() == !eval);
     if (!eval)
-        return JSValue::encode(jsUndefined());
+        return encodedJSValue();
 
+    scope.release();
     return JSValue::encode(vm.interpreter->execute(eval, exec, calleeGlobalObject->globalThis(), calleeGlobalObject->globalScope()));
 }
 
@@ -706,11 +711,13 @@ EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
     JSObject* thisObject = jsDynamicCast<JSObject*>(vm, thisValue);
     if (!thisObject) {
         JSObject* prototype = exec->thisValue().synthesizePrototype(exec);
+        EXCEPTION_ASSERT(!!scope.exception() == !prototype);
         if (UNLIKELY(!prototype))
             return JSValue::encode(JSValue());
         return JSValue::encode(prototype);
     }
 
+    scope.release();
     return JSValue::encode(thisObject->getPrototype(vm, exec));
 }
 
@@ -735,6 +742,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
     if (!value.isObject() && !value.isNull())
         return JSValue::encode(jsUndefined());
 
+    scope.release();
     bool shouldThrowIfCantSet = true;
     thisObject->setPrototype(vm, exec, value, shouldThrowIfCantSet);
     return JSValue::encode(jsUndefined());
@@ -777,7 +785,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState* exec)
     auto* globalObject = exec->lexicalGlobalObject();
 
     auto* promise = JSPromiseDeferred::create(exec, globalObject);
-    RETURN_IF_EXCEPTION(catchScope, { });
+    CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue());
 
     auto sourceOrigin = exec->callerSourceOrigin();
     RELEASE_ASSERT(exec->argumentCount() == 1);
@@ -785,6 +793,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState* exec)
     if (Exception* exception = catchScope.exception()) {
         catchScope.clearException();
         promise->reject(exec, exception->value());
+        CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue());
         return JSValue::encode(promise->promise());
     }
 
@@ -792,9 +801,11 @@ EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState* exec)
     if (Exception* exception = catchScope.exception()) {
         catchScope.clearException();
         promise->reject(exec, exception->value());
+        CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue());
         return JSValue::encode(promise->promise());
     }
     promise->resolve(exec, internalPromise);
+    CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, encodedJSValue());
 
     return JSValue::encode(promise->promise());
 }
index 2f60c6e..c4eb16e 100644 (file)
@@ -53,7 +53,10 @@ JSInternalPromise::JSInternalPromise(VM& vm, Structure* structure)
 JSInternalPromise* JSInternalPromise::then(ExecState* exec, JSFunction* onFulfilled, JSFunction* onRejected)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().thenPublicName()));
+    RETURN_IF_EXCEPTION(scope, nullptr);
     CallData callData;
     CallType callType = JSC::getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -62,6 +65,7 @@ JSInternalPromise* JSInternalPromise::then(ExecState* exec, JSFunction* onFulfil
     arguments.append(onFulfilled ? onFulfilled : jsUndefined());
     arguments.append(onRejected ? onRejected : jsUndefined());
 
+    scope.release();
     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
 }
 
index 31d664d..179ba76 100644 (file)
@@ -40,13 +40,18 @@ const ClassInfo JSInternalPromiseDeferred::s_info = { "JSInternalPromiseDeferred
 JSInternalPromiseDeferred* JSInternalPromiseDeferred::create(ExecState* exec, JSGlobalObject* globalObject)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue deferred = newPromiseCapability(exec, globalObject, globalObject->internalPromiseConstructor());
+    RETURN_IF_EXCEPTION(scope, nullptr);
 
     JSValue promise = deferred.get(exec, vm.propertyNames->builtinNames().promisePrivateName());
+    RETURN_IF_EXCEPTION(scope, nullptr);
     ASSERT(promise.inherits(vm, JSInternalPromise::info()));
     JSValue resolve = deferred.get(exec, vm.propertyNames->builtinNames().resolvePrivateName());
+    RETURN_IF_EXCEPTION(scope, nullptr);
     JSValue reject = deferred.get(exec, vm.propertyNames->builtinNames().rejectPrivateName());
+    RETURN_IF_EXCEPTION(scope, nullptr);
 
     JSInternalPromiseDeferred* result = new (NotNull, allocateCell<JSInternalPromiseDeferred>(vm.heap)) JSInternalPromiseDeferred(vm);
     result->finishCreation(vm, jsCast<JSObject*>(promise), resolve, reject);
index 5d6e96d..adf8ada 100644 (file)
@@ -71,8 +71,11 @@ void JSJobMicrotask::run(ExecState* exec)
     ASSERT(handlerCallType != CallType::None);
 
     MarkedArgumentBuffer handlerArguments;
-    for (unsigned index = 0, length = m_arguments->length(); index < length; ++index)
-        handlerArguments.append(m_arguments->JSArray::get(exec, index));
+    for (unsigned index = 0, length = m_arguments->length(); index < length; ++index) {
+        JSValue arg = m_arguments->JSArray::get(exec, index);
+        CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
+        handlerArguments.append(arg);
+    }
     profiledCall(exec, ProfilingReason::Microtask, m_job.get(), handlerCallType, handlerCallData, jsUndefined(), handlerArguments);
     scope.clearException();
 }
index 119d699..24dbf77 100644 (file)
@@ -83,6 +83,7 @@ bool JSModuleEnvironment::getOwnPropertySlot(JSObject* cell, ExecState* exec, Pr
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell);
     AbstractModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid()));
+    RETURN_IF_EXCEPTION(scope, false);
     if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) {
         // When resolveImport resolves the resolution, the imported module environment must have the binding.
         JSModuleEnvironment* importedModuleEnvironment = resolution.moduleRecord->moduleEnvironment();
@@ -120,6 +121,7 @@ bool JSModuleEnvironment::put(JSCell* cell, ExecState* exec, PropertyName proper
     JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell);
     // All imported bindings are immutable.
     AbstractModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid()));
+    RETURN_IF_EXCEPTION(scope, false);
     if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) {
         throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
         return false;
@@ -129,9 +131,13 @@ bool JSModuleEnvironment::put(JSCell* cell, ExecState* exec, PropertyName proper
 
 bool JSModuleEnvironment::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell);
     // All imported bindings are immutable.
     AbstractModuleRecord::Resolution resolution = thisObject->moduleRecord()->resolveImport(exec, Identifier::fromUid(exec, propertyName.uid()));
+    RETURN_IF_EXCEPTION(scope, false);
     if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved)
         return false;
     return Base::deleteProperty(thisObject, exec, propertyName);
index 7d2a4f0..56a4c2f 100644 (file)
@@ -81,7 +81,10 @@ static String printableModuleKey(ExecState* exec, JSValue key)
 JSValue JSModuleLoader::provide(ExecState* exec, JSValue key, Status status, const SourceCode& sourceCode)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().providePublicName()));
+    RETURN_IF_EXCEPTION(scope, { });
     CallData callData;
     CallType callType = JSC::getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -92,13 +95,17 @@ JSValue JSModuleLoader::provide(ExecState* exec, JSValue key, Status status, con
     arguments.append(jsNumber(status));
     arguments.append(JSSourceCode::create(vm, WTFMove(source)));
 
+    scope.release();
     return call(exec, function, callType, callData, this, arguments);
 }
 
 JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().loadAndEvaluateModulePublicName()));
+    RETURN_IF_EXCEPTION(scope, nullptr);
     CallData callData;
     CallType callType = JSC::getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -108,13 +115,17 @@ JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValu
     arguments.append(referrer);
     arguments.append(scriptFetcher);
 
+    scope.release();
     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
 }
 
 JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().loadModulePublicName()));
+    RETURN_IF_EXCEPTION(scope, nullptr);
     CallData callData;
     CallType callType = JSC::getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -124,13 +135,17 @@ JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleNam
     arguments.append(referrer);
     arguments.append(scriptFetcher);
 
+    scope.release();
     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
 }
 
 JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().linkAndEvaluateModulePublicName()));
+    RETURN_IF_EXCEPTION(scope, { });
     CallData callData;
     CallType callType = JSC::getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -139,13 +154,17 @@ JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey
     arguments.append(moduleKey);
     arguments.append(scriptFetcher);
 
+    scope.release();
     return call(exec, function, callType, callData, this, arguments);
 }
 
 JSInternalPromise* JSModuleLoader::requestImportModule(ExecState* exec, const Identifier& moduleKey, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     auto* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().requestImportModulePublicName()));
+    RETURN_IF_EXCEPTION(scope, nullptr);
     CallData callData;
     auto callType = JSC::getCallData(function, callData);
     ASSERT(callType != CallType::None);
@@ -154,6 +173,7 @@ JSInternalPromise* JSModuleLoader::requestImportModule(ExecState* exec, const Id
     arguments.append(jsString(exec, moduleKey.impl()));
     arguments.append(scriptFetcher);
 
+    scope.release();
     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
 }
 
index 990ae82..e13f7a8 100644 (file)
@@ -82,6 +82,7 @@ void JSModuleRecord::link(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     ModuleProgramExecutable* executable = ModuleProgramExecutable::create(exec, sourceCode());
+    EXCEPTION_ASSERT(!!scope.exception() == !executable);
     if (!executable) {
         throwSyntaxError(exec, scope);
         return;
@@ -110,6 +111,7 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu
         const ExportEntry& exportEntry = pair.value;
         if (exportEntry.type == JSModuleRecord::ExportEntry::Type::Indirect) {
             Resolution resolution = resolveExport(exec, exportEntry.exportName);
+            RETURN_IF_EXCEPTION(scope, void());
             switch (resolution.type) {
             case Resolution::Type::NotFound:
                 throwSyntaxError(exec, scope, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' is not found."));
@@ -136,13 +138,16 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu
     for (const auto& pair : importEntries()) {
         const ImportEntry& importEntry = pair.value;
         AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
+        RETURN_IF_EXCEPTION(scope, void());
         if (importEntry.isNamespace(vm)) {
             JSModuleNamespaceObject* namespaceObject = importedModule->getModuleNamespace(exec);
             RETURN_IF_EXCEPTION(scope, void());
             bool putResult = false;
             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, importEntry.localName, namespaceObject, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);
+            RETURN_IF_EXCEPTION(scope, void());
         } else {
             Resolution resolution = importedModule->resolveExport(exec, importEntry.importName);
+            RETURN_IF_EXCEPTION(scope, void());
             switch (resolution.type) {
             case Resolution::Type::NotFound:
                 throwSyntaxError(exec, scope, makeString("Importing binding name '", String(importEntry.importName.impl()), "' is not found."));
@@ -173,6 +178,7 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu
         if (!offset.isStack()) {
             bool putResult = false;
             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromUid(exec, variable.key.get()), jsUndefined(), /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);
+            RETURN_IF_EXCEPTION(scope, void());
         }
     }
 
@@ -195,6 +201,7 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu
             JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable->source()), moduleEnvironment);
             bool putResult = false;
             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, unlinkedFunctionExecutable->name(), function, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);
+            RETURN_IF_EXCEPTION(scope, void());
         }
     }
 
index 0cf361f..0c7f3d1 100644 (file)
@@ -275,7 +275,7 @@ Local<Unknown> Stringifier::stringify(Handle<Unknown> value)
     StringBuilder result;
     Holder root(Holder::RootHolder, vm, object);
     auto stringifyResult = appendStringifiedValue(result, value.get(), root, emptyPropertyName);
-    ASSERT(!scope.exception() || (stringifyResult != StringifySucceeded));
+    EXCEPTION_ASSERT(!scope.exception() || (stringifyResult != StringifySucceeded));
     if (UNLIKELY(stringifyResult != StringifySucceeded))
         return Local<Unknown>(vm, jsUndefined());
 
@@ -294,7 +294,7 @@ ALWAYS_INLINE JSValue Stringifier::toJSON(JSValue value, const PropertyNameForFu
     JSObject* object = asObject(value);
     PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
     bool hasProperty = object->getPropertySlot(m_exec, vm.propertyNames->toJSON, slot);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (!hasProperty)
         return value;
 
@@ -794,7 +794,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
     if (view.is8Bit()) {
         LiteralParser<LChar> jsonParser(exec, view.characters8(), view.length(), StrictJSON);
         unfiltered = jsonParser.tryLiteralParse();
-        ASSERT(!scope.exception() || !unfiltered);
+        EXCEPTION_ASSERT(!scope.exception() || !unfiltered);
         if (!unfiltered) {
             RETURN_IF_EXCEPTION(scope, { });
             return throwVMError(exec, scope, createSyntaxError(exec, jsonParser.getErrorMessage()));
@@ -802,7 +802,7 @@ EncodedJSValue JSC_HOST_CALL JSONProtoFuncParse(ExecState* exec)
     } else {
         LiteralParser<UChar> jsonParser(exec, view.characters16(), view.length(), StrictJSON);
         unfiltered = jsonParser.tryLiteralParse();
-        ASSERT(!scope.exception() || !unfiltered);
+        EXCEPTION_ASSERT(!scope.exception() || !unfiltered);
         if (!unfiltered) {
             RETURN_IF_EXCEPTION(scope, { });
             return throwVMError(exec, scope, createSyntaxError(exec, jsonParser.getErrorMessage()));
index 95c15cf..adb6dc6 100644 (file)
@@ -535,6 +535,7 @@ String JSObject::calculatedClassName(JSObject* object)
     PropertySlot slot(object->getPrototypeDirect(), PropertySlot::InternalMethodType::VMInquiry);
     PropertyName constructor(vm.propertyNames->constructor);
     if (object->getPropertySlot(exec, constructor, slot)) {
+        EXCEPTION_ASSERT(!scope.exception());
         if (slot.isValue()) {
             JSValue constructorValue = slot.getValue(exec, constructor);
             if (constructorValue.isCell()) {
@@ -549,7 +550,7 @@ String JSObject::calculatedClassName(JSObject* object)
             }
         }
     }
-    ASSERT(!scope.exception() || prototypeFunctionName.isNull());
+    EXCEPTION_ASSERT(!scope.exception() || prototypeFunctionName.isNull());
     if (UNLIKELY(scope.exception()))
         scope.clearException();
 
@@ -658,6 +659,7 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
         if (current->type() == ProxyObjectType && propertyName != vm.propertyNames->underscoreProto) {
             ProxyObject* proxy = jsCast<ProxyObject*>(current);
             PutPropertySlot slot(receiver, shouldThrow);
+            scope.release();
             return proxy->ProxyObject::put(proxy, exec, propertyName, value, slot);
         }
 
@@ -716,11 +718,13 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
             valueDescriptor.setValue(value);
 
             // 9.1.9.1-4-d-iv Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
+            scope.release();
             return receiverObject->methodTable(vm)->defineOwnProperty(receiverObject, exec, propertyName, valueDescriptor, shouldThrow);
         }
 
         // 9.1.9.1-4-e Else Receiver does not currently have a property P,
         // 9.1.9.1-4-e-i Return ? CreateDataProperty(Receiver, P, V).
+        scope.release();
         return receiverObject->methodTable(vm)->defineOwnProperty(receiverObject, exec, propertyName, PropertyDescriptor(value, None), shouldThrow);
     }
 
@@ -740,6 +744,7 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
 
     CallData callData;
     CallType callType = setterObject->methodTable(vm)->getCallData(setterObject, callData);
+    scope.release();
     call(exec, setterObject, callType, callData, receiver, args);
 
     // 9.1.9.1-9 Return true.
@@ -772,6 +777,7 @@ bool JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue
             JSValue gs = obj->getDirect(offset);
             if (gs.isGetterSetter()) {
                 bool result = callSetter(exec, slot.thisValue(), gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode);
+                RETURN_IF_EXCEPTION(scope, false);
                 if (!structure()->isDictionary())
                     slot.setCacheableSetter(obj, offset);
                 return result;
@@ -792,8 +798,10 @@ bool JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue
         }
         if (!obj->staticPropertiesReified()) {
             if (obj->classInfo(vm)->hasStaticSetterOrReadonlyProperties()) {
-                if (auto entry = obj->findPropertyHashEntry(vm, propertyName))
+                if (auto entry = obj->findPropertyHashEntry(vm, propertyName)) {
+                    scope.release();
                     return putEntry(exec, entry->table->classForThis, entry->value, obj, this, propertyName, value, slot);
+                }
             }
         }
         if (obj->type() == ProxyObjectType && propertyName != vm.propertyNames->underscoreProto) {
@@ -801,6 +809,7 @@ bool JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue
             // We need to do more because this is observable behavior.
             // https://bugs.webkit.org/show_bug.cgi?id=155012
             ProxyObject* proxy = jsCast<ProxyObject*>(obj);
+            scope.release();
             return proxy->ProxyObject::put(proxy, exec, propertyName, value, slot);
         }
         JSValue prototype = obj->getPrototype(vm, exec);
@@ -1947,20 +1956,20 @@ JSValue JSObject::ordinaryToPrimitive(ExecState* exec, PreferredPrimitiveType hi
     JSValue value;
     if (hint == PreferString) {
         value = callToPrimitiveFunction(exec, this, vm.propertyNames->toString, hint);
-        ASSERT(!scope.exception() || scope.exception() == value.asCell());
+        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
         if (value)
             return value;
         value = callToPrimitiveFunction(exec, this, vm.propertyNames->valueOf, hint);
-        ASSERT(!scope.exception() || scope.exception() == value.asCell());
+        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
         if (value)
             return value;
     } else {
         value = callToPrimitiveFunction(exec, this, vm.propertyNames->valueOf, hint);
-        ASSERT(!scope.exception() || scope.exception() == value.asCell());
+        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
         if (value)
             return value;
         value = callToPrimitiveFunction(exec, this, vm.propertyNames->toString, hint);
-        ASSERT(!scope.exception() || scope.exception() == value.asCell());
+        EXCEPTION_ASSERT(!scope.exception() || scope.exception() == value.asCell());
         if (value)
             return value;
     }
@@ -1985,6 +1994,7 @@ JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredT
     if (value)
         return value;
 
+    scope.release();
     return this->methodTable(vm)->defaultValue(this, exec, preferredType);
 }
 
@@ -2046,10 +2056,13 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue hasInstanceVa
     if (info.implementsDefaultHasInstance()) {
         JSValue prototype = get(exec, vm.propertyNames->prototype);
         RETURN_IF_EXCEPTION(scope, false);
+        scope.release();
         return defaultHasInstance(exec, value, prototype);
     }
-    if (info.implementsHasInstance())
+    if (info.implementsHasInstance()) {
+        scope.release();
         return methodTable(vm)->customHasInstance(this, exec, value);
+    }
     throwException(exec, scope, createInvalidInstanceofParameterErrorNotFunction(exec, this));
     return false;
 }
@@ -2061,6 +2074,7 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value)
     JSValue hasInstanceValue = get(exec, vm.propertyNames->hasInstanceSymbol);
     RETURN_IF_EXCEPTION(scope, false);
 
+    scope.release();
     return hasInstance(exec, value, hasInstanceValue);
 }
 
@@ -2113,8 +2127,9 @@ void JSObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameA
     JSObject* prototype = asObject(nextProto);
     while(1) {
         if (prototype->structure(vm)->typeInfo().overridesGetPropertyNames()) {
+            scope.release();
             prototype->methodTable(vm)->getPropertyNames(prototype, exec, propertyNames, mode);
-            break;
+            return;
         }
         prototype->methodTable(vm)->getOwnPropertyNames(prototype, exec, propertyNames, mode);
         RETURN_IF_EXCEPTION(scope, void());
@@ -2221,6 +2236,7 @@ double JSObject::toNumber(ExecState* exec) const
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue primitive = toPrimitive(exec, PreferNumber);
     RETURN_IF_EXCEPTION(scope, 0.0); // should be picked up soon in Nodes.cpp
+    scope.release();
     return primitive.toNumber(exec);
 }
 
@@ -2388,6 +2404,7 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
         // state (i.e. defineOwnProperty could be used to set a value without needing to entering 'SparseMode').
         if (!descriptor.attributes() && descriptor.value() && canDoFastPutDirectIndex(this)) {
             ASSERT(!descriptor.isAccessorDescriptor());
+            scope.release();
             return putDirectIndex(exec, index, descriptor.value(), 0, throwException ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
         }
         
@@ -2439,7 +2456,9 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
     // 6. Return true, if every field in Desc also occurs in current and the value of every field in Desc is the same value as the corresponding field in current when compared using the SameValue algorithm (9.12).
     PropertyDescriptor current;
     entryInMap->get(current);
-    if (descriptor.isEmpty() || descriptor.equalTo(exec, current))
+    bool isEmptyOrEqual = descriptor.isEmpty() || descriptor.equalTo(exec, current);
+    RETURN_IF_EXCEPTION(scope, false);
+    if (isEmptyOrEqual)
         return true;
 
     // 7. If the [[Configurable]] field of current is false then
@@ -2574,6 +2593,7 @@ bool JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un
         ensureArrayStorageSlow(vm);
         SparseArrayValueMap* map = allocateSparseIndexMap(vm);
         bool result = map->putEntry(exec, this, i, value, false);
+        RETURN_IF_EXCEPTION(scope, false);
         ASSERT(i >= arrayStorage()->length());
         arrayStorage()->setLength(i + 1);
         return result;
@@ -2647,6 +2667,7 @@ bool JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, uns
         }
         // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
         map = allocateSparseIndexMap(vm);
+        scope.release();
         return map->putEntry(exec, this, i, value, shouldThrow);
     }
 
@@ -2663,8 +2684,10 @@ bool JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, uns
     // We are currently using a map - check whether we still want to be doing so.
     // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
     unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
-    if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length))
+    if (map->sparseMode() || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length)) {
+        scope.release();
         return map->putEntry(exec, this, i, value, shouldThrow);
+    }
 
     // Reread m_storage after increaseVectorLength, update m_numValuesInVector.
     storage = arrayStorage();
@@ -2783,6 +2806,7 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
         }
         // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
         map = allocateSparseIndexMap(vm);
+        scope.release();
         return map->putDirect(exec, this, i, value, attributes, mode);
     }
 
@@ -2803,8 +2827,10 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
     // We are currently using a map - check whether we still want to be doing so.
     // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
     unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
-    if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length))
+    if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length)) {
+        scope.release();
         return map->putDirect(exec, this, i, value, attributes, mode);
+    }
 
     // Reread m_storage after increaseVectorLength, update m_numValuesInVector.
     storage = arrayStorage();
@@ -3351,7 +3377,9 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     if (descriptor.isEmpty())
         return true;
     // Step 4.
-    if (current.equalTo(exec, descriptor))
+    bool isEqual = current.equalTo(exec, descriptor);
+    RETURN_IF_EXCEPTION(scope, false);
+    if (isEqual)
         return true;
 
     // Step 5.
@@ -3368,6 +3396,7 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     if (descriptor.isGenericDescriptor()) {
         if (!current.attributesEqual(descriptor) && object) {
             object->methodTable(vm)->deleteProperty(object, exec, propertyName);
+            RETURN_IF_EXCEPTION(scope, false);
             return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
         }
         return true;
@@ -3383,6 +3412,7 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
             return true;
 
         object->methodTable(vm)->deleteProperty(object, exec, propertyName);
+        RETURN_IF_EXCEPTION(scope, false);
         return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
     }
 
@@ -3402,6 +3432,7 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
         if (!object)
             return true;
         object->methodTable(vm)->deleteProperty(object, exec, propertyName);
+        RETURN_IF_EXCEPTION(scope, false);
         return putDescriptor(exec, object, propertyName, descriptor, descriptor.attributesOverridingCurrent(current), current);
     }
 
@@ -3447,6 +3478,7 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     if (current.attributesEqual(descriptor) && !getterSetterChanged)
         return true;
     object->methodTable(vm)->deleteProperty(object, exec, propertyName);
+    RETURN_IF_EXCEPTION(scope, false);
     unsigned attrs = descriptor.attributesOverridingCurrent(current);
     object->putDirectAccessor(exec, propertyName, getterSetter, attrs | Accessor);
     return true;
@@ -3466,6 +3498,7 @@ bool JSObject::defineOwnNonIndexProperty(ExecState* exec, PropertyName propertyN
     bool isCurrentDefined = getOwnPropertyDescriptor(exec, propertyName, current);
     bool isExtensible = this->isExtensible(exec);
     RETURN_IF_EXCEPTION(throwScope, false);
+    throwScope.release();
     return validateAndApplyPropertyDescriptor(exec, this, propertyName, isExtensible, descriptor, isCurrentDefined, current, throwException);
 }
 
@@ -3594,8 +3627,9 @@ void JSObject::getGenericPropertyNames(JSObject* object, ExecState* exec, Proper
     JSObject* prototype = asObject(nextProto);
     while (true) {
         if (prototype->structure(vm)->typeInfo().overridesGetPropertyNames()) {
+            scope.release();
             prototype->methodTable(vm)->getPropertyNames(prototype, exec, propertyNames, mode);
-            break;
+            return;
         }
         prototype->methodTable(vm)->getOwnPropertyNames(prototype, exec, propertyNames, mode);
         RETURN_IF_EXCEPTION(scope, void());
index 4be8636..ebd0ceb 100644 (file)
@@ -1413,19 +1413,29 @@ ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, PropertyName prope
 
 inline JSValue JSObject::get(ExecState* exec, PropertyName propertyName) const
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     PropertySlot slot(this, PropertySlot::InternalMethodType::Get);
-    if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
+    bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+    if (hasProperty) {
+        scope.release();
         return slot.getValue(exec, propertyName);
-    
+    }
     return jsUndefined();
 }
 
 inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     PropertySlot slot(this, PropertySlot::InternalMethodType::Get);
-    if (const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot))
+    bool hasProperty = const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+    if (hasProperty) {
+        scope.release();
         return slot.getValue(exec, propertyName);
-
+    }
     return jsUndefined();
 }
 
index e48e9b9..3863620 100644 (file)
@@ -97,6 +97,7 @@ ALWAYS_INLINE typename std::result_of<CallbackWhenNoException(bool, PropertySlot
     auto scope = DECLARE_THROW_SCOPE(vm);
     bool found = const_cast<JSObject*>(this)->getPropertySlot(exec, propertyName, slot);
     RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
     return callback(found, slot);
 }
 
@@ -109,9 +110,10 @@ ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyN
     MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
     while (true) {
         Structure* structure = structureIDTable.get(object->structureID());
-        if (structure->classInfo()->methodTable.getOwnPropertySlotByIndex(object, exec, propertyName, slot))
-            return true;
+        bool hasSlot = structure->classInfo()->methodTable.getOwnPropertySlotByIndex(object, exec, propertyName, slot);
         RETURN_IF_EXCEPTION(scope, false);
+        if (hasSlot)
+            return true;
         JSValue prototype;
         if (LIKELY(structure->classInfo()->methodTable.getPrototype == defaultGetPrototype || slot.internalMethodType() == PropertySlot::InternalMethodType::VMInquiry))
             prototype = structure->storedPrototype();
@@ -141,9 +143,10 @@ ALWAYS_INLINE bool JSObject::getNonIndexPropertySlot(ExecState* exec, PropertyNa
             if (object->getOwnNonIndexPropertySlot(vm, structure, propertyName, slot))
                 return true;
         } else {
-            if (structure->classInfo()->methodTable.getOwnPropertySlot(object, exec, propertyName, slot))
-                return true;
+            bool hasSlot = structure->classInfo()->methodTable.getOwnPropertySlot(object, exec, propertyName, slot);
             RETURN_IF_EXCEPTION(scope, false);
+            if (hasSlot)
+                return true;
         }
         JSValue prototype;
         if (LIKELY(structure->classInfo()->methodTable.getPrototype == defaultGetPrototype || slot.internalMethodType() == PropertySlot::InternalMethodType::VMInquiry))
@@ -203,13 +206,17 @@ ALWAYS_INLINE bool JSObject::putInlineForJSObject(JSCell* cell, ExecState* exec,
     ASSERT(value);
     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
 
-    if (UNLIKELY(isThisValueAltered(slot, thisObject)))
+    if (UNLIKELY(isThisValueAltered(slot, thisObject))) {
+        scope.release();
         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
+    }
 
     // Try indexed put first. This is required for correctness, since loads on property names that appear like
     // valid indices will never look in the named property storage.
-    if (std::optional<uint32_t> index = parseIndex(propertyName))
+    if (std::optional<uint32_t> index = parseIndex(propertyName)) {
+        scope.release();
         return putByIndex(thisObject, exec, index.value(), value, slot.isStrictMode());
+    }
 
     if (thisObject->canPerformFastPutInline(vm, propertyName)) {
         ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(vm, propertyName));
index 485bd3a..8600aa4 100644 (file)
@@ -106,6 +106,7 @@ static EncodedJSValue JSC_HOST_CALL constructPromise(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSPromise* promise = JSPromise::create(vm, promiseStructure);
     promise->initialize(exec, globalObject, exec->argument(0));
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     return JSValue::encode(promise);
 }
index 52a9e50..b50366e 100644 (file)
@@ -61,9 +61,12 @@ JSPromiseDeferred* JSPromiseDeferred::create(ExecState* exec, JSGlobalObject* gl
     RETURN_IF_EXCEPTION(scope, nullptr);
 
     JSValue promise = deferred.get(exec, vm.propertyNames->builtinNames().promisePrivateName());
+    RETURN_IF_EXCEPTION(scope, nullptr);
     ASSERT(promise.inherits(vm, JSPromise::info()));
     JSValue resolve = deferred.get(exec, vm.propertyNames->builtinNames().resolvePrivateName());
+    RETURN_IF_EXCEPTION(scope, nullptr);
     JSValue reject = deferred.get(exec, vm.propertyNames->builtinNames().rejectPrivateName());
+    RETURN_IF_EXCEPTION(scope, nullptr);
 
     return JSPromiseDeferred::create(vm, jsCast<JSPromise*>(promise), resolve, reject);
 }
index 36dead5..8ecb262 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2016 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2012-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
@@ -50,6 +50,9 @@ void JSScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
 // Returns true if we found enough information to terminate optimization.
 static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, size_t depth, bool& needsVarInjectionChecks, ResolveOp& op, InitializationMode initializationMode)
 {
+    VM& vm = exec->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
     if (scope->isJSLexicalEnvironment()) {
         JSLexicalEnvironment* lexicalEnvironment = jsCast<JSLexicalEnvironment*>(scope);
 
@@ -75,6 +78,7 @@ static inline bool abstractAccess(ExecState* exec, JSScope* scope, const Identif
             JSModuleEnvironment* moduleEnvironment = jsCast<JSModuleEnvironment*>(scope);
             AbstractModuleRecord* moduleRecord = moduleEnvironment->moduleRecord();
             AbstractModuleRecord::Resolution resolution = moduleRecord->resolveImport(exec, ident);
+            RETURN_IF_EXCEPTION(throwScope, false);
             if (resolution.type == AbstractModuleRecord::Resolution::Type::Resolved) {
                 AbstractModuleRecord* importedRecord = resolution.moduleRecord;
                 JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironment();
@@ -246,7 +250,7 @@ ALWAYS_INLINE JSObject* JSScope::resolve(ExecState* exec, JSScope* scope, const
         RETURN_IF_EXCEPTION(throwScope, nullptr);
         if (hasProperty) {
             bool unscopable = isUnscopable(exec, scope, object, ident);
-            ASSERT(!throwScope.exception() || !unscopable);
+            EXCEPTION_ASSERT(!throwScope.exception() || !unscopable);
             if (!unscopable)
                 return object;
         }
@@ -259,6 +263,8 @@ ALWAYS_INLINE JSObject* JSScope::resolve(ExecState* exec, JSScope* scope, const
 JSValue JSScope::resolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope* scope, const Identifier& ident)
 {
     VM& vm = exec->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
     auto returnPredicate = [&] (JSScope* scope) -> bool {
         return scope->isVarScope();
     };
@@ -266,7 +272,8 @@ JSValue JSScope::resolveScopeForHoistingFuncDeclInEval(ExecState* exec, JSScope*
         return scope->isWithScope();
     };
     JSObject* object = resolve(exec, scope, ident, returnPredicate, skipPredicate);
-    
+    RETURN_IF_EXCEPTION(throwScope, { });
+
     bool result = false;
     if (JSScope* scope = jsDynamicCast<JSScope*>(vm, object)) {
         if (SymbolTable* scopeSymbolTable = scope->symbolTable(vm)) {
@@ -292,6 +299,9 @@ JSObject* JSScope::resolve(ExecState* exec, JSScope* scope, const Identifier& id
 
 ResolveOp JSScope::abstractResolve(ExecState* exec, size_t depthOffset, JSScope* scope, const Identifier& ident, GetOrPut getOrPut, ResolveType unlinkedType, InitializationMode initializationMode)
 {
+    VM& vm = exec->vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+
     ResolveOp op(Dynamic, 0, 0, 0, 0, 0);
     if (unlinkedType == Dynamic)
         return op;
@@ -299,7 +309,9 @@ ResolveOp JSScope::abstractResolve(ExecState* exec, size_t depthOffset, JSScope*
     bool needsVarInjectionChecks = JSC::needsVarInjectionChecks(unlinkedType);
     size_t depth = depthOffset;
     for (; scope; scope = scope->next()) {
-        if (abstractAccess(exec, scope, ident, getOrPut, depth, needsVarInjectionChecks, op, initializationMode))
+        bool success = abstractAccess(exec, scope, ident, getOrPut, depth, needsVarInjectionChecks, op, initializationMode);
+        RETURN_IF_EXCEPTION(throwScope, ResolveOp(Dynamic, 0, 0, 0, 0, 0));
+        if (success)
             break;
         ++depth;
     }
index 8d86269..893de8b 100644 (file)
@@ -51,22 +51,24 @@ static ALWAYS_INLINE bool isJSONWhiteSpace(const CharType& c)
 template <typename CharType>
 bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool needsFullSourceInfo)
 {
+    VM& vm = m_exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     if (m_lexer.next() != TokIdentifier)
         return false;
     do {
         Vector<JSONPPathEntry> path;
         // Unguarded next to start off the lexer
-        Identifier name = Identifier::fromString(&m_exec->vm(), m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
+        Identifier name = Identifier::fromString(&vm, m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
         JSONPPathEntry entry;
-        if (name == m_exec->vm().propertyNames->varKeyword) {
+        if (name == vm.propertyNames->varKeyword) {
             if (m_lexer.next() != TokIdentifier)
                 return false;
             entry.m_type = JSONPPathEntryTypeDeclare;
-            entry.m_pathEntryName = Identifier::fromString(&m_exec->vm(), m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
+            entry.m_pathEntryName = Identifier::fromString(&vm, m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
             path.append(entry);
         } else {
             entry.m_type = JSONPPathEntryTypeDot;
-            entry.m_pathEntryName = Identifier::fromString(&m_exec->vm(), m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
+            entry.m_pathEntryName = Identifier::fromString(&vm, m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
             path.append(entry);
         }
         if (isLexerKeyword(entry.m_pathEntryName))
@@ -93,7 +95,7 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
                 entry.m_type = JSONPPathEntryTypeDot;
                 if (m_lexer.next() != TokIdentifier)
                     return false;
-                entry.m_pathEntryName = Identifier::fromString(&m_exec->vm(), m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
+                entry.m_pathEntryName = Identifier::fromString(&vm, m_lexer.currentToken()->start, m_lexer.currentToken()->end - m_lexer.currentToken()->start);
                 break;
             }
             case TokLParen: {
@@ -112,7 +114,9 @@ bool LiteralParser<CharType>::tryJSONPParse(Vector<JSONPData>& results, bool nee
     startJSON:
         m_lexer.next();
         results.append(JSONPData());
-        results.last().m_value.set(m_exec->vm(), parse(StartParseExpression));
+        JSValue startParseExpressionValue = parse(StartParseExpression);
+        RETURN_IF_EXCEPTION(scope, false);
+        results.last().m_value.set(vm, startParseExpressionValue);
         if (!results.last().m_value)
             return false;
         results.last().m_path.swap(path);
@@ -612,7 +616,8 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
             case DoParseArrayEndExpression: {
                 JSArray* array = asArray(objectStack.last());
                 array->putDirectIndex(m_exec, array->length(), lastValue);
-                
+                RETURN_IF_EXCEPTION(scope, JSValue());
+
                 if (m_lexer.currentToken()->type == TokComma)
                     goto doParseArrayStartExpression;
 
@@ -699,6 +704,7 @@ JSValue LiteralParser<CharType>::parse(ParserState initialState)
                     else
                         object->putDirect(vm, ident, lastValue);
                 }
+                RETURN_IF_EXCEPTION(scope, JSValue());
                 identifierStack.removeLast();
                 if (m_lexer.currentToken()->type == TokComma)
                     goto doParseObjectStartExpression;
index b95b145..dc4c0ce 100644 (file)
@@ -290,6 +290,7 @@ inline bool putEntry(ExecState* exec, const ClassInfo*, const HashTableValue* en
         bool isAccessor = entry->attributes() & CustomAccessor;
         JSValue updateThisValue = entry->attributes() & CustomAccessor ? slot.thisValue() : JSValue(base);
         bool result = callCustomSetter(exec, entry->propertyPutter(), isAccessor, updateThisValue, value);
+        RETURN_IF_EXCEPTION(scope, false);
         if (isAccessor)
             slot.setCustomAccessor(base, entry->propertyPutter());
         else
index 0a50770..203095d 100644 (file)
@@ -64,13 +64,17 @@ static EncodedJSValue JSC_HOST_CALL constructMap(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     JSValue iterable = exec->argument(0);
-    if (iterable.isUndefinedOrNull())
+    if (iterable.isUndefinedOrNull()) {
+        scope.release();
         return JSValue::encode(JSMap::create(exec, vm, mapStructure));
+    }
 
     if (isJSMap(iterable)) {
         JSMap* iterableMap = jsCast<JSMap*>(iterable);
-        if (iterableMap->canCloneFastAndNonObservable(mapStructure))
+        if (iterableMap->canCloneFastAndNonObservable(mapStructure)) {
+            scope.release();
             return JSValue::encode(iterableMap->clone(exec, vm, mapStructure));
+        }
     }
 
     JSMap* map = JSMap::create(exec, vm, mapStructure);
index 75fcee3..c17b5eb 100644 (file)
@@ -598,9 +598,11 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
         return throwVMTypeError(exec, scope);
 
     int32_t radix = extractRadixFromArgs(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
     if (radix < 2 || radix > 36)
         return throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
 
+    scope.release();
     return JSValue::encode(numberToStringInternal(vm, doubleValue, radix));
 }
 
index 33b7f43..f574002 100644 (file)
@@ -188,7 +188,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorSetPrototypeOf(ExecState* exec)
 
     bool shouldThrowIfCantSet = true;
     bool didSetPrototype = object->setPrototype(vm, exec, protoValue, shouldThrowIfCantSet);
-    ASSERT_UNUSED(didSetPrototype, scope.exception() || didSetPrototype);
+    EXCEPTION_ASSERT_UNUSED(didSetPrototype, scope.exception() || didSetPrototype);
     return JSValue::encode(objectValue);
 }
 
@@ -204,7 +204,7 @@ JSValue objectConstructorGetOwnPropertyDescriptor(ExecState* exec, JSObject* obj
     RETURN_IF_EXCEPTION(scope, { });
 
     JSObject* result = constructObjectFromPropertyDescriptor(exec, descriptor);
-    ASSERT(!!scope.exception() == !result);
+    EXCEPTION_ASSERT(!!scope.exception() == !result);
     if (!result)
         return jsUndefined();
     return result;
@@ -230,7 +230,7 @@ JSValue objectConstructorGetOwnPropertyDescriptors(ExecState* exec, JSObject* ob
             continue;
 
         JSObject* fromDescriptor = constructObjectFromPropertyDescriptor(exec, descriptor);
-        ASSERT(!!scope.exception() == !fromDescriptor);
+        EXCEPTION_ASSERT(!!scope.exception() == !fromDescriptor);
         if (!fromDescriptor)
             return jsUndefined();
 
@@ -322,7 +322,9 @@ EncodedJSValue JSC_HOST_CALL objectConstructorAssign(ExecState* exec)
 
         auto assign = [&] (PropertyName propertyName) {
             PropertySlot slot(source, PropertySlot::InternalMethodType::GetOwnProperty);
-            if (!source->methodTable(vm)->getOwnPropertySlot(source, exec, propertyName, slot))
+            bool hasProperty = source->methodTable(vm)->getOwnPropertySlot(source, exec, propertyName, slot);
+            RETURN_IF_EXCEPTION(scope, void());
+            if (!hasProperty)
                 return;
             if (slot.attributes() & DontEnum)
                 return;
@@ -386,7 +388,9 @@ EncodedJSValue JSC_HOST_CALL objectConstructorValues(ExecState* exec)
 
     auto addValue = [&] (PropertyName propertyName) {
         PropertySlot slot(target, PropertySlot::InternalMethodType::GetOwnProperty);
-        if (!target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot))
+        bool hasProperty = target->methodTable(vm)->getOwnPropertySlot(target, exec, propertyName, slot);
+        RETURN_IF_EXCEPTION(scope, void());
+        if (!hasProperty)
             return;
         if (slot.attributes() & DontEnum)
             return;
@@ -428,7 +432,7 @@ bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
     JSObject* description = asObject(in);
 
     bool hasProperty = description->hasProperty(exec, vm.propertyNames->enumerable);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         JSValue value = description->get(exec, vm.propertyNames->enumerable);
         RETURN_IF_EXCEPTION(scope, false);
@@ -437,7 +441,7 @@ bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
         RETURN_IF_EXCEPTION(scope, false);
 
     hasProperty = description->hasProperty(exec, vm.propertyNames->configurable);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         JSValue value = description->get(exec, vm.propertyNames->configurable);
         RETURN_IF_EXCEPTION(scope, false);
@@ -447,7 +451,7 @@ bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
 
     JSValue value;
     hasProperty = description->hasProperty(exec, vm.propertyNames->value);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         JSValue value = description->get(exec, vm.propertyNames->value);
         RETURN_IF_EXCEPTION(scope, false);
@@ -456,7 +460,7 @@ bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
         RETURN_IF_EXCEPTION(scope, false);
 
     hasProperty = description->hasProperty(exec, vm.propertyNames->writable);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         JSValue value = description->get(exec, vm.propertyNames->writable);
         RETURN_IF_EXCEPTION(scope, false);
@@ -465,7 +469,7 @@ bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
         RETURN_IF_EXCEPTION(scope, false);
 
     hasProperty = description->hasProperty(exec, vm.propertyNames->get);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         JSValue get = description->get(exec, vm.propertyNames->get);
         RETURN_IF_EXCEPTION(scope, false);
@@ -481,7 +485,7 @@ bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
         RETURN_IF_EXCEPTION(scope, false);
 
     hasProperty = description->hasProperty(exec, vm.propertyNames->set);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         JSValue set = description->get(exec, vm.propertyNames->set);
         RETURN_IF_EXCEPTION(scope, false);
@@ -523,7 +527,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     PropertyDescriptor descriptor;
     auto success = toPropertyDescriptor(exec, exec->argument(2), descriptor);
-    ASSERT(!scope.exception() == success);
+    EXCEPTION_ASSERT(!scope.exception() == success);
     if (!success)
         return JSValue::encode(jsNull());
     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
@@ -549,7 +553,7 @@ static JSValue defineProperties(ExecState* exec, JSObject* object, JSObject* pro
         RETURN_IF_EXCEPTION(scope, { });
         PropertyDescriptor descriptor;
         bool success = toPropertyDescriptor(exec, prop, descriptor);
-        ASSERT(!scope.exception() || !success);
+        EXCEPTION_ASSERT(!scope.exception() || !success);
         if (UNLIKELY(!success))
             return jsNull();
         descriptors.append(descriptor);
@@ -582,7 +586,7 @@ EncodedJSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState* exec)
         return throwVMTypeError(exec, scope, ASCIILiteral("Properties can only be defined on Objects."));
     JSObject* targetObj = asObject(exec->argument(0));
     JSObject* props = exec->argument(1).toObject(exec);
-    ASSERT(!!scope.exception() == !props);
+    EXCEPTION_ASSERT(!!scope.exception() == !props);
     if (UNLIKELY(!props))
         return encodedJSValue();
     scope.release();
@@ -856,7 +860,9 @@ JSArray* ownPropertyKeys(ExecState* exec, JSObject* object, PropertyNameMode pro
         for (size_t i = 0; i < numProperties; i++) {
             const auto& identifier = properties[i];
             ASSERT(!identifier.isSymbol());
-            if (filterPropertyIfNeeded(identifier))
+            bool hasProperty = filterPropertyIfNeeded(identifier);
+            EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+            if (hasProperty)
                 keys->push(exec, jsOwnedString(exec, identifier.string()));
             RETURN_IF_EXCEPTION(scope, nullptr);
         }
@@ -869,7 +875,9 @@ JSArray* ownPropertyKeys(ExecState* exec, JSObject* object, PropertyNameMode pro
             const auto& identifier = properties[i];
             ASSERT(identifier.isSymbol());
             if (!identifier.isPrivateName()) {
-                if (filterPropertyIfNeeded(identifier))
+                bool hasProperty = filterPropertyIfNeeded(identifier);
+                EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+                if (hasProperty)
                     keys->push(exec, Symbol::create(vm, static_cast<SymbolImpl&>(*identifier.impl())));
                 RETURN_IF_EXCEPTION(scope, nullptr);
             }
@@ -885,7 +893,9 @@ JSArray* ownPropertyKeys(ExecState* exec, JSObject* object, PropertyNameMode pro
             if (identifier.isSymbol() && !identifier.isPrivateName())
                 propertySymbols.append(identifier);
             else {
-                if (filterPropertyIfNeeded(identifier))
+                bool hasProperty = filterPropertyIfNeeded(identifier);
+                EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+                if (hasProperty)
                     keys->push(exec, jsOwnedString(exec, identifier.string()));
                 RETURN_IF_EXCEPTION(scope, nullptr);
             }
@@ -893,7 +903,9 @@ JSArray* ownPropertyKeys(ExecState* exec, JSObject* object, PropertyNameMode pro
 
         // To ensure the order defined in the spec (9.1.12), we append symbols at the last elements of keys.
         for (const auto& identifier : propertySymbols) {
-            if (filterPropertyIfNeeded(identifier))
+            bool hasProperty = filterPropertyIfNeeded(identifier);
+            EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+            if (hasProperty)
                 keys->push(exec, Symbol::create(vm, static_cast<SymbolImpl&>(*identifier.impl())));
             RETURN_IF_EXCEPTION(scope, nullptr);
         }
index aa350fb..e7d5f6d 100644 (file)
@@ -97,7 +97,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec)
     auto propertyName = exec->argument(0).toPropertyKey(exec);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSObject* thisObject = thisValue.toObject(exec);
-    ASSERT(!!scope.exception() == !thisObject);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
     if (UNLIKELY(!thisObject))
         return encodedJSValue();
 
@@ -124,7 +124,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec)
 
     JSValue thisValue = exec->thisValue().toThis(exec, StrictMode);
     JSObject* thisObj = thisValue.toObject(exec);
-    ASSERT(!!scope.exception() == !thisObj);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
 
@@ -213,7 +213,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupGetter(ExecState* exec)
 
     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
     bool hasProperty = thisObject->getPropertySlot(exec, propertyName, slot);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         if (slot.isAccessor()) {
             GetterSetter* getterSetter = slot.getterSetter();
@@ -243,7 +243,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState* exec)
 
     PropertySlot slot(thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
     bool hasProperty = thisObject->getPropertySlot(exec, propertyName, slot);
-    ASSERT(!scope.exception() || !hasProperty);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     if (hasProperty) {
         if (slot.isAccessor()) {
             GetterSetter* getterSetter = slot.getterSetter();
@@ -295,6 +295,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec)
     // Let toString be the O.[[Get]]("toString", V)
     PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
     bool hasProperty = object->getPropertySlot(exec, vm.propertyNames->toString, slot);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
     JSValue toString = hasProperty ? slot.getValue(exec, vm.propertyNames->toString) : jsUndefined();
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
@@ -318,7 +319,7 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec)
     if (thisValue.isUndefinedOrNull())
         return JSValue::encode(thisValue.isUndefined() ? vm.smallStrings.undefinedObjectString() : vm.smallStrings.nullObjectString());
     JSObject* thisObject = thisValue.toObject(exec);
-    ASSERT(!!scope.exception() == !thisObject);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
     if (!thisObject)
         return JSValue::encode(jsUndefined());
 
index 64f7830..de9620e 100644 (file)
@@ -394,7 +394,7 @@ typedef const char* optionString;
     v(bool, useExceptionFuzz, false, Normal, nullptr) \
     v(unsigned, fireExceptionFuzzAt, 0, Normal, nullptr) \
     v(bool, validateDFGExceptionHandling, false, Normal, "Causes the DFG to emit code validating exception handling for each node that can exit") /* This is true by default on Debug builds */\
-    v(bool, dumpSimulatedThrows, false, Normal, "Dumps the call stack at each simulated throw for exception scope verification") \
+    v(bool, dumpSimulatedThrows, false, Normal, "Dumps the call stack of the last simulated throw if exception scope verification fails") \
     v(bool, validateExceptionChecks, false, Normal, "Verifies that needed exception checks are performed.") \
     v(unsigned, unexpectedExceptionStackTraceLimit, 100, Normal, "Stack trace limit for debugging unexpected exceptions observed in the VM") \
     \
index 209242b..e4795ec 100644 (file)
@@ -217,10 +217,12 @@ static ALWAYS_INLINE typename std::result_of<CallbackWhenNoException(StringView)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSString* string = value.toStringOrNull(exec);
+    EXCEPTION_ASSERT(!!scope.exception() == !string);
     if (UNLIKELY(!string))
         return { };
     auto viewWithString = string->viewWithUnderlyingString(exec);
     RETURN_IF_EXCEPTION(scope, { });
+    scope.release();
     return callback(viewWithString.view);
 }
 
index 8492130..9231b0e 100644 (file)
@@ -130,8 +130,12 @@ static JSValue performProxyGet(ExecState* exec, ProxyObject* proxyObject, JSValu
     auto performDefaultGet = [&] {
         scope.release();
         PropertySlot slot(receiver, PropertySlot::InternalMethodType::Get);
-        if (target->getPropertySlot(exec, propertyName, slot))
+        bool hasProperty = target->getPropertySlot(exec, propertyName, slot);
+        EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+        if (hasProperty) {
+            scope.release();
             return slot.getValue(exec, propertyName);
+        }
         return jsUndefined();
     };
 
@@ -442,7 +446,9 @@ bool ProxyObject::performPut(ExecState* exec, JSValue putValue, JSValue thisValu
         return false;
 
     PropertyDescriptor descriptor;
-    if (target->getOwnPropertyDescriptor(exec, propertyName, descriptor)) {
+    bool hasProperty = target->getOwnPropertyDescriptor(exec, propertyName, descriptor);
+    EXCEPTION_ASSERT(!scope.exception() || !hasProperty);
+    if (hasProperty) {
         if (descriptor.isDataDescriptor() && !descriptor.configurable() && !descriptor.writable()) {
             if (!sameValue(exec, descriptor.value(), putValue)) {
                 throwVMTypeError(exec, scope, ASCIILiteral("Proxy handler's 'set' on a non-configurable and non-writable property on 'target' should either return false or be the same value already on the 'target'"));
index af0c35f..e9de113 100644 (file)
@@ -140,7 +140,7 @@ EncodedJSValue JSC_HOST_CALL reflectObjectDefineProperty(ExecState* exec)
 
     PropertyDescriptor descriptor;
     bool success = toPropertyDescriptor(exec, exec->argument(2), descriptor);
-    ASSERT(!scope.exception() == success);
+    EXCEPTION_ASSERT(!scope.exception() == success);
     if (UNLIKELY(!success))
         return encodedJSValue();
     ASSERT((descriptor.attributes() & Accessor) || (!descriptor.isAccessorDescriptor()));
index 5822985..e5d0aae 100644 (file)
@@ -213,7 +213,7 @@ inline RegExpFlags toFlags(ExecState* exec, JSValue flags)
     if (flags.isUndefined())
         return NoFlags;
     JSString* flagsString = flags.toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !flagsString);
+    EXCEPTION_ASSERT(!!scope.exception() == !flagsString);
     if (UNLIKELY(!flagsString))
         return InvalidFlags;
 
@@ -233,7 +233,7 @@ static JSObject* regExpCreate(ExecState* exec, JSGlobalObject* globalObject, JSV
     RETURN_IF_EXCEPTION(scope, nullptr);
 
     RegExpFlags flags = toFlags(exec, flagsArg);
-    ASSERT(!!scope.exception() == (flags == InvalidFlags));
+    EXCEPTION_ASSERT(!!scope.exception() == (flags == InvalidFlags));
     if (UNLIKELY(flags == InvalidFlags))
         return nullptr;
 
@@ -273,7 +273,7 @@ JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const A
 
         if (!flagsArg.isUndefined()) {
             RegExpFlags flags = toFlags(exec, flagsArg);
-            ASSERT(!!scope.exception() == (flags == InvalidFlags));
+            EXCEPTION_ASSERT(!!scope.exception() == (flags == InvalidFlags));
             if (flags == InvalidFlags)
                 return nullptr;
             regExp = RegExp::create(vm, regExp->pattern(), flags);
index af69849..1d3c508 100644 (file)
@@ -232,7 +232,7 @@ JSValue collectMatches(VM& vm, ExecState* exec, JSString* string, const String&
             result = savedResult;
             do {
                 iterate();
-                ASSERT(!!scope.exception() == hasException);
+                EXCEPTION_ASSERT(!!scope.exception() == hasException);
                 if (UNLIKELY(hasException))
                     return { };
             } while (result);
index 296bd15..01514f3 100644 (file)
@@ -75,7 +75,7 @@ JSValue RegExpObject::execInline(ExecState* exec, JSGlobalObject* globalObject,
     unsigned lastIndex;
     if (globalOrSticky) {
         lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
-        ASSERT(!scope.exception() || lastIndex == UINT_MAX);
+        EXCEPTION_ASSERT(!scope.exception() || lastIndex == UINT_MAX);
         if (lastIndex == UINT_MAX)
             return jsNull();
     } else
@@ -114,7 +114,7 @@ MatchResult RegExpObject::matchInline(
         return regExpConstructor->performMatch(vm, regExp, string, input, 0);
 
     unsigned lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
-    ASSERT(!scope.exception() || (lastIndex == UINT_MAX));
+    EXCEPTION_ASSERT(!scope.exception() || (lastIndex == UINT_MAX));
     if (lastIndex == UINT_MAX)
         return MatchResult::failed();
     
index 6c5d19b..4305482 100644 (file)
@@ -107,7 +107,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncTestFast(ExecState* exec)
     if (!thisValue.inherits(vm, RegExpObject::info()))
         return throwVMTypeError(exec, scope);
     JSString* string = exec->argument(0).toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !string);
+    EXCEPTION_ASSERT(!!scope.exception() == !string);
     if (!string)
         return JSValue::encode(jsUndefined());
     scope.release();
@@ -123,7 +123,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
     if (!thisValue.inherits(vm, RegExpObject::info()))
         return throwVMTypeError(exec, scope, "Builtin RegExp exec can only be called on a RegExp object");
     JSString* string = exec->argument(0).toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !string);
+    EXCEPTION_ASSERT(!!scope.exception() == !string);
     if (!string)
         return JSValue::encode(jsUndefined());
     scope.release();
@@ -139,7 +139,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchFast(ExecState* exec)
     if (!thisValue.inherits(vm, RegExpObject::info()))
         return throwVMTypeError(exec, scope);
     JSString* string = exec->argument(0).toStringOrNull(exec);
-    ASSERT(!!scope.exception() == !string);
+    EXCEPTION_ASSERT(!!scope.exception() == !string);
     if (!string)
         return encodedJSValue();
     if (!asRegExpObject(thisValue)->regExp()->global()) {
@@ -243,7 +243,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec)
     JSObject* thisObject = asObject(thisValue);
 
     StringRecursionChecker checker(exec, thisObject);
-    ASSERT(!scope.exception() || checker.earlyReturnValue());
+    EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
@@ -627,6 +627,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncSplitFast(ExecState* exec)
     // 13. If limit is undefined, let lim be 2^32-1; else let lim be ? ToUint32(limit).
     JSValue limitValue = exec->argument(1);
     unsigned limit = limitValue.isUndefined() ? 0xFFFFFFFFu : limitValue.toUInt32(exec);
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     // 14. Let size be the number of elements in S.
     unsigned inputSize = input.length();
index 2722124..bb2aa70 100644 (file)
@@ -188,7 +188,7 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
         auto codeBlock = EvalCodeBlock::create(vm,
             executable, executable->m_unlinkedEvalCodeBlock.get(), scope,
             executable->source().provider());
-        ASSERT(throwScope.exception() || codeBlock);
+        EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
         if (!codeBlock) {
             exception = throwException(
                 exec, throwScope,
@@ -206,7 +206,7 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
         auto codeBlock = ProgramCodeBlock::create(vm,
             executable, executable->m_unlinkedProgramCodeBlock.get(), scope,
             executable->source().provider(), startColumn());
-        ASSERT(throwScope.exception() || codeBlock);
+        EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
         if (!codeBlock) {
             exception = throwException(
                 exec, throwScope,
@@ -224,7 +224,7 @@ CodeBlock* ScriptExecutable::newCodeBlockFor(
         auto codeBlock = ModuleProgramCodeBlock::create(vm,
             executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope,
             executable->source().provider(), startColumn());
-        ASSERT(throwScope.exception() || codeBlock);
+        EXCEPTION_ASSERT(throwScope.exception() || codeBlock);
         if (!codeBlock) {
             exception = throwException(
                 exec, throwScope,
@@ -338,7 +338,7 @@ JSObject* ScriptExecutable::prepareForExecutionImpl(
     JSObject* exception = nullptr;
     CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);
     resultCodeBlock = codeBlock;
-    ASSERT(!!throwScope.exception() == !codeBlock);
+    EXCEPTION_ASSERT(!!throwScope.exception() == !codeBlock);
     if (UNLIKELY(!codeBlock))
         return exception;
     
index 286ca39..eb10f4d 100644 (file)
@@ -64,13 +64,17 @@ static EncodedJSValue JSC_HOST_CALL constructSet(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     JSValue iterable = exec->argument(0);
-    if (iterable.isUndefinedOrNull())
+    if (iterable.isUndefinedOrNull()) {
+        scope.release();
         return JSValue::encode(JSSet::create(exec, vm, setStructure));
+    }
 
     if (isJSSet(iterable)) {
         JSSet* iterableSet = jsCast<JSSet*>(iterable);
-        if (iterableSet->canCloneFastAndNonObservable(setStructure))
+        if (iterableSet->canCloneFastAndNonObservable(setStructure)) {
+            scope.release();
             return JSValue::encode(iterableSet->clone(exec, vm, setStructure));
+        }
     }
 
     JSSet* set = JSSet::create(exec, vm, setStructure);
index 03c0bf7..06e9303 100644 (file)
@@ -100,12 +100,8 @@ void ThrowScope::simulateThrow()
     m_vm.m_simulatedThrowPointLocation = m_location;
     m_vm.m_simulatedThrowPointRecursionDepth = m_recursionDepth;
     m_vm.m_needExceptionCheck = true;
-
-    if (Options::dumpSimulatedThrows()) {
-        dataLog("Simulated throw from this scope: ", m_location, "\n");
-        dataLog("    (ExceptionScope::m_recursionDepth was ", m_recursionDepth, ")\n");
-        WTFReportBacktrace();
-    }
+    if (UNLIKELY(Options::dumpSimulatedThrows()))
+        m_vm.m_nativeStackTraceOfLastSimulatedThrow = StackTrace::captureStackTrace(Options::unexpectedExceptionStackTraceLimit());
 }
 
 #endif // ENABLE(EXCEPTION_SCOPE_VERIFICATION)
index dda429d..181e3b7 100644 (file)
@@ -970,6 +970,19 @@ void VM::verifyExceptionCheckNeedIsSatisfied(unsigned recursionDepth, ExceptionE
             "        (ExceptionScope::m_recursionDepth was ", recursionDepth, ")\n"
             "\n");
 
+        StringPrintStream out;
+        std::unique_ptr<StackTrace> currentTrace = StackTrace::captureStackTrace(Options::unexpectedExceptionStackTraceLimit());
+
+        if (Options::dumpSimulatedThrows()) {
+            out.println("The simulated exception was thrown at:");
+            m_nativeStackTraceOfLastSimulatedThrow->dump(out, "    ");
+            out.println();
+        }
+        out.println("Unchecked exception detected at:");
+        currentTrace->dump(out, "    ");
+        out.println();
+
+        dataLog(out.toCString());
         RELEASE_ASSERT(!m_needExceptionCheck);
     }
 }
index 6bba992..2fddf18 100644 (file)
@@ -785,6 +785,7 @@ private:
     unsigned m_simulatedThrowPointRecursionDepth { 0 };
     mutable bool m_needExceptionCheck { false };
     std::unique_ptr<StackTrace> m_nativeStackTraceOfLastThrow;
+    std::unique_ptr<StackTrace> m_nativeStackTraceOfLastSimulatedThrow;
     ThreadIdentifier m_throwingThread;
 #endif
 
index 8fa862e..370a78a 100644 (file)
@@ -105,7 +105,7 @@ EncodedJSValue JSC_HOST_CALL protoFuncWeakMapSet(CallFrame* callFrame)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     auto* map = getWeakMap(callFrame, callFrame->thisValue());
-    ASSERT(!!scope.exception() == !map);
+    EXCEPTION_ASSERT(!!scope.exception() == !map);
     if (!map)
         return JSValue::encode(jsUndefined());
     JSValue key = callFrame->argument(0);
index 2134d98..71be655 100644 (file)
@@ -92,7 +92,7 @@ EncodedJSValue JSC_HOST_CALL protoFuncWeakSetAdd(CallFrame* callFrame)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     auto* set = getWeakSet(callFrame, callFrame->thisValue());
-    ASSERT(!!scope.exception() == !set);
+    EXCEPTION_ASSERT(!!scope.exception() == !set);
     if (!set)
         return JSValue::encode(jsUndefined());
     JSValue key = callFrame->argument(0);
index bbc0880..02f043c 100644 (file)
@@ -183,6 +183,7 @@ JSValue WebAssemblyModuleConstructor::createModule(ExecState* exec, JSValue buff
     Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, buffer);
     RETURN_IF_EXCEPTION(scope, { });
 
+    scope.release();
     return JSWebAssemblyModule::createStub(vm, exec, structure, Wasm::Module::validateSync(vm, WTFMove(source)));
 }
 
index 5c5bfc6..cb1fec1 100644 (file)
@@ -178,6 +178,7 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
         bool ignoreReadOnlyErrors = true;
         bool putResult = false;
         symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromString(&vm, String::fromUTF8(exp.field)), exportedValue, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
+        scope.assertNoException();
         RELEASE_ASSERT(putResult);
     }
 
index 3722458..e9a634a 100644 (file)
@@ -73,6 +73,7 @@ static void reject(ExecState* exec, CatchScope& catchScope, JSPromiseDeferred* p
     ASSERT(exception);
     catchScope.clearException();
     promise->reject(exec, exception->value());
+    CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, void());
 }
 
 static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
@@ -82,7 +83,7 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
     auto* globalObject = exec->lexicalGlobalObject();
 
     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
-    RETURN_IF_EXCEPTION(scope, { });
+    CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     Vector<Strong<JSCell>> dependencies;
     dependencies.append(Strong<JSCell>(vm, globalObject));
@@ -98,12 +99,13 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
                 auto scope = DECLARE_CATCH_SCOPE(vm);
                 ExecState* exec = globalObject->globalExec();
                 JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(result));
-                if (scope.exception()) {
+                if (UNLIKELY(scope.exception())) {
                     reject(exec, scope, promise);
                     return;
                 }
 
                 promise->resolve(exec, module);
+                CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
             });
         }));
     }
@@ -126,6 +128,7 @@ static void resolve(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAs
         result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("instance")), instance);
         promise->resolve(exec, result);
     }
+    CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
 }
 
 static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyModule* module, JSObject* importObject, Resolve resolveKind)
@@ -181,13 +184,14 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec->lexicalGlobalObject());
-    RETURN_IF_EXCEPTION(scope, { });
+    CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     JSValue importArgument = exec->argument(1);
     JSObject* importObject = importArgument.getObject();
     if (!importArgument.isUndefined() && !importObject) {
         promise->reject(exec, createTypeError(exec,
             ASCIILiteral("second argument to WebAssembly.instantiate must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)));
+        CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
         return JSValue::encode(promise->promise());
     }
 
index 7de7fa6..83f3e7c 100644 (file)
@@ -1,3 +1,26 @@
+2017-09-10  Mark Lam  <mark.lam@apple.com>
+
+        Fix all ExceptionScope verification failures in JavaScriptCore.
+        https://bugs.webkit.org/show_bug.cgi?id=176662
+        <rdar://problem/34352085>
+
+        Reviewed by Filip Pizlo.
+
+        No new tests because this is covered by existing tests with the JSC_validateExceptionChecks=true enabled.
+
+        * bindings/js/JSCustomElementInterface.cpp:
+        (WebCore::JSCustomElementInterface::tryToConstructCustomElement):
+        * bindings/js/JSCustomElementRegistryCustom.cpp:
+        (WebCore::whenDefinedPromise):
+        * bindings/js/JSDOMConvertRecord.h:
+        * bindings/js/JSDOMMapLike.cpp:
+        (WebCore::createBackingMap):
+        * bindings/js/JSDOMPromiseDeferred.cpp:
+        (WebCore::DeferredPromise::callFunction):
+        (WebCore::DeferredPromise::reject):
+        * bindings/js/JSDOMPromiseDeferred.h:
+        (WebCore::callPromiseFunction):
+
 2017-09-10  Frederic Wang  <fwang@igalia.coml>
 
         Make RenderLayerCompositor always use isRootLayer()
index fcd113b..a74fa79 100644 (file)
@@ -104,7 +104,7 @@ RefPtr<Element> JSCustomElementInterface::tryToConstructCustomElement(Document&
     ASSERT(&document == scriptExecutionContext());
     auto& state = *document.execState();
     auto element = constructCustomElementSynchronously(document, vm, state, m_constructor.get(), localName);
-    ASSERT(!!scope.exception() == !element);
+    EXCEPTION_ASSERT(!!scope.exception() == !element);
     if (!element) {
         auto* exception = scope.exception();
         scope.clearException();
index 1e82a13..fa6958b 100644 (file)
@@ -186,7 +186,7 @@ static JSValue whenDefinedPromise(ExecState& state, JSDOMGlobalObject& globalObj
     RETURN_IF_EXCEPTION(scope, JSValue());
 
     if (!validateCustomElementNameAndThrowIfNeeded(state, localName)) {
-        ASSERT(scope.exception());
+        EXCEPTION_ASSERT(scope.exception());
         return jsUndefined();
     }
 
index c2b2e25..e1b068a 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
@@ -105,6 +105,7 @@ template<typename K, typename V> struct Converter<IDLRecord<K, V>> : DefaultConv
             if (didGetDescriptor && descriptor.enumerable()) {
                 // 1. Let typedKey be key converted to an IDL value of type K.
                 auto typedKey = Detail::IdentifierConverter<K>::convert(state, key);
+                RETURN_IF_EXCEPTION(scope, { });
 
                 // 2. Let value be ? Get(O, key).
                 auto subValue = object->get(&state, key);
index 0b65975..b7e9f2b 100644 (file)
@@ -27,6 +27,7 @@
 #include "JSDOMMapLike.h"
 
 #include "WebCoreJSClientData.h"
+#include <runtime/CatchScope.h>
 
 namespace WebCore {
 
@@ -45,9 +46,11 @@ void initializeBackingMap(JSC::VM& vm, JSC::JSObject& mapLike, JSC::JSMap& backi
 JSC::JSMap& createBackingMap(JSC::ExecState& state, JSC::JSGlobalObject& globalObject, JSC::JSObject& mapLike)
 {
     auto& vm = state.vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
 
     ASSERT(mapLike.get(&state, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().backingMapPrivateName()).isUndefined());
     auto backingMap = JSC::JSMap::create(&state, vm, globalObject.mapStructure());
+    scope.releaseAssertNoException();
     mapLike.putDirect(vm, static_cast<JSVMClientData*>(vm.clientData)->builtinNames().backingMapPrivateName(), backingMap, JSC::DontEnum);
     return *backingMap;
 }
index 4189644..ff2f057 100644 (file)
@@ -63,7 +63,7 @@ void DeferredPromise::callFunction(ExecState& exec, JSValue function, JSValue re
 
     // DeferredPromise should only be used by internal implementations that are well behaved.
     // In practice, the only exception we should ever see here is the TerminatedExecutionException.
-    ASSERT_UNUSED(scope, !scope.exception() || isTerminatedExecutionException(vm, scope.exception()));
+    EXCEPTION_ASSERT_UNUSED(scope, !scope.exception() || isTerminatedExecutionException(vm, scope.exception()));
 
     if (m_mode == Mode::ClearPromiseOnResolve)
         clear();
@@ -106,7 +106,7 @@ void DeferredPromise::reject(Exception exception)
     if (exception.code() == ExistingExceptionError) {
         auto scope = DECLARE_CATCH_SCOPE(state.vm());
 
-        ASSERT(scope.exception());
+        EXCEPTION_ASSERT(scope.exception());
 
         auto error = scope.exception()->value();
         scope.clearException();
@@ -138,7 +138,7 @@ void DeferredPromise::reject(ExceptionCode ec, const String& message)
     if (ec == ExistingExceptionError) {
         auto scope = DECLARE_CATCH_SCOPE(state.vm());
 
-        ASSERT(scope.exception());
+        EXCEPTION_ASSERT(scope.exception());
 
         auto error = scope.exception()->value();
         scope.clearException();
index fb6cdf5..4236f81 100644 (file)
@@ -274,7 +274,7 @@ inline JSC::JSValue callPromiseFunction(JSC::ExecState& state)
     promiseFunction(state, DeferredPromise::create(globalObject, *promiseDeferred));
 
     rejectPromiseWithExceptionIfAny(state, globalObject, *promiseDeferred);
-    ASSERT_UNUSED(scope, !scope.exception());
+    EXCEPTION_ASSERT_UNUSED(scope, !scope.exception());
     return promiseDeferred->promise();
 }
 
@@ -294,7 +294,7 @@ inline JSC::JSValue callPromiseFunction(JSC::ExecState& state, PromiseFunctor fu
     functor(state, DeferredPromise::create(globalObject, *promiseDeferred));
 
     rejectPromiseWithExceptionIfAny(state, globalObject, *promiseDeferred);
-    ASSERT_UNUSED(scope, !scope.exception());
+    EXCEPTION_ASSERT_UNUSED(scope, !scope.exception());
     return promiseDeferred->promise();
 }