Ignore:
Timestamp:
Jun 16, 2015, 1:51:04 PM (10 years ago)
Author:
[email protected]
Message:

Use NakedPtr<Exception>& to return exception results.
https://bugs.webkit.org/show_bug.cgi?id=145870

Reviewed by Anders Carlsson and Filip Pizlo.

Source/JavaScriptCore:

Before r185259, calls into the VM takes a JSValue* exception result argument for
returning any uncaught exception that may have been thrown while executing JS code.
As a result, clients of the VM functions will declare a local JSValue exception
result which is automatically initialized to a null value (i.e. the empty value,
not the JS null value).

With r185259, the VM functions were changed to take an Exception*& exception result
instead, and the VM functions are responsible for initializing the exception result
to null if no exception is thrown.

This introduces 2 issues:

  1. the VM functions are vulnerable to modifications that may add early returns before the exception result is nullified. This can result in the exception result being used without initialization.
  1. Previously, a client could technically use the same exception result for more than one calls into the VM functions. If an earlier call sets it to a thrown value, the thrown value will stick unless a subsequent call throws a different exception.

With the new Exception*& exception result, the VM functions will always clear
the exception result before proceeding. As a result, the client's exception
result will be null after the second call even though the first call saw an
exception thrown. This is a change in the expected behavior.

To fix these issues, we'll introduce a NakedPtr smart pointer whose sole purpose
is to guarantee that the pointer is initialized. The VM functions will now take
a NakedPtr<Exception>& instead of the Exception*&. This ensures that the
exception result is initialized.

The VM functions be also reverted to only set the exception result if a new
exception is thrown.

  • API/JSBase.cpp:

(JSEvaluateScript):

  • API/JSScriptRef.cpp:
  • bindings/ScriptFunctionCall.cpp:

(Deprecated::ScriptFunctionCall::call):

  • bindings/ScriptFunctionCall.h:
  • debugger/Debugger.cpp:

(JSC::Debugger::hasBreakpoint):

  • debugger/Debugger.h:
  • debugger/DebuggerCallFrame.cpp:

(JSC::DebuggerCallFrame::thisValue):
(JSC::DebuggerCallFrame::evaluate):

  • debugger/DebuggerCallFrame.h:

(JSC::DebuggerCallFrame::isValid):

  • inspector/InjectedScriptManager.cpp:

(Inspector::InjectedScriptManager::createInjectedScript):

  • inspector/InspectorEnvironment.h:
  • inspector/JSJavaScriptCallFrame.cpp:

(Inspector::JSJavaScriptCallFrame::evaluate):

  • inspector/JavaScriptCallFrame.h:

(Inspector::JavaScriptCallFrame::vmEntryGlobalObject):
(Inspector::JavaScriptCallFrame::thisValue):
(Inspector::JavaScriptCallFrame::evaluate):

  • inspector/ScriptDebugServer.cpp:

(Inspector::ScriptDebugServer::evaluateBreakpointAction):

  • jsc.cpp:

(functionRun):
(functionLoad):
(runWithScripts):
(runInteractive):

  • runtime/CallData.cpp:

(JSC::call):

  • runtime/CallData.h:
  • runtime/Completion.cpp:

(JSC::checkSyntax):
(JSC::evaluate):

  • runtime/Completion.h:

(JSC::evaluate):

Source/WebCore:

No new WebCore tests because this functionality is already covered by existing tests.
API tests added for WTF::NakedPtr.

  • bindings/js/JSCallbackData.cpp:

(WebCore::JSCallbackData::invokeCallback):

  • bindings/js/JSCustomXPathNSResolver.cpp:

(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):

  • bindings/js/JSErrorHandler.cpp:

(WebCore::JSErrorHandler::handleEvent):

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/JSMainThreadExecState.cpp:

(WebCore::JSMainThreadExecState::didLeaveScriptContext):
(WebCore::functionCallHandlerFromAnyThread):
(WebCore::evaluateHandlerFromAnyThread):

  • bindings/js/JSMainThreadExecState.h:

(WebCore::JSMainThreadExecState::currentState):
(WebCore::JSMainThreadExecState::call):
(WebCore::JSMainThreadExecState::evaluate):

  • bindings/js/JSMutationCallback.cpp:

(WebCore::JSMutationCallback::call):

  • bindings/js/ScheduledAction.cpp:

(WebCore::ScheduledAction::executeFunctionInContext):

  • bindings/js/ScriptController.cpp:

(WebCore::ScriptController::evaluateInWorld):

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::evaluate):
(WebCore::WorkerScriptController::setException):

  • bindings/js/WorkerScriptController.h:

(WebCore::WorkerScriptController::workerGlobalScopeWrapper):

  • bindings/objc/WebScriptObject.mm:

(-[WebScriptObject callWebScriptMethod:withArguments:]):

  • workers/WorkerGlobalScope.cpp:

(WebCore::WorkerGlobalScope::importScripts):

Source/WTF:

Introducing the NakedPtr class.

  • WTF.xcodeproj/project.pbxproj:
  • wtf/NakedPtr.h: Added.

(WTF::NakedPtr::NakedPtr):
(WTF::NakedPtr::get):
(WTF::NakedPtr::clear):
(WTF::NakedPtr::operator*):
(WTF::NakedPtr::operator->):
(WTF::NakedPtr::operator T*):
(WTF::NakedPtr::operator!):
(WTF::NakedPtr::operator bool):
(WTF::=):
(WTF::NakedPtr<T>::swap):
(WTF::swap):

Tools:

  • TestWebKitAPI/CMakeLists.txt:
  • TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj:
  • TestWebKitAPI/TestWebKitAPI.vcxproj/TestWebKitAPI.vcxproj.filters:
  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/WTF/NakedPtr.cpp: Added.

(TestWebKitAPI::TEST):
(TestWebKitAPI::nakedPtrFoo):

Location:
trunk/Source/JavaScriptCore/bindings
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.cpp

    r185259 r185608  
    134134
    135135    JSValue result;
    136     Exception* exception;
     136    NakedPtr<Exception> exception;
    137137    if (m_callHandler)
    138138        result = m_callHandler(m_exec, function, callType, callData, thisObject, m_arguments, exception);
  • trunk/Source/JavaScriptCore/bindings/ScriptFunctionCall.h

    r185259 r185608  
    7272class JS_EXPORT_PRIVATE ScriptFunctionCall : public ScriptCallArgumentHandler {
    7373public:
    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::Exception*& exception);
     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, NakedPtr<JSC::Exception>&);
    7575    ScriptFunctionCall(const ScriptObject& thisObject, const String& name, ScriptFunctionCallHandler handler = nullptr);
    7676    ScriptValue call(bool& hadException);
Note: See TracChangeset for help on using the changeset viewer.