Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(397)

Unified Diff: Source/bindings/v8/SerializedScriptValue.cpp

Issue 114363002: Structured cloning: improve DataCloneError reporting. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebased + reset V8TestInterfaceConstructor.cpp result Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/bindings/v8/SerializedScriptValue.h ('k') | Source/bindings/v8/V8Utilities.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/bindings/v8/SerializedScriptValue.cpp
diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp
index 72f3560274859d1976525d08925f14eb1469278c..28bf94f5bb0b32d521a3956ab3c8ae928f114a89 100644
--- a/Source/bindings/v8/SerializedScriptValue.cpp
+++ b/Source/bindings/v8/SerializedScriptValue.cpp
@@ -37,6 +37,7 @@
#include "V8FileList.h"
#include "V8ImageData.h"
#include "V8MessagePort.h"
+#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/ScriptScope.h"
#include "bindings/v8/ScriptState.h"
#include "bindings/v8/V8Binding.h"
@@ -703,9 +704,7 @@ public:
Success,
InputError,
DataCloneError,
- InvalidStateError,
- JSException,
- JSFailure
+ JSException
};
Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate)
@@ -742,6 +741,8 @@ public:
return m_status;
}
+ String errorMessage() { return m_errorMessage; }
+
// Functions used by serialization states.
StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next);
@@ -752,12 +753,7 @@ public:
StateBase* checkException(StateBase* state)
{
- return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0;
- }
-
- StateBase* reportFailure(StateBase* state)
- {
- return handleError(JSFailure, state);
+ return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0;
}
StateBase* writeObject(uint32_t numProperties, StateBase* state)
@@ -860,7 +856,7 @@ private:
if (StateBase* newState = serializer.checkException(this))
return newState;
if (propertyName.IsEmpty())
- return serializer.reportFailure(this);
+ return serializer.handleError(InputError, "Empty property names cannot be cloned.", this);
bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>());
if (StateBase* newState = serializer.checkException(this))
return newState;
@@ -919,7 +915,7 @@ private:
if (StateBase* newState = serializer.checkException(this))
return newState;
if (m_propertyNames.IsEmpty())
- return serializer.reportFailure(this);
+ return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState());
}
return serializeProperties(false, serializer);
}
@@ -989,7 +985,7 @@ private:
{
ASSERT(state);
++m_depth;
- return checkComposite(state) ? state : handleError(InputError, state);
+ return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state);
}
StateBase* pop(StateBase* state)
@@ -1001,10 +997,11 @@ private:
return next;
}
- StateBase* handleError(Status errorStatus, StateBase* state)
+ StateBase* handleError(Status errorStatus, const String& message, StateBase* state)
{
ASSERT(errorStatus != Success);
m_status = errorStatus;
+ m_errorMessage = message;
while (state) {
StateBase* tmp = state->nextState();
delete state;
@@ -1071,7 +1068,7 @@ private:
if (!fs)
return 0;
if (!fs->clonable())
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "A FileSystem object could not be cloned.", next);
m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
return 0;
}
@@ -1118,10 +1115,10 @@ private:
if (!arrayBufferView)
return 0;
if (!arrayBufferView->buffer())
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate());
if (underlyingBuffer.IsEmpty())
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next);
StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next);
if (stateOut)
return stateOut;
@@ -1146,7 +1143,7 @@ private:
if (!arrayBuffer)
return 0;
if (arrayBuffer->isNeutered())
- return handleError(InvalidStateError, next);
+ return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>()));
m_writer.writeArrayBuffer(*arrayBuffer);
return 0;
@@ -1158,7 +1155,7 @@ private:
if (!arrayBuffer)
return 0;
if (arrayBuffer->isNeutered())
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next);
m_writer.writeTransferredArrayBuffer(index);
return 0;
}
@@ -1208,6 +1205,7 @@ private:
v8::TryCatch& m_tryCatch;
int m_depth;
Status m_status;
+ String m_errorMessage;
typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool;
ObjectPool m_objectPool;
ObjectPool m_transferredMessagePorts;
@@ -1229,9 +1227,9 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
// that we grey and write below).
ASSERT(!value->IsString());
m_writer.writeObjectReference(objectReference);
- } else if (value.IsEmpty())
- return reportFailure(next);
- else if (value->IsUndefined())
+ } else if (value.IsEmpty()) {
+ return handleError(InputError, "The empty property name cannot be cloned.", next);
+ } else if (value->IsUndefined())
m_writer.writeUndefined();
else if (value->IsNull())
m_writer.writeNull();
@@ -1254,13 +1252,13 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex))
m_writer.writeTransferredMessagePort(messagePortIndex);
else
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "A MessagePort could not be cloned.", next);
} else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex))
return writeTransferredArrayBuffer(value, arrayBufferIndex, next);
else {
v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
if (jsObject.IsEmpty())
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "An object could not be cloned.", next);
greyObject(jsObject);
if (value->IsDate())
m_writer.writeDate(value->NumberValue());
@@ -1288,10 +1286,10 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat
return writeArrayBuffer(value, next);
else if (value->IsObject()) {
if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "An object could not be cloned.", next);
return startObjectState(jsObject, next);
} else
- return handleError(DataCloneError, next);
+ return handleError(DataCloneError, "A value could not be cloned.", next);
}
return 0;
}
@@ -2253,21 +2251,21 @@ private:
} // namespace
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate)
+PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
{
- return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate));
+ return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, exceptionState, isolate));
}
PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate)
{
- bool didThrow;
- return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions));
+ TrackExceptionState exceptionState;
+ return adoptRef(new SerializedScriptValue(value, 0, 0, exceptionState, isolate));
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, bool& didThrow, ScriptState* state)
+PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, ExceptionState& exceptionState, ScriptState* state)
{
ScriptScope scope(state);
- return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, state->isolate()));
+ return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, exceptionState, state->isolate()));
}
PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data)
@@ -2368,14 +2366,13 @@ inline void neuterBinding(ArrayBufferView* object)
}
}
-PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isolate* isolate)
+PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
{
ASSERT(arrayBuffers.size());
for (size_t i = 0; i < arrayBuffers.size(); i++) {
if (arrayBuffers[i]->isNeutered()) {
- setDOMException(InvalidStateError, isolate);
- didThrow = true;
+ exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered.");
return nullptr;
}
}
@@ -2392,8 +2389,7 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews);
if (!result) {
- setDOMException(InvalidStateError, isolate);
- didThrow = true;
+ exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred.");
return nullptr;
}
@@ -2404,52 +2400,36 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
return contents.release();
}
-SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy)
+SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate)
: m_externallyAllocatedMemory(0)
{
- didThrow = false;
Writer writer(isolate);
Serializer::Status status;
+ String errorMessage;
{
v8::TryCatch tryCatch;
Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate);
status = serializer.serialize(value);
if (status == Serializer::JSException) {
- didThrow = true;
// If there was a JS exception thrown, re-throw it.
- if (policy == ThrowExceptions)
- tryCatch.ReThrow();
+ exceptionState.rethrowV8Exception(tryCatch.Exception());
return;
}
+ errorMessage = serializer.errorMessage();
}
switch (status) {
case Serializer::InputError:
case Serializer::DataCloneError:
- // If there was an input error, throw a new exception outside
- // of the TryCatch scope.
- didThrow = true;
- if (policy == ThrowExceptions)
- setDOMException(DataCloneError, isolate);
- return;
- case Serializer::InvalidStateError:
- didThrow = true;
- if (policy == ThrowExceptions)
- setDOMException(InvalidStateError, isolate);
- return;
- case Serializer::JSFailure:
- // If there was a JS failure (but no exception), there's not
- // much we can do except for unwinding the C++ stack by
- // pretending there was a JS exception.
- didThrow = true;
+ exceptionState.throwDOMException(DataCloneError, errorMessage);
return;
case Serializer::Success:
m_data = writer.takeWireString();
ASSERT(m_data.impl()->hasOneRef());
if (arrayBuffers && arrayBuffers->size())
- m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, didThrow, isolate);
+ m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate);
return;
case Serializer::JSException:
- // We should never get here because this case was handled above.
+ ASSERT_NOT_REACHED();
break;
}
ASSERT_NOT_REACHED();
« no previous file with comments | « Source/bindings/v8/SerializedScriptValue.h ('k') | Source/bindings/v8/V8Utilities.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698