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

Unified Diff: third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp

Issue 2323413002: Support ImageData cloning in the V8-based structured clone path. (Closed)
Patch Set: does win_clang like the other order better? Created 4 years, 3 months 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
Index: third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
diff --git a/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b0ab416d2bc0466fe1764194faf63271d727ecc
--- /dev/null
+++ b/third_party/WebKit/Source/bindings/core/v8/serialization/V8ScriptValueSerializerTest.cpp
@@ -0,0 +1,182 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "bindings/core/v8/serialization/V8ScriptValueSerializer.h"
+
+#include "bindings/core/v8/ExceptionStatePlaceholder.h"
+#include "bindings/core/v8/ScriptController.h"
+#include "bindings/core/v8/ScriptSourceCode.h"
+#include "bindings/core/v8/V8BindingForTesting.h"
+#include "bindings/core/v8/V8DOMException.h"
+#include "bindings/core/v8/V8ImageData.h"
+#include "bindings/core/v8/V8StringResource.h"
+#include "bindings/core/v8/serialization/V8ScriptValueDeserializer.h"
+#include "core/frame/LocalFrame.h"
+#include "core/html/ImageData.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+namespace {
+
+class ScopedEnableV8BasedStructuredClone {
+public:
+ ScopedEnableV8BasedStructuredClone()
+ : m_wasEnabled(RuntimeEnabledFeatures::v8BasedStructuredCloneEnabled())
+ {
+ RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(true);
+ }
+ ~ScopedEnableV8BasedStructuredClone()
+ {
+ RuntimeEnabledFeatures::setV8BasedStructuredCloneEnabled(m_wasEnabled);
+ }
+private:
+ bool m_wasEnabled;
+};
+
+RefPtr<SerializedScriptValue> serializedValue(const Vector<uint8_t>& bytes)
+{
+ // TODO(jbroman): Fix this once SerializedScriptValue can take bytes without
+ // endianness swapping.
+ DCHECK_EQ(bytes.size() % 2, 0u);
+ return SerializedScriptValue::create(String(reinterpret_cast<const UChar*>(&bytes[0]), bytes.size() / 2));
+}
+
+v8::Local<v8::Value> roundTrip(v8::Local<v8::Value> value, V8TestingScope& scope)
+{
+ RefPtr<ScriptState> scriptState = scope.getScriptState();
+ ExceptionState& exceptionState = scope.getExceptionState();
+ RefPtr<SerializedScriptValue> serializedScriptValue =
+ V8ScriptValueSerializer(scriptState).serialize(value, nullptr, exceptionState);
+ DCHECK_EQ(!serializedScriptValue, exceptionState.hadException());
+ EXPECT_TRUE(serializedScriptValue);
+ if (!serializedScriptValue)
+ return v8::Local<v8::Value>();
+ return V8ScriptValueDeserializer(scriptState, serializedScriptValue).deserialize();
+}
+
+v8::Local<v8::Value> eval(const String& source, V8TestingScope& scope)
+{
+ return scope.frame().script().executeScriptInMainWorldAndReturnValue(source);
+}
+
+String toJSON(v8::Local<v8::Object> object, const V8TestingScope& scope)
+{
+ return v8StringToWebCoreString<String>(
+ v8::JSON::Stringify(scope.context(), object).ToLocalChecked(),
+ DoNotExternalize);
+}
+
+// Checks for a DOM exception, including a rethrown one.
+::testing::AssertionResult hadDOMException(const StringView& name, ScriptState* scriptState, ExceptionState& exceptionState)
+{
+ if (!exceptionState.hadException())
+ return ::testing::AssertionFailure() << "no exception thrown";
+ DOMException* domException = V8DOMException::toImplWithTypeCheck(scriptState->isolate(), exceptionState.getException());
+ if (!domException)
+ return ::testing::AssertionFailure() << "exception thrown was not a DOMException";
+ if (domException->name() != name)
+ return ::testing::AssertionFailure() << "was " << domException->name();
+ return ::testing::AssertionSuccess();
+}
+
+TEST(V8ScriptValueSerializerTest, RoundTripJSONLikeValue)
+{
+ // Ensure that simple JavaScript objects work.
+ // There are more exhaustive tests of JavaScript objects in V8.
+ ScopedEnableV8BasedStructuredClone enable;
+ V8TestingScope scope;
+ v8::Local<v8::Value> object = eval("({ foo: [1, 2, 3], bar: 'baz' })", scope);
+ DCHECK(object->IsObject());
+ v8::Local<v8::Value> result = roundTrip(object, scope);
+ ASSERT_TRUE(result->IsObject());
+ EXPECT_NE(object, result);
+ EXPECT_EQ(toJSON(object.As<v8::Object>(), scope), toJSON(result.As<v8::Object>(), scope));
+}
+
+TEST(V8ScriptValueSerializerTest, ThrowsDataCloneError)
+{
+ // Ensure that a proper DataCloneError DOMException is thrown when issues
+ // are encountered in V8 (for example, cloning a symbol). It should be an
+ // instance of DOMException, and it should have a proper descriptive
+ // message.
+ ScopedEnableV8BasedStructuredClone enable;
+ V8TestingScope scope;
+ ScriptState* scriptState = scope.getScriptState();
+ ExceptionState exceptionState(scope.isolate(), ExceptionState::ExecutionContext, "Window", "postMessage");
+ v8::Local<v8::Value> symbol = eval("Symbol()", scope);
+ DCHECK(symbol->IsSymbol());
+ ASSERT_FALSE(V8ScriptValueSerializer(scriptState).serialize(symbol, nullptr, exceptionState));
+ ASSERT_TRUE(hadDOMException("DataCloneError", scriptState, exceptionState));
+ DOMException* domException = V8DOMException::toImpl(exceptionState.getException().As<v8::Object>());
+ EXPECT_TRUE(domException->toString().contains("postMessage"));
+}
+
+TEST(V8ScriptValueSerializerTest, RethrowsScriptError)
+{
+ // Ensure that other exceptions, like those thrown by script, are properly
+ // rethrown.
+ ScopedEnableV8BasedStructuredClone enable;
+ V8TestingScope scope;
+ ScriptState* scriptState = scope.getScriptState();
+ ExceptionState exceptionState(scope.isolate(), ExceptionState::ExecutionContext, "Window", "postMessage");
+ v8::Local<v8::Value> exception = eval("myException=new Error()", scope);
+ v8::Local<v8::Value> object = eval("({ get a() { throw myException; }})", scope);
+ DCHECK(object->IsObject());
+ ASSERT_FALSE(V8ScriptValueSerializer(scriptState).serialize(object, nullptr, exceptionState));
+ ASSERT_TRUE(exceptionState.hadException());
+ EXPECT_EQ(exception, exceptionState.getException());
+}
+
+TEST(V8ScriptValueSerializerTest, DeserializationErrorReturnsNull)
+{
+ // If there's a problem during deserialization, it results in null, but no
+ // exception.
+ ScopedEnableV8BasedStructuredClone enable;
+ V8TestingScope scope;
+ ScriptState* scriptState = scope.getScriptState();
+ RefPtr<SerializedScriptValue> invalid = SerializedScriptValue::create("invalid data");
+ v8::Local<v8::Value> result = V8ScriptValueDeserializer(scriptState, invalid).deserialize();
+ EXPECT_TRUE(result->IsNull());
+ EXPECT_FALSE(scope.getExceptionState().hadException());
+}
+
+TEST(V8ScriptValueSerializerTest, RoundTripImageData)
+{
+ // ImageData objects should serialize and deserialize correctly.
+ ScopedEnableV8BasedStructuredClone enable;
+ V8TestingScope scope;
+ ImageData* imageData = ImageData::create(2, 1, ASSERT_NO_EXCEPTION);
+ imageData->data()->data()[0] = 200;
+ v8::Local<v8::Value> wrapper = toV8(imageData, scope.context()->Global(), scope.isolate());
+ v8::Local<v8::Value> result = roundTrip(wrapper, scope);
+ ASSERT_TRUE(V8ImageData::hasInstance(result, scope.isolate()));
+ ImageData* newImageData = V8ImageData::toImpl(result.As<v8::Object>());
+ EXPECT_NE(imageData, newImageData);
+ EXPECT_EQ(imageData->size(), newImageData->size());
+ EXPECT_EQ(imageData->data()->length(), newImageData->data()->length());
+ EXPECT_EQ(200, newImageData->data()->data()[0]);
+}
+
+TEST(V8ScriptValueSerializerTest, DecodeImageData)
+{
+ // Backward compatibility with existing serialized ImageData objects must be
+ // maintained. Add more cases if the format changes; don't remove tests for
+ // old versions.
+ ScopedEnableV8BasedStructuredClone enable;
+ V8TestingScope scope;
+ ScriptState* scriptState = scope.getScriptState();
+ RefPtr<SerializedScriptValue> input = serializedValue({
+ 0xff, 0x09, 0x3f, 0x00, 0x23, 0x02, 0x01, 0x08,
+ 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
+ v8::Local<v8::Value> result = V8ScriptValueDeserializer(scriptState, input).deserialize();
+ ASSERT_TRUE(V8ImageData::hasInstance(result, scope.isolate()));
+ ImageData* newImageData = V8ImageData::toImpl(result.As<v8::Object>());
+ EXPECT_EQ(IntSize(2, 1), newImageData->size());
+ EXPECT_EQ(8u, newImageData->data()->length());
+ EXPECT_EQ(200, newImageData->data()->data()[0]);
+}
+
+} // namespace
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698