Index: Source/bindings/v8/SerializedScriptValue.cpp |
diff --git a/Source/bindings/v8/SerializedScriptValue.cpp b/Source/bindings/v8/SerializedScriptValue.cpp |
index 1a14881f71fcfea0e32f0045f23a23679038f60b..d735e2292b78c5b9f08ee9e4856358436b5f6ac3 100644 |
--- a/Source/bindings/v8/SerializedScriptValue.cpp |
+++ b/Source/bindings/v8/SerializedScriptValue.cpp |
@@ -41,7 +41,6 @@ |
#include "bindings/v8/ScriptScope.h" |
#include "bindings/v8/ScriptState.h" |
#include "bindings/v8/V8Binding.h" |
-#include "bindings/v8/V8Utilities.h" |
#include "bindings/v8/WorkerScriptController.h" |
#include "bindings/v8/custom/V8ArrayBufferCustom.h" |
#include "bindings/v8/custom/V8ArrayBufferViewCustom.h" |
@@ -2440,6 +2439,57 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M |
return deserializer.deserialize(); |
} |
+bool SerializedScriptValue::extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) |
+{ |
+ if (isUndefinedOrNull(value)) { |
+ ports.resize(0); |
+ arrayBuffers.resize(0); |
+ return true; |
+ } |
+ |
+ uint32_t length = 0; |
+ if (value->IsArray()) { |
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value); |
+ length = array->Length(); |
+ } else if (toV8Sequence(value, length, isolate).IsEmpty()) { |
+ exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1)); |
+ return false; |
+ } |
+ |
+ v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value); |
+ |
+ // Validate the passed array of transferrables. |
+ for (unsigned i = 0; i < length; ++i) { |
+ v8::Local<v8::Value> transferrable = transferrables->Get(i); |
+ // Validation of non-null objects, per HTML5 spec 10.3.3. |
+ if (isUndefinedOrNull(transferrable)) { |
+ exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value."); |
+ return false; |
+ } |
+ // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. |
+ if (V8MessagePort::hasInstance(transferrable, isolate)) { |
+ RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable)); |
+ // Check for duplicate MessagePorts. |
+ if (ports.contains(port)) { |
+ exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port."); |
+ return false; |
+ } |
+ ports.append(port.release()); |
+ } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) { |
+ RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable)); |
+ if (arrayBuffers.contains(arrayBuffer)) { |
+ exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer."); |
+ return false; |
+ } |
+ arrayBuffers.append(arrayBuffer.release()); |
+ } else { |
+ exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type."); |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext() |
{ |
if (m_externallyAllocatedMemory) |