Diff
Modified: trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-test.js (93765 => 93766)
--- trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-test.js 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-test.js 2011-08-25 09:25:16 UTC (rev 93766)
@@ -111,7 +111,7 @@
function onmessage(evt) {
eventData = evt.data;
if (evt.data !== evt.data)
- console.innerHTML += "MessageEvent.data does not produce the same value on multiple queries.<br>";
+ console.innerHTML += "MessageEvent.data does not produce the same value on multiple queries. " + evt.data + ", " + evt.data + "<br>";
var message = messages.shift();
switch (message) {
case "cyclicObject":
Modified: trunk/Source/WebCore/ChangeLog (93765 => 93766)
--- trunk/Source/WebCore/ChangeLog 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/ChangeLog 2011-08-25 09:25:16 UTC (rev 93766)
@@ -1,3 +1,42 @@
+2011-08-25 Yuta Kitamura <[email protected]>
+
+ Let MessageEvent.data hold SerializedScriptValue or String selectively
+ https://bugs.webkit.org/show_bug.cgi?id=66841
+
+ Reviewed by Adam Barth.
+
+ MessageEvent from WebSocket contains a String in its "data" attribute, but it does not have
+ to be serialized.
+
+ No new tests are added, because this is refactoring and the behavior should not change.
+
+ * bindings/js/JSMessageEventCustom.cpp:
+ (WebCore::JSMessageEvent::data):
+ To call putAnonymousValue(), "this" needs to be converted to non-const using const_cast<>.
+ (WebCore::JSMessageEvent::initMessageEvent):
+ Update the cache value as well.
+ * bindings/v8/custom/V8MessageEventCustom.cpp:
+ (WebCore::V8MessageEvent::dataAccessorGetter):
+ ForceSet() is used to cache a value. This is the same as what the code generated by
+ CodeGeneratorV8 does.
+ (WebCore::V8MessageEvent::initMessageEventCallback):
+ * dom/MessageEvent.cpp:
+ (WebCore::MessageEvent::MessageEvent):
+ (WebCore::MessageEvent::initMessageEvent):
+ (WebCore::MessageEvent::data):
+ This is only used within the Objective-C bindings (JSC and V8 have the custom functions).
+ Since Objective-C code generator does not support [CustomGetter] IDL attribute, there is
+ no good way to return a variant value for Objective-C bindings.
+ * dom/MessageEvent.h:
+ (WebCore::MessageEvent::create):
+ (WebCore::MessageEvent::dataType):
+ (WebCore::MessageEvent::dataAsSerializedScriptValue):
+ (WebCore::MessageEvent::dataAsString):
+ * dom/MessageEvent.idl:
+ * websockets/WebSocket.cpp:
+ (WebCore::WebSocket::didReceiveMessage):
+ Construct a MessageEvent without serializing the received message.
+
2011-08-25 MORITA Hajime <[email protected]>
Unreviewed, rolling out r93762.
Modified: trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp (93765 => 93766)
--- trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/bindings/js/JSMessageEventCustom.cpp 2011-08-25 09:25:16 UTC (rev 93766)
@@ -42,6 +42,31 @@
namespace WebCore {
+JSValue JSMessageEvent::data(ExecState* exec) const
+{
+ if (JSValue cachedValue = getAnonymousValue(JSMessageEvent::dataSlot))
+ return cachedValue;
+
+ MessageEvent* event = static_cast<MessageEvent*>(impl());
+ JSValue result;
+ switch (event->dataType()) {
+ case MessageEvent::DataTypeSerializedScriptValue:
+ if (SerializedScriptValue* serializedValue = event->dataAsSerializedScriptValue())
+ result = serializedValue->deserialize(exec, globalObject(), NonThrowing);
+ else
+ result = jsNull();
+ break;
+
+ case MessageEvent::DataTypeString:
+ result = jsString(exec, event->dataAsString());
+ break;
+ }
+
+ // Save the result so we don't have to deserialize the value again.
+ const_cast<JSMessageEvent*>(this)->putAnonymousValue(exec->globalData(), JSMessageEvent::dataSlot, result);
+ return result;
+}
+
JSValue JSMessageEvent::ports(ExecState* exec) const
{
MessagePortArray* ports = static_cast<MessageEvent*>(impl())->ports();
@@ -75,6 +100,12 @@
MessageEvent* event = static_cast<MessageEvent*>(this->impl());
event->initMessageEvent(ustringToAtomicString(typeArg), canBubbleArg, cancelableArg, dataArg.release(), ustringToString(originArg), ustringToString(lastEventIdArg), sourceArg, messagePorts.release());
+ JSValue result;
+ if (SerializedScriptValue* serializedValue = event->dataAsSerializedScriptValue())
+ result = serializedValue->deserialize(exec, globalObject(), NonThrowing);
+ else
+ result = jsNull();
+ putAnonymousValue(exec->globalData(), JSMessageEvent::dataSlot, result);
return jsUndefined();
}
Modified: trunk/Source/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp (93765 => 93766)
--- trunk/Source/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp 2011-08-25 09:25:16 UTC (rev 93766)
@@ -42,6 +42,34 @@
namespace WebCore {
+v8::Handle<v8::Value> V8MessageEvent::dataAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
+{
+ INC_STATS("DOM.MessageEvent.data");
+ MessageEvent* event = V8MessageEvent::toNative(info.Holder());
+
+ v8::Handle<v8::Value> result;
+ switch (event->dataType()) {
+ case MessageEvent::DataTypeSerializedScriptValue:
+ if (SerializedScriptValue* serializedValue = event->dataAsSerializedScriptValue())
+ result = serializedValue->deserialize();
+ else
+ result = v8::Null();
+ break;
+
+ case MessageEvent::DataTypeString: {
+ String stringValue = event->dataAsString();
+ result = v8::String::New(fromWebCoreString(stringValue), stringValue.length());
+ break;
+ }
+ }
+
+ // Overwrite the data attribute so it returns the cached result in future invocations.
+ // This custom handler (dataAccessGetter) will not be called again.
+ v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly);
+ info.Holder()->ForceSet(name, result, dataAttr);
+ return result;
+}
+
v8::Handle<v8::Value> V8MessageEvent::portsAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
{
INC_STATS("DOM.MessageEvent.ports");
@@ -85,7 +113,7 @@
}
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());
+ SerializedScriptValue::deserializeAndSetProperty(args.Holder(), "data", dataAttr, event->dataAsSerializedScriptValue());
return v8::Undefined();
}
Modified: trunk/Source/WebCore/dom/MessageEvent.cpp (93765 => 93766)
--- trunk/Source/WebCore/dom/MessageEvent.cpp 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/dom/MessageEvent.cpp 2011-08-25 09:25:16 UTC (rev 93766)
@@ -34,13 +34,15 @@
namespace WebCore {
MessageEvent::MessageEvent()
- : m_data(SerializedScriptValue::create())
+ : m_dataType(DataTypeSerializedScriptValue)
+ , m_dataAsSerializedScriptValue(SerializedScriptValue::create())
{
}
MessageEvent::MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray> ports)
: Event(eventNames().messageEvent, false, false)
- , m_data(data)
+ , m_dataType(DataTypeSerializedScriptValue)
+ , m_dataAsSerializedScriptValue(data)
, m_origin(origin)
, m_lastEventId(lastEventId)
, m_source(source)
@@ -48,6 +50,15 @@
{
}
+MessageEvent::MessageEvent(const String& data)
+ : Event(eventNames().messageEvent, false, false)
+ , m_dataType(DataTypeString)
+ , m_dataAsString(data)
+ , m_origin("")
+ , m_lastEventId("")
+{
+}
+
MessageEvent::~MessageEvent()
{
}
@@ -58,14 +69,23 @@
return;
initEvent(type, canBubble, cancelable);
-
- m_data = data;
+
+ m_dataType = DataTypeSerializedScriptValue;
+ m_dataAsSerializedScriptValue = data;
m_origin = origin;
m_lastEventId = lastEventId;
m_source = source;
m_ports = ports;
}
+// FIXME: Remove this when we have custom ObjC binding support.
+SerializedScriptValue* MessageEvent::data() const
+{
+ // WebSocket is not exposed in ObjC bindings, thus the data type should always be SerializedScriptValue.
+ ASSERT(m_dataType == DataTypeSerializedScriptValue);
+ return m_dataAsSerializedScriptValue.get();
+}
+
// FIXME: remove this when we update the ObjC bindings (bug #28774).
MessagePort* MessageEvent::messagePort()
{
Modified: trunk/Source/WebCore/dom/MessageEvent.h (93765 => 93766)
--- trunk/Source/WebCore/dom/MessageEvent.h 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/dom/MessageEvent.h 2011-08-25 09:25:16 UTC (rev 93766)
@@ -47,16 +47,22 @@
{
return adoptRef(new MessageEvent(data, origin, lastEventId, source, ports));
}
+ static PassRefPtr<MessageEvent> create(const String& data)
+ {
+ return adoptRef(new MessageEvent(data));
+ }
virtual ~MessageEvent();
void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>);
- SerializedScriptValue* data() const { return m_data.get(); }
const String& origin() const { return m_origin; }
const String& lastEventId() const { return m_lastEventId; }
DOMWindow* source() const { return m_source.get(); }
MessagePortArray* ports() const { return m_ports.get(); }
+ // FIXME: Remove this when we have custom ObjC binding support.
+ SerializedScriptValue* data() const;
+
// FIXME: remove this when we update the ObjC bindings (bug #28774).
MessagePort* messagePort();
// FIXME: remove this when we update the ObjC bindings (bug #28774).
@@ -64,11 +70,22 @@
virtual bool isMessageEvent() const;
+ enum DataType {
+ DataTypeSerializedScriptValue,
+ DataTypeString
+ };
+ DataType dataType() const { return m_dataType; }
+ SerializedScriptValue* dataAsSerializedScriptValue() const { return m_dataAsSerializedScriptValue.get(); }
+ String dataAsString() const { return m_dataAsString; }
+
private:
MessageEvent();
MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
+ explicit MessageEvent(const String& data);
- RefPtr<SerializedScriptValue> m_data;
+ DataType m_dataType;
+ RefPtr<SerializedScriptValue> m_dataAsSerializedScriptValue;
+ String m_dataAsString;
String m_origin;
String m_lastEventId;
RefPtr<DOMWindow> m_source;
Modified: trunk/Source/WebCore/dom/MessageEvent.idl (93765 => 93766)
--- trunk/Source/WebCore/dom/MessageEvent.idl 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/dom/MessageEvent.idl 2011-08-25 09:25:16 UTC (rev 93766)
@@ -29,12 +29,11 @@
interface [
NoStaticTables
] MessageEvent : Event {
- readonly attribute [CachedAttribute] SerializedScriptValue data;
-
readonly attribute DOMString origin;
readonly attribute DOMString lastEventId;
readonly attribute DOMWindow source;
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
+ readonly attribute [CachedAttribute, CustomGetter] any data;
readonly attribute [CustomGetter] Array ports;
[Custom] void initMessageEvent(in [Optional=CallWithDefaultValue] DOMString typeArg,
@@ -46,6 +45,10 @@
in [Optional=CallWithDefaultValue] DOMWindow sourceArg,
in [Optional=CallWithDefaultValue] Array messagePorts);
#else
+ // Code generator for ObjC bindings does not support custom bindings, thus there is no good way to
+ // return a variant value. As workaround, expose the data attribute as SerializedScriptValue.
+ readonly attribute SerializedScriptValue data;
+
// There's no good way to expose an array via the ObjC bindings, so for now just expose a single port.
readonly attribute MessagePort messagePort;
Modified: trunk/Source/WebCore/websockets/WebSocket.cpp (93765 => 93766)
--- trunk/Source/WebCore/websockets/WebSocket.cpp 2011-08-25 08:38:37 UTC (rev 93765)
+++ trunk/Source/WebCore/websockets/WebSocket.cpp 2011-08-25 09:25:16 UTC (rev 93766)
@@ -393,9 +393,7 @@
if (m_state != OPEN && m_state != CLOSING)
return;
ASSERT(scriptExecutionContext());
- RefPtr<MessageEvent> evt = MessageEvent::create();
- evt->initMessageEvent(eventNames().messageEvent, false, false, SerializedScriptValue::create(msg), "", "", 0, 0);
- dispatchEvent(evt);
+ dispatchEvent(MessageEvent::create(msg));
}
void WebSocket::didReceiveMessageError()