2010-03-31 Vitaly Repeshko <vitalyr@chromium.org>
Reviewed by David Levin.
[V8] SerializedScriptValue must be deserialized only once and in the right context
https://bugs.webkit.org/show_bug.cgi?id=36892
See also https://bugs.webkit.org/show_bug.cgi?id=34227 for the
corresponding JSC change.
General idea: SerializedScriptValue must be deserialized only once
and in the context of the intended MessageEvent recepient. The
approach we take for now is to eagerly deserialize when a
JavaScript wrapper for MessageEvent is created.
A better fix would be to keep a reference to the context in
MessageEvent and use it when lazily deserializing. It's harder to
do since the API doesn't have a clean method to have such a reference.
Tested by fast/dom/Window/window-postmessage-clone-frames.html. This
test still fails but only for the types which we can't serialize yet.
* bindings/scripts/CodeGeneratorV8.pm:
* bindings/v8/SerializedScriptValue.h:
(WebCore::SerializedScriptValue::deserializeAndSetProperty):
* bindings/v8/custom/V8MessageEventCustom.cpp:
(WebCore::V8MessageEvent::initMessageEventCallback):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@56877 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 93fa577..4142ece 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,31 @@
+2010-03-31 Vitaly Repeshko <vitalyr@chromium.org>
+
+ Reviewed by David Levin.
+
+ [V8] SerializedScriptValue must be deserialized only once and in the right context
+ https://bugs.webkit.org/show_bug.cgi?id=36892
+
+ See also https://bugs.webkit.org/show_bug.cgi?id=34227 for the
+ corresponding JSC change.
+
+ General idea: SerializedScriptValue must be deserialized only once
+ and in the context of the intended MessageEvent recepient. The
+ approach we take for now is to eagerly deserialize when a
+ JavaScript wrapper for MessageEvent is created.
+
+ A better fix would be to keep a reference to the context in
+ MessageEvent and use it when lazily deserializing. It's harder to
+ do since the API doesn't have a clean method to have such a reference.
+
+ Tested by fast/dom/Window/window-postmessage-clone-frames.html. This
+ test still fails but only for the types which we can't serialize yet.
+
+ * bindings/scripts/CodeGeneratorV8.pm:
+ * bindings/v8/SerializedScriptValue.h:
+ (WebCore::SerializedScriptValue::deserializeAndSetProperty):
+ * bindings/v8/custom/V8MessageEventCustom.cpp:
+ (WebCore::V8MessageEvent::initMessageEventCallback):
+
2010-03-31 Adam Barth <abarth@webkit.org>
Reviewed by Darin Fisher.
diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm
index 68007e2..0c28707 100644
--- a/WebCore/bindings/scripts/CodeGeneratorV8.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm
@@ -1141,6 +1141,10 @@
my $attrName = $attribute->signature->name;
my $attrExt = $attribute->signature->extendedAttributes;
+ # Attributes of type SerializedScriptValue are set in the
+ # constructor and don't require callbacks.
+ return if ($attribute->signature->type eq "SerializedScriptValue");
+
my $accessControl = "v8::DEFAULT";
if ($attrExt->{"DoNotCheckDomainSecurityOnGet"}) {
$accessControl = "v8::ALL_CAN_READ";
@@ -1467,6 +1471,7 @@
push(@implContentDecls, "template <typename T> void V8_USE(T) { }\n\n");
my $hasConstructors = 0;
+ my $serializedAttribute;
# Generate property accessors for attributes.
for ($index = 0; $index < @{$dataNode->attributes}; $index++) {
$attribute = @{$dataNode->attributes}[$index];
@@ -1486,6 +1491,15 @@
$attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
}
+ # Attributes of type SerializedScriptValue are set in the
+ # constructor and don't require callbacks.
+ if ($attrType eq "SerializedScriptValue") {
+ die "Only one attribute of type SerializedScriptValue supported" if $serializedAttribute;
+ $implIncludes{"SerializedScriptValue.h"} = 1;
+ $serializedAttribute = $attribute;
+ next;
+ }
+
# Do not generate accessor if this is a custom attribute. The
# call will be forwarded to a hand-written accessor
# implementation.
@@ -1911,7 +1925,7 @@
END
}
- GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType);
+ GenerateToV8Converters($dataNode, $interfaceName, $className, $nativeType, $serializedAttribute);
push(@implContent, <<END);
@@ -1940,6 +1954,7 @@
my $interfaceName = shift;
my $className = shift;
my $nativeType = shift;
+ my $serializedAttribute = shift;
my $domMapFunction = GetDomMapFunction($dataNode, $interfaceName);
my $forceNewObjectInput = IsDOMNodeType($interfaceName) ? ", bool forceNewObject" : "";
@@ -1993,7 +2008,6 @@
push(@implContent, <<END);
wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl);
END
-
if (IsNodeSubType($dataNode)) {
push(@implContent, <<END);
// Exit the node's context if it was entered.
@@ -2008,6 +2022,22 @@
END
push(@implContent, "\n impl->ref();\n") if IsRefPtrType($interfaceName);
+ # Eagerly deserialize attributes of type SerializedScriptValue
+ # while we're in the right context.
+ if ($serializedAttribute) {
+ die "Attribute of type SerializedScriptValue expected" if $serializedAttribute->signature->type ne "SerializedScriptValue";
+ my $attrName = $serializedAttribute->signature->name;
+ my $attrAttr = "v8::DontDelete";
+ if ($serializedAttribute->type =~ /^readonly/) {
+ $attrAttr .= " | v8::ReadOnly";
+ }
+ $attrAttr = "static_cast<v8::PropertyAttribute>($attrAttr)";
+ my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
+ push(@implContent, <<END);
+ SerializedScriptValue::deserializeAndSetProperty(wrapper, "${attrName}", ${attrAttr}, impl->${getterFunc}());
+END
+ }
+
if ($domMapFunction) {
push(@implContent, <<END);
${domMapFunction}.set(impl, v8::Persistent<v8::Object>::New(wrapper));
diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h
index ba4d5ed..2b6c392 100644
--- a/WebCore/bindings/v8/SerializedScriptValue.h
+++ b/WebCore/bindings/v8/SerializedScriptValue.h
@@ -40,6 +40,18 @@
class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
public:
+ // Deserializes the given value and sets it as a property on the
+ // object.
+ static void deserializeAndSetProperty(v8::Handle<v8::Object> object,
+ const char* propertyName,
+ v8::PropertyAttribute attribute,
+ SerializedScriptValue* value)
+ {
+ ASSERT(value);
+ v8::Handle<v8::Value> deserialized = value->deserialize();
+ object->ForceSet(v8::String::NewSymbol(propertyName), deserialized, attribute);
+ }
+
// Creates a serialized representation of the given V8 value.
static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value> value)
{
diff --git a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp
index d41a785..cca4a24 100644
--- a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp
@@ -84,6 +84,8 @@
return v8::Undefined();
}
event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg.release(), originArg, lastEventIdArg, sourceArg, portArray.release());
+ v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly);
+ SerializedScriptValue::deserializeAndSetProperty(args.Holder(), "data", dataAttr, event->data());
return v8::Undefined();
}