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):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jsc.cpp

    r185346 r185608  
    909909        exec->vm(), Identifier::fromString(globalObject->globalExec(), "arguments"), array);
    910910
    911     Exception* exception;
     911    NakedPtr<Exception> exception;
    912912    StopWatch stopWatch;
    913913    stopWatch.start();
     
    932932    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    933933   
    934     Exception* evaluationException;
     934    NakedPtr<Exception> evaluationException;
    935935    JSValue result = evaluate(globalObject->globalExec(), jscSource(script.data(), fileName), JSValue(), evaluationException);
    936936    if (evaluationException)
     
    12951295        vm.startSampling();
    12961296
    1297         Exception* evaluationException;
     1297        NakedPtr<Exception> evaluationException;
    12981298        JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
    12991299        success = success && !evaluationException;
     
    13591359       
    13601360       
    1361         Exception* evaluationException;
     1361        NakedPtr<Exception> evaluationException;
    13621362        JSValue returnValue = evaluate(globalObject->globalExec(), makeSource(source, interpreterName), JSValue(), evaluationException);
    13631363#else
     
    13751375        line.append('\0');
    13761376
    1377         Exception* evaluationException;
     1377        NakedPtr<Exception> evaluationException;
    13781378        JSValue returnValue = evaluate(globalObject->globalExec(), jscSource(line.data(), interpreterName), JSValue(), evaluationException);
    13791379#endif
Note: See TracChangeset for help on using the changeset viewer.