Changeset 167142 in webkit
- Timestamp:
- Apr 11, 2014 1:24:56 PM (10 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r167139 r167142 1 2014-04-11 Mark Lam <mark.lam@apple.com> 2 3 JSMainThreadExecState::call() should clear exceptions before returning. 4 <https://webkit.org/b/131530> 5 6 Reviewed by Geoffrey Garen. 7 8 * fast/dom/regress-131530-expected.txt: Added. 9 * fast/dom/regress-131530.html: Added. 10 1 11 2014-04-11 Carlos Alberto Lopez Perez <clopez@igalia.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r167137 r167142 1 2014-04-11 Mark Lam <mark.lam@apple.com> 2 3 JSMainThreadExecState::call() should clear exceptions before returning. 4 <https://webkit.org/b/131530> 5 6 Reviewed by Geoffrey Garen. 7 8 Added a version of JSC::call() that return any uncaught exception instead 9 of leaving it pending in the VM. 10 11 As part of this change, I updated various parts of the code base to use the 12 new API as needed. 13 14 * bindings/ScriptFunctionCall.cpp: 15 (Deprecated::ScriptFunctionCall::call): 16 - ScriptFunctionCall::call() is only used by the inspector to inject scripts. 17 The injected scripts that will include Inspector scripts that should catch 18 and handle any exceptions that were thrown. We should not be seeing any 19 exceptions returned from this call. However, we do have checks for 20 exceptions in case there are bugs in the Inspector scripts which allowed 21 the exception to leak through. Hence, it is proper to clear the exception 22 here, and only record the fact that an exception was seen (if present). 23 24 * bindings/ScriptFunctionCall.h: 25 * inspector/InspectorEnvironment.h: 26 * runtime/CallData.cpp: 27 (JSC::call): 28 * runtime/CallData.h: 29 1 30 2014-04-11 Oliver Hunt <oliver@apple.com> 2 31 -
trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp
r163844 r167142 134 134 135 135 JSValue result; 136 JSValue exception; 136 137 if (m_callHandler) 137 result = m_callHandler(m_exec, function, callType, callData, thisObject, m_arguments );138 result = m_callHandler(m_exec, function, callType, callData, thisObject, m_arguments, &exception); 138 139 else 139 result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments );140 result = JSC::call(m_exec, function, callType, callData, thisObject, m_arguments, &exception); 140 141 141 if ( m_exec->hadException()) {142 if (exception) { 142 143 hadException = true; 143 144 return Deprecated::ScriptValue(); -
trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.h
r160457 r167142 72 72 class JS_EXPORT_PRIVATE ScriptFunctionCall : public ScriptCallArgumentHandler { 73 73 public: 74 typedef JSC::JSValue (*ScriptFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args );74 typedef JSC::JSValue (*ScriptFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception); 75 75 ScriptFunctionCall(const ScriptObject& thisObject, const String& name, ScriptFunctionCallHandler handler = nullptr); 76 76 ScriptValue call(bool& hadException); -
trunk/Source/JavaScriptCore/inspector/InspectorEnvironment.h
r163139 r167142 35 35 namespace Inspector { 36 36 37 typedef JSC::JSValue (*InspectorFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args );37 typedef JSC::JSValue (*InspectorFunctionCallHandler)(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception); 38 38 typedef JSC::JSValue (*InspectorEvaluateHandler)(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, JSC::JSValue* exception); 39 39 -
trunk/Source/JavaScriptCore/runtime/CallData.cpp
r163844 r167142 40 40 } 41 41 42 JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args, JSValue* exception) 43 { 44 JSValue result = call(exec, functionObject, callType, callData, thisValue, args); 45 if (exec->hadException()) { 46 if (exception) 47 *exception = exec->exception(); 48 exec->clearException(); 49 return jsUndefined(); 50 } 51 RELEASE_ASSERT(result); 52 return result; 53 } 54 42 55 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/CallData.h
r165676 r167142 59 59 60 60 JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); 61 JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&, JSValue* exception); 61 62 62 63 } // namespace JSC -
trunk/Source/WebCore/ChangeLog
r167140 r167142 1 2014-04-11 Mark Lam <mark.lam@apple.com> 2 3 JSMainThreadExecState::call() should clear exceptions before returning. 4 <https://webkit.org/b/131530> 5 6 Reviewed by Geoffrey Garen. 7 8 Test: fast/dom/regress-131530.html 9 10 Previously, JSMainThreadExecState::call() did not clear any pending 11 exceptions in the VM before returning. On returning, the 12 JSMainThreadExecState destructor may re-enter the VM to notify 13 MutationObservers. This may result in a crash because the VM expects 14 exceptions to be cleared at entry. 15 16 We now change JSMainThreadExecState::call() to return the exception 17 (if present) via an argument, and clear it from the VM before returning. 18 19 As part of this change, I updated various parts of the code base to use the 20 new API as needed. 21 22 * bindings/js/JSCallbackData.cpp: 23 (WebCore::JSCallbackData::invokeCallback): 24 * bindings/js/JSCustomXPathNSResolver.cpp: 25 (WebCore::JSCustomXPathNSResolver::lookupNamespaceURI): 26 * bindings/js/JSDOMGlobalObjectTask.cpp: 27 - Assert that there's no unhandled exception after the Microtask returns. 28 See comment for WebCore::JSMainThreadExecState::runTask below for more 29 details. 30 31 * bindings/js/JSErrorHandler.cpp: 32 (WebCore::JSErrorHandler::handleEvent): 33 * bindings/js/JSEventListener.cpp: 34 (WebCore::JSEventListener::handleEvent): 35 * bindings/js/JSHTMLDocumentCustom.cpp: 36 (WebCore::JSHTMLDocument::open): 37 - Document.open() cannot be the first function on the JS stack. Hence, 38 there is no need to use JSMainThreadExecState to call into the VM, as 39 this is only needed to catch the event of returning from the first 40 function for the purpose of notifying MutationObservers. Change to 41 call JSC::call() directly. 42 43 * bindings/js/JSMainThreadExecState.cpp: 44 (WebCore::functionCallHandlerFromAnyThread): 45 * bindings/js/JSMainThreadExecState.h: 46 (WebCore::JSMainThreadExecState::call): 47 (WebCore::JSMainThreadExecState::evaluate): 48 - Remove the explicitly acquisition of the JSLock here because we now 49 acquire the JSLock as part of the JSMainThreadExecState instance. 50 (WebCore::JSMainThreadExecState::runTask): 51 - Added an assert to verify that the task does not return with an 52 unhandled exception. Currently, the only Microtask in use is for the 53 Promise implementation, which will eat the exception before returning. 54 This assertion is added here to verify that this contract does not 55 inadvertantly change in the future. 56 (WebCore::JSMainThreadExecState::JSMainThreadExecState): 57 - Now acquires the JSLock as well since by definition, we're only 58 instantiating the JSMainThreadExecState because we're about to enter 59 the VM. 60 61 * bindings/js/JSMutationCallback.cpp: 62 (WebCore::JSMutationCallback::call): 63 * bindings/js/JSNodeFilterCondition.cpp: 64 (WebCore::JSNodeFilterCondition::acceptNode): 65 - acceptNode() is only used in the TreeWalker and NodeIterator APIs which 66 cannot be the first function on the JS stack. Hence, we should call 67 JSC::call() directly instead of going through JSMainThreadExecState. 68 69 * bindings/js/ScheduledAction.cpp: 70 (WebCore::ScheduledAction::executeFunctionInContext): 71 * bindings/objc/WebScriptObject.mm: 72 (WebCore::addExceptionToConsole): 73 (-[WebScriptObject callWebScriptMethod:withArguments:]): 74 1 75 2014-04-11 Brian J. Burg <burg@cs.washington.edu> 2 76 -
trunk/Source/WebCore/bindings/js/JSCallbackData.cpp
r165676 r167142 74 74 InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); 75 75 76 JSValue exception; 76 77 JSValue result = context->isDocument() 77 ? JSMainThreadExecState::call(exec, function, callType, callData, thisValue, args )78 : JSC::call(exec, function, callType, callData, thisValue, args );78 ? JSMainThreadExecState::call(exec, function, callType, callData, thisValue, args, &exception) 79 : JSC::call(exec, function, callType, callData, thisValue, args, &exception); 79 80 80 81 InspectorInstrumentation::didCallFunction(cookie, context); 81 82 82 if (ex ec->hadException()) {83 report CurrentException(exec);83 if (exception) { 84 reportException(exec, exception); 84 85 if (raisedException) 85 86 *raisedException = true; -
trunk/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
r165676 r167142 93 93 args.append(jsStringWithCache(exec, prefix)); 94 94 95 JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args); 95 JSValue exception; 96 JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args, &exception); 96 97 97 98 String result; 98 if (ex ec->hadException())99 report CurrentException(exec);99 if (exception) 100 reportException(exec, exception); 100 101 else { 101 102 if (!retval.isUndefinedOrNull()) -
trunk/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
r166943 r167142 65 65 else 66 66 m_task->run(exec); 67 ASSERT(!exec->hadException()); 67 68 } 68 69 -
trunk/Source/WebCore/bindings/js/JSErrorHandler.cpp
r164184 r167142 99 99 VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject); 100 100 101 JSValue exception; 101 102 JSValue returnValue = scriptExecutionContext->isDocument() 102 ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, globalObject, args )103 : JSC::call(exec, jsFunction, callType, callData, globalObject, args );103 ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, globalObject, args, &exception) 104 : JSC::call(exec, jsFunction, callType, callData, globalObject, args, &exception); 104 105 105 106 globalObject->setCurrentEvent(savedEvent); 106 107 107 if (ex ec->hadException())108 report CurrentException(exec);108 if (exception) 109 reportException(exec, exception); 109 110 else { 110 111 if (returnValue.isTrue()) -
trunk/Source/WebCore/bindings/js/JSEventListener.cpp
r164735 r167142 123 123 124 124 JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction; 125 JSValue exception; 125 126 JSValue retval = scriptExecutionContext->isDocument() 126 ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args )127 : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args );127 ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args, &exception) 128 : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args, &exception); 128 129 129 130 InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext); … … 137 138 } 138 139 139 if (ex ec->hadException()) {140 if (exception) { 140 141 event->target()->uncaughtExceptionInEventHandler(); 141 report CurrentException(exec);142 reportException(exec, exception); 142 143 } else { 143 144 if (!retval.isUndefinedOrNull() && event->isBeforeUnloadEvent()) -
trunk/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
r165676 r167142 114 114 if (callType == CallTypeNone) 115 115 return throwTypeError(exec); 116 return JS MainThreadExecState::call(exec, function, callType, callData, wrapper, ArgList(exec));116 return JSC::call(exec, function, callType, callData, wrapper, ArgList(exec)); 117 117 } 118 118 } -
trunk/Source/WebCore/bindings/js/JSMainThreadExecState.cpp
r161563 r167142 47 47 } 48 48 49 JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args )49 JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception) 50 50 { 51 51 if (isMainThread()) 52 return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args );53 return JSC::call(exec, functionObject, callType, callData, thisValue, args );52 return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args, exception); 53 return JSC::call(exec, functionObject, callType, callData, thisValue, args, exception); 54 54 } 55 55 -
trunk/Source/WebCore/bindings/js/JSMainThreadExecState.h
r166943 r167142 51 51 }; 52 52 53 static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args )53 static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception) 54 54 { 55 55 JSMainThreadExecState currentState(exec); 56 return JSC::call(exec, functionObject, callType, callData, thisValue, args );56 return JSC::call(exec, functionObject, callType, callData, thisValue, args, exception); 57 57 }; 58 58 … … 60 60 { 61 61 JSMainThreadExecState currentState(exec); 62 JSC::JSLockHolder lock(exec);63 62 return JSC::evaluate(exec, source, thisValue, exception); 64 63 }; … … 75 74 explicit JSMainThreadExecState(JSC::ExecState* exec) 76 75 : m_previousState(s_mainThreadState) 76 , m_lock(exec) 77 77 { 78 78 ASSERT(isMainThread()); … … 83 83 { 84 84 ASSERT(isMainThread()); 85 ASSERT(!s_mainThreadState->hadException()); 85 86 86 87 bool didExitJavaScript = s_mainThreadState && !m_previousState; … … 94 95 static JSC::ExecState* s_mainThreadState; 95 96 JSC::ExecState* m_previousState; 97 JSC::JSLockHolder m_lock; 96 98 97 99 static void didLeaveScriptContext(); … … 120 122 }; 121 123 122 JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args);124 JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception); 123 125 JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, JSC::JSValue* exception); 124 126 -
trunk/Source/WebCore/bindings/js/JSMutationCallback.cpp
r163139 r167142 88 88 InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); 89 89 90 JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args); 90 JSValue exception; 91 JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args, &exception); 91 92 92 93 InspectorInstrumentation::didCallFunction(cookie, context); 93 94 94 if (ex ec->hadException())95 report CurrentException(exec);95 if (exception) 96 reportException(exec, exception); 96 97 } 97 98 -
trunk/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
r163225 r167142 68 68 return NodeFilter::FILTER_REJECT; 69 69 70 JSValue result = JS MainThreadExecState::call(exec, filter, callType, callData, m_filter.get(), args);70 JSValue result = JSC::call(exec, filter, callType, callData, m_filter.get(), args); 71 71 if (exec->hadException()) 72 72 return NodeFilter::FILTER_REJECT; -
trunk/Source/WebCore/bindings/js/ScheduledAction.cpp
r164182 r167142 100 100 InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData); 101 101 102 JSValue exception; 102 103 if (context->isDocument()) 103 JSMainThreadExecState::call(exec, m_function.get(), callType, callData, thisValue, args );104 JSMainThreadExecState::call(exec, m_function.get(), callType, callData, thisValue, args, &exception); 104 105 else 105 JSC::call(exec, m_function.get(), callType, callData, thisValue, args );106 JSC::call(exec, m_function.get(), callType, callData, thisValue, args, &exception); 106 107 107 108 InspectorInstrumentation::didCallFunction(cookie, context); 108 109 109 if (ex ec->hadException())110 report CurrentException(exec);110 if (exception) 111 reportException(exec, exception); 111 112 } 112 113 -
trunk/Source/WebCore/bindings/objc/WebScriptObject.mm
r165848 r167142 121 121 } 122 122 123 static void addExceptionToConsole(ExecState* exec, JSC::JSValue& exception) 124 { 125 JSDOMWindow* window = asJSDOMWindow(exec->vmEntryGlobalObject()); 126 if (!window || !exception) 127 return; 128 reportException(exec, exception); 129 } 130 123 131 static void addExceptionToConsole(ExecState* exec) 124 132 { 125 JSDOMWindow* window = asJSDOMWindow(exec->vmEntryGlobalObject()); 126 if (!window || !exec->hadException()) 127 return; 128 reportCurrentException(exec); 133 JSC::JSValue exception = exec->exception(); 134 exec->clearException(); 135 addExceptionToConsole(exec, exception); 129 136 } 130 137 … … 335 342 return nil; 336 343 337 JSC::JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, [self _imp], argList); 338 339 if (exec->hadException()) { 340 addExceptionToConsole(exec); 344 JSC::JSValue exception; 345 JSC::JSValue result = JSMainThreadExecState::call(exec, function, callType, callData, [self _imp], argList, &exception); 346 347 if (exception) { 348 addExceptionToConsole(exec, exception); 341 349 result = jsUndefined(); 342 exec->clearException();343 350 } 344 351
Note: See TracChangeset
for help on using the changeset viewer.