Commit 15b0869d authored by jbroman's avatar jbroman Committed by Commit bot

Implement v8::ValueSerializer::Delegate to throw DOMException for DataCloneError.

This allows V8 to indirectly throw a DOMException, as is required to handle
certain kinds of errors encountered during serialization.

BUG=chromium:148757

Review-Url: https://codereview.chromium.org/2316763002
Cr-Commit-Position: refs/heads/master@{#417184}
parent 09d8cdfc
...@@ -130,6 +130,8 @@ public: ...@@ -130,6 +130,8 @@ public:
const char* propertyName() const { return m_propertyName; } const char* propertyName() const { return m_propertyName; }
const char* interfaceName() const { return m_interfaceName; } const char* interfaceName() const { return m_interfaceName; }
String addExceptionContext(const String&) const;
protected: protected:
// An ExceptionCode for the case that an exception is rethrown. In that // An ExceptionCode for the case that an exception is rethrown. In that
// case, we cannot determine an exception code. // case, we cannot determine an exception code.
...@@ -138,8 +140,6 @@ protected: ...@@ -138,8 +140,6 @@ protected:
void setException(ExceptionCode, const String&, v8::Local<v8::Value>); void setException(ExceptionCode, const String&, v8::Local<v8::Value>);
private: private:
String addExceptionContext(const String&) const;
ExceptionCode m_code; ExceptionCode m_code;
ContextType m_context; ContextType m_context;
String m_message; String m_message;
......
...@@ -7,13 +7,14 @@ ...@@ -7,13 +7,14 @@
#include "bindings/core/v8/ToV8.h" #include "bindings/core/v8/ToV8.h"
#include "core/dom/DOMArrayBufferBase.h" #include "core/dom/DOMArrayBufferBase.h"
#include "platform/RuntimeEnabledFeatures.h" #include "platform/RuntimeEnabledFeatures.h"
#include "wtf/AutoReset.h"
namespace blink { namespace blink {
V8ScriptValueSerializer::V8ScriptValueSerializer(RefPtr<ScriptState> scriptState) V8ScriptValueSerializer::V8ScriptValueSerializer(RefPtr<ScriptState> scriptState)
: m_scriptState(std::move(scriptState)) : m_scriptState(std::move(scriptState))
, m_serializedScriptValue(SerializedScriptValue::create()) , m_serializedScriptValue(SerializedScriptValue::create())
, m_serializer(m_scriptState->isolate()) , m_serializer(m_scriptState->isolate(), this)
{ {
DCHECK(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled()); DCHECK(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled());
} }
...@@ -25,6 +26,7 @@ RefPtr<SerializedScriptValue> V8ScriptValueSerializer::serialize(v8::Local<v8::V ...@@ -25,6 +26,7 @@ RefPtr<SerializedScriptValue> V8ScriptValueSerializer::serialize(v8::Local<v8::V
m_serializeInvoked = true; m_serializeInvoked = true;
#endif #endif
DCHECK(m_serializedScriptValue); DCHECK(m_serializedScriptValue);
AutoReset<const ExceptionState*> reset(&m_exceptionState, &exceptionState);
ScriptState::Scope scope(m_scriptState.get()); ScriptState::Scope scope(m_scriptState.get());
// Prepare to transfer the provided transferables. // Prepare to transfer the provided transferables.
...@@ -42,11 +44,7 @@ RefPtr<SerializedScriptValue> V8ScriptValueSerializer::serialize(v8::Local<v8::V ...@@ -42,11 +44,7 @@ RefPtr<SerializedScriptValue> V8ScriptValueSerializer::serialize(v8::Local<v8::V
exceptionState.rethrowV8Exception(tryCatch.Exception()); exceptionState.rethrowV8Exception(tryCatch.Exception());
return nullptr; return nullptr;
} }
if (!wroteValue) { DCHECK(wroteValue);
DCHECK(!tryCatch.HasCaught());
exceptionState.throwDOMException(DataCloneError, "An object could not be cloned.");
return nullptr;
}
// Finalize the results. // Finalize the results.
std::vector<uint8_t> buffer = m_serializer.ReleaseBuffer(); std::vector<uint8_t> buffer = m_serializer.ReleaseBuffer();
...@@ -85,4 +83,14 @@ void V8ScriptValueSerializer::transfer(Transferables* transferables, ExceptionSt ...@@ -85,4 +83,14 @@ void V8ScriptValueSerializer::transfer(Transferables* transferables, ExceptionSt
} }
} }
void V8ScriptValueSerializer::ThrowDataCloneError(v8::Local<v8::String> v8Message)
{
DCHECK(m_exceptionState);
String message = m_exceptionState->addExceptionContext(
v8StringToWebCoreString<String>(v8Message, DoNotExternalize));
v8::Local<v8::Value> exception = V8ThrowException::createDOMException(
m_scriptState->isolate(), DataCloneError, message);
V8ThrowException::throwException(m_scriptState->isolate(), exception);
}
} // namespace blink } // namespace blink
...@@ -25,7 +25,7 @@ class Transferables; ...@@ -25,7 +25,7 @@ class Transferables;
// //
// A serializer cannot be used multiple times; it is expected that its serialize // A serializer cannot be used multiple times; it is expected that its serialize
// method will be invoked exactly once. // method will be invoked exactly once.
class V8ScriptValueSerializer { class GC_PLUGIN_IGNORE("https://crbug.com/644725") V8ScriptValueSerializer : public v8::ValueSerializer::Delegate {
STACK_ALLOCATED(); STACK_ALLOCATED();
WTF_MAKE_NONCOPYABLE(V8ScriptValueSerializer); WTF_MAKE_NONCOPYABLE(V8ScriptValueSerializer);
public: public:
...@@ -35,9 +35,13 @@ public: ...@@ -35,9 +35,13 @@ public:
private: private:
void transfer(Transferables*, ExceptionState&); void transfer(Transferables*, ExceptionState&);
// v8::ValueSerializer::Delegate
void ThrowDataCloneError(v8::Local<v8::String> message) override;
RefPtr<ScriptState> m_scriptState; RefPtr<ScriptState> m_scriptState;
RefPtr<SerializedScriptValue> m_serializedScriptValue; RefPtr<SerializedScriptValue> m_serializedScriptValue;
v8::ValueSerializer m_serializer; v8::ValueSerializer m_serializer;
const ExceptionState* m_exceptionState = nullptr;
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
bool m_serializeInvoked = false; bool m_serializeInvoked = false;
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment