Implement a MessageEvent constructor for JSC
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Sep 2011 02:02:18 +0000 (02:02 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 28 Sep 2011 02:02:18 +0000 (02:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=68883

Patch by Kentaro Hara <haraken@chromium.org> on 2011-09-27
Reviewed by Adam Barth.

Source/WebCore:

The spec for MessageEvent is here:
http://www.whatwg.org/specs/web-apps/current-work/#messageevent

Currently, some tests in fast/events/constructors/message-event-constructor.html
are failing or crashing in DRT, as we commented in the test file.
This is because MessageEvent.data is implemented as SerializedScriptValue,
and thus it cannot keep ScriptValue passed by JavaScript.
This is the same issue as the bug (https://bugs.webkit.org/show_bug.cgi?id=68345).
We will soon make a follow-up patch to fix these failures, after this
patch is landed.

Test: fast/events/constructors/message-event-constructor.html

* bindings/generic/EventConstructors.h: Added a definition for the MessageEvent constructor.
* bindings/js/JSDictionary.cpp:
(WebCore::JSDictionary::convertValue): Generates MessagePortArray from the list of message ports in the format of JSValues.
* bindings/js/JSDictionary.h:
* bindings/js/JSEventConstructors.cpp: Added #includes for MessageEvent.
* dom/MessageEvent.cpp:
(WebCore::MessageEventInit::MessageEventInit):
(WebCore::MessageEvent::MessageEvent):
(WebCore::MessageEvent::initMessageEvent):
* dom/MessageEvent.h: Added a definition for MessageEvent. Removed an extra leading spaces.
(WebCore::MessageEvent::create):
(WebCore::MessageEvent::origin):
(WebCore::MessageEvent::lastEventId):
(WebCore::MessageEvent::source):
(WebCore::MessageEvent::ports):
(WebCore::MessageEvent::dataType):
(WebCore::MessageEvent::dataAsSerializedScriptValue):
(WebCore::MessageEvent::dataAsString):
(WebCore::MessageEvent::dataAsBlob):
(WebCore::MessageEvent::dataAsArrayBuffer):
* dom/MessageEvent.idl: Makes MessageEvent constructible.

LayoutTests:

message-event-constructor.html checks the behavior of the MessageEvent constructor.

* fast/dom/constructed-objects-prototypes-expected.txt: Now window has MessageEvent.
* fast/events/constructors/message-event-constructor-expected.txt: Added.
* fast/events/constructors/message-event-constructor.html: Added.
* platform/chromium/test_expectations.txt: Skipped message-event-constructor.html, since V8 does not yet have the MessageEvent constructor.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96179 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/dom/constructed-objects-prototypes-expected.txt
LayoutTests/fast/events/constructors/message-event-constructor-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/constructors/message-event-constructor.html [new file with mode: 0644]
LayoutTests/platform/chromium/test_expectations.txt
Source/WebCore/ChangeLog
Source/WebCore/bindings/generic/EventConstructors.h
Source/WebCore/bindings/js/JSDictionary.cpp
Source/WebCore/bindings/js/JSDictionary.h
Source/WebCore/bindings/js/JSEventConstructors.cpp
Source/WebCore/dom/MessageEvent.cpp
Source/WebCore/dom/MessageEvent.h
Source/WebCore/dom/MessageEvent.idl

index 01f4802..4174eb5 100644 (file)
@@ -1,3 +1,17 @@
+2011-09-27  Kentaro Hara  <haraken@chromium.org>
+
+        Implement a MessageEvent constructor for JSC
+        https://bugs.webkit.org/show_bug.cgi?id=68883
+
+        Reviewed by Adam Barth.
+
+        message-event-constructor.html checks the behavior of the MessageEvent constructor.
+
+        * fast/dom/constructed-objects-prototypes-expected.txt: Now window has MessageEvent.
+        * fast/events/constructors/message-event-constructor-expected.txt: Added.
+        * fast/events/constructors/message-event-constructor.html: Added.
+        * platform/chromium/test_expectations.txt: Skipped message-event-constructor.html, since V8 does not yet have the MessageEvent constructor.
+
 2011-09-27  Eric Uhrhane  <ericu@chromium.org>
 
         [Chromium/FileWriter] race condition in FileWriter completion can lead to assert
index 03dc8c8..4905284 100644 (file)
@@ -23,6 +23,8 @@ PASS (new inner.Image()).isInner is true
 PASS (new inner.Image()).constructor.isInner is true
 PASS (new inner.MessageChannel()).isInner is true
 PASS (new inner.MessageChannel()).constructor.isInner is true
+PASS (new inner.MessageEvent()).isInner is true
+PASS (new inner.MessageEvent()).constructor.isInner is true
 PASS (new inner.Option()).isInner is true
 PASS (new inner.Option()).constructor.isInner is true
 PASS (new inner.PageTransitionEvent()).isInner is true
diff --git a/LayoutTests/fast/events/constructors/message-event-constructor-expected.txt b/LayoutTests/fast/events/constructors/message-event-constructor-expected.txt
new file mode 100644 (file)
index 0000000..5fcc4d2
--- /dev/null
@@ -0,0 +1,107 @@
+This tests the constructor for the MessageEvent DOM class.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS new MessageEvent('eventType').bubbles is false
+PASS new MessageEvent('eventType').cancelable is false
+PASS new MessageEvent('eventType').data is null
+PASS new MessageEvent('eventType').origin is ""
+PASS new MessageEvent('eventType').lastEventId is ""
+PASS new MessageEvent('eventType').source is null
+PASS new MessageEvent('eventType').ports is []
+PASS new MessageEvent('eventType', { bubbles: false }).bubbles is false
+PASS new MessageEvent('eventType', { bubbles: true }).bubbles is true
+PASS new MessageEvent('eventType', { cancelable: false }).cancelable is false
+PASS new MessageEvent('eventType', { cancelable: true }).cancelable is true
+FAIL new MessageEvent('eventType', { data: test_object }).data should be [object Object]. Was [object Object].
+PASS new MessageEvent('eventType', { data: undefined }).data is undefined
+PASS new MessageEvent('eventType', { data: null }).data is null
+PASS new MessageEvent('eventType', { data: false }).data is false
+PASS new MessageEvent('eventType', { data: true }).data is true
+PASS new MessageEvent('eventType', { data: '' }).data is ""
+PASS new MessageEvent('eventType', { data: 'chocolate' }).data is "chocolate"
+PASS new MessageEvent('eventType', { data: 12345 }).data is 12345
+PASS new MessageEvent('eventType', { data: 18446744073709551615 }).data is 18446744073709552000
+PASS new MessageEvent('eventType', { data: NaN }).data is NaN
+PASS new MessageEvent('eventType', { data: {valueOf: function () { return test_object; } } }).data == test_object is false
+PASS new MessageEvent('eventType', { get data() { return 123; } }).data is 123
+PASS new MessageEvent('eventType', { get data() { throw 'MessageEvent Error'; } }) threw exception MessageEvent Error.
+PASS new MessageEvent('eventType', { origin: 'melancholy' }).origin is "melancholy"
+PASS new MessageEvent('eventType', { origin: '' }).origin is ""
+PASS new MessageEvent('eventType', { origin: undefined }).origin is "undefined"
+PASS new MessageEvent('eventType', { origin: null }).origin is "null"
+PASS new MessageEvent('eventType', { origin: false }).origin is "false"
+PASS new MessageEvent('eventType', { origin: true }).origin is "true"
+PASS new MessageEvent('eventType', { origin: 12345 }).origin is "12345"
+PASS new MessageEvent('eventType', { origin: 18446744073709551615 }).origin is "18446744073709552000"
+PASS new MessageEvent('eventType', { origin: NaN }).origin is "NaN"
+PASS new MessageEvent('eventType', { origin: [] }).origin is ""
+PASS new MessageEvent('eventType', { origin: [1, 2, 3] }).origin is "1,2,3"
+PASS new MessageEvent('eventType', { origin: {melancholy: 12345} }).origin is "[object Object]"
+PASS new MessageEvent('eventType', { origin: {valueOf: function () { return 'melancholy'; } } }).origin is "[object Object]"
+PASS new MessageEvent('eventType', { get origin() { return 123; } }).origin is "123"
+PASS new MessageEvent('eventType', { get origin() { throw 'MessageEvent Error'; } }) threw exception MessageEvent Error.
+PASS new MessageEvent('eventType', { lastEventId: 'melancholy' }).lastEventId is "melancholy"
+PASS new MessageEvent('eventType', { lastEventId: '' }).lastEventId is ""
+PASS new MessageEvent('eventType', { lastEventId: undefined }).lastEventId is "undefined"
+PASS new MessageEvent('eventType', { lastEventId: null }).lastEventId is "null"
+PASS new MessageEvent('eventType', { lastEventId: false }).lastEventId is "false"
+PASS new MessageEvent('eventType', { lastEventId: true }).lastEventId is "true"
+PASS new MessageEvent('eventType', { lastEventId: 12345 }).lastEventId is "12345"
+PASS new MessageEvent('eventType', { lastEventId: 18446744073709551615 }).lastEventId is "18446744073709552000"
+PASS new MessageEvent('eventType', { lastEventId: NaN }).lastEventId is "NaN"
+PASS new MessageEvent('eventType', { lastEventId: [] }).lastEventId is ""
+PASS new MessageEvent('eventType', { lastEventId: [1, 2, 3] }).lastEventId is "1,2,3"
+PASS new MessageEvent('eventType', { lastEventId: {melancholy: 12345} }).lastEventId is "[object Object]"
+PASS new MessageEvent('eventType', { lastEventId: {valueOf: function () { return 'melancholy'; } } }).lastEventId is "[object Object]"
+PASS new MessageEvent('eventType', { get lastEventId() { return 123; } }).lastEventId is "123"
+PASS new MessageEvent('eventType', { get lastEventId() { throw 'MessageEvent Error'; } }) threw exception MessageEvent Error.
+PASS new MessageEvent('eventType', { source: window }).source is window
+PASS new MessageEvent('eventType', { source: this }).source is this
+PASS new MessageEvent('eventType', { source: test_object }).source is null
+PASS new MessageEvent('eventType', { source: document }).source is null
+PASS new MessageEvent('eventType', { source: undefined }).source is null
+PASS new MessageEvent('eventType', { source: null }).source is null
+PASS new MessageEvent('eventType', { source: false }).source is null
+PASS new MessageEvent('eventType', { source: true }).source is null
+PASS new MessageEvent('eventType', { source: '' }).source is null
+PASS new MessageEvent('eventType', { source: 'chocolate' }).source is null
+PASS new MessageEvent('eventType', { source: 12345 }).source is null
+PASS new MessageEvent('eventType', { source: 18446744073709551615 }).source is null
+PASS new MessageEvent('eventType', { source: NaN }).source is null
+PASS new MessageEvent('eventType', { source: {valueOf: function () { return window; } } }).source == window is false
+PASS new MessageEvent('eventType', { get source() { return 123; } }).source is null
+PASS new MessageEvent('eventType', { get source() { throw 'MessageEvent Error'; } }) threw exception MessageEvent Error.
+PASS new MessageEvent('eventType', { ports: [channel.port1, channel.port2, channel.port2] }).ports[0] is channel.port1
+PASS new MessageEvent('eventType', { ports: [channel.port1, channel.port2, channel.port2] }).ports[1] is channel.port2
+PASS new MessageEvent('eventType', { ports: [channel.port1, channel.port2, channel.port2] }).ports[2] is channel.port2
+PASS new MessageEvent('eventType', { ports: [] }).ports is []
+PASS new MessageEvent('eventType', { ports: undefined }).ports is []
+PASS new MessageEvent('eventType', { ports: null }).ports is []
+PASS new MessageEvent('eventType', { ports: [1, 2, 3] }).ports[2] threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: test_object }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: document }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: false }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: true }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: '' }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: 'chocolate' }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: 12345 }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: 18446744073709551615 }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { ports: NaN }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { get ports() { return 123; } }).ports threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { get ports() { throw 'MessageEvent Error'; } }) threw exception MessageEvent Error.
+PASS new MessageEvent('eventType', { ports: {valueOf: function () { return [channel.port1, channel.port2, channel.port2]; } } }).ports[0] threw exception TypeError: Type error.
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).bubbles is true
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).cancelable is true
+FAIL new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).data should be [object Object]. Was [object Object].
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).origin is "wonderful"
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).lastEventId is "excellent"
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).source is window
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).ports[0] is channel.port1
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).ports[1] is channel.port2
+PASS new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).ports[2] is channel.port2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/constructors/message-event-constructor.html b/LayoutTests/fast/events/constructors/message-event-constructor.html
new file mode 100644 (file)
index 0000000..6dfb6f1
--- /dev/null
@@ -0,0 +1,138 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css">
+<script src="../../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+
+description("This tests the constructor for the MessageEvent DOM class.");
+
+var test_object = {nyannyan: 123};
+
+// No initializer is passed.
+shouldBe("new MessageEvent('eventType').bubbles", "false");
+shouldBe("new MessageEvent('eventType').cancelable", "false");
+shouldBe("new MessageEvent('eventType').data", "null");
+shouldBeEqualToString("new MessageEvent('eventType').origin", "");
+shouldBeEqualToString("new MessageEvent('eventType').lastEventId", "");
+shouldBe("new MessageEvent('eventType').source", "null");
+shouldBe("new MessageEvent('eventType').ports", "[]");
+
+// bubbles is passed.
+shouldBe("new MessageEvent('eventType', { bubbles: false }).bubbles", "false");
+shouldBe("new MessageEvent('eventType', { bubbles: true }).bubbles", "true");
+
+// cancelable is passed.
+shouldBe("new MessageEvent('eventType', { cancelable: false }).cancelable", "false");
+shouldBe("new MessageEvent('eventType', { cancelable: true }).cancelable", "true");
+
+// data is passed.
+// FIXME(haraken): This fails because MessageEvent.data cannot handle ScriptValue.
+shouldBe("new MessageEvent('eventType', { data: test_object }).data", "test_object");
+// FIXME(haraken): When we pass a DOM object, it crashes in DRT (it returns TypeError in non-DRT build).
+// shouldBe("new MessageEvent('eventType', { data: document }).data", "document");
+shouldBe("new MessageEvent('eventType', { data: undefined }).data", "undefined");
+shouldBe("new MessageEvent('eventType', { data: null }).data", "null");
+shouldBe("new MessageEvent('eventType', { data: false }).data", "false");
+shouldBe("new MessageEvent('eventType', { data: true }).data", "true");
+shouldBeEqualToString("new MessageEvent('eventType', { data: '' }).data", "");
+shouldBeEqualToString("new MessageEvent('eventType', { data: 'chocolate' }).data", "chocolate");
+shouldBe("new MessageEvent('eventType', { data: 12345 }).data", "12345");
+shouldBe("new MessageEvent('eventType', { data: 18446744073709551615 }).data", "18446744073709552000");
+shouldBe("new MessageEvent('eventType', { data: NaN }).data", "NaN");
+// Note that valueOf() is not called, when the left hand side is evaluated.
+shouldBeFalse("new MessageEvent('eventType', { data: {valueOf: function () { return test_object; } } }).data == test_object");
+shouldBe("new MessageEvent('eventType', { get data() { return 123; } }).data", "123");
+shouldThrow("new MessageEvent('eventType', { get data() { throw 'MessageEvent Error'; } })");
+
+// origin or lastEventId is passed.
+["origin", "lastEventId"].forEach(function (attr) {
+    // Strings.
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": 'melancholy' })." + attr, "melancholy");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": '' })." + attr, "");
+
+    // Non-strings.
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": undefined })." + attr, "undefined");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": null })." + attr, "null");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": false })." + attr, "false");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": true })." + attr, "true");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": 12345 })." + attr, "12345");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": 18446744073709551615 })." + attr, "18446744073709552000");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": NaN })." + attr, "NaN");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": [] })." + attr, "");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": [1, 2, 3] })." + attr, "1,2,3");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": {melancholy: 12345} })." + attr, "[object Object]");
+    shouldBeEqualToString("new MessageEvent('eventType', { " + attr + ": {valueOf: function () { return 'melancholy'; } } })." + attr, "[object Object]");
+    shouldBeEqualToString("new MessageEvent('eventType', { get " + attr + "() { return 123; } })." + attr, "123");
+    shouldThrow("new MessageEvent('eventType', { get " + attr + "() { throw 'MessageEvent Error'; } })");
+});
+
+// source is passed.
+// Window objects.
+shouldBe("new MessageEvent('eventType', { source: window }).source", "window");
+shouldBe("new MessageEvent('eventType', { source: this }).source", "this");
+
+// Non-window objects.
+shouldBe("new MessageEvent('eventType', { source: test_object }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: document }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: undefined }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: null }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: false }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: true }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: '' }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: 'chocolate' }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: 12345 }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: 18446744073709551615 }).source", "null");
+shouldBe("new MessageEvent('eventType', { source: NaN }).source", "null");
+// Note that valueOf() is not called, when the left hand side is evaluated.
+shouldBeFalse("new MessageEvent('eventType', { source: {valueOf: function () { return window; } } }).source == window");
+shouldBe("new MessageEvent('eventType', { get source() { return 123; } }).source", "null");
+shouldThrow("new MessageEvent('eventType', { get source() { throw 'MessageEvent Error'; } })");
+
+// ports is passed.
+// Valid message ports.
+var channel = new MessageChannel();
+shouldBe("new MessageEvent('eventType', { ports: [channel.port1, channel.port2, channel.port2] }).ports[0]", "channel.port1");
+shouldBe("new MessageEvent('eventType', { ports: [channel.port1, channel.port2, channel.port2] }).ports[1]", "channel.port2");
+shouldBe("new MessageEvent('eventType', { ports: [channel.port1, channel.port2, channel.port2] }).ports[2]", "channel.port2");
+shouldBe("new MessageEvent('eventType', { ports: [] }).ports", "[]");
+shouldBe("new MessageEvent('eventType', { ports: undefined }).ports", "[]");
+shouldBe("new MessageEvent('eventType', { ports: null }).ports", "[]");
+
+// Invalid message ports.
+shouldThrow("new MessageEvent('eventType', { ports: [1, 2, 3] }).ports[2]");
+shouldThrow("new MessageEvent('eventType', { ports: test_object }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: document }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: false }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: true }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: '' }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: 'chocolate' }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: 12345 }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: 18446744073709551615 }).ports");
+shouldThrow("new MessageEvent('eventType', { ports: NaN }).ports");
+shouldThrow("new MessageEvent('eventType', { get ports() { return 123; } }).ports");
+shouldThrow("new MessageEvent('eventType', { get ports() { throw 'MessageEvent Error'; } })");
+// Note that valueOf() is not called, when the left hand side is evaluated.
+shouldThrow("new MessageEvent('eventType', { ports: {valueOf: function () { return [channel.port1, channel.port2, channel.port2]; } } }).ports[0]");
+
+// All initializers are passed.
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).bubbles", "true");
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).cancelable", "true");
+// FIXME(haraken): This fails because MessageEvent.data cannot handle ScriptValue.
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).data", "test_object");
+shouldBeEqualToString("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).origin", "wonderful");
+shouldBeEqualToString("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).lastEventId", "excellent");
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).source", "window");
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).ports[0]", "channel.port1");
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).ports[1]", "channel.port2");
+shouldBe("new MessageEvent('eventType', { bubbles: true, cancelable: true, data: test_object, origin: 'wonderful', lastEventId: 'excellent', source: window, ports: [channel.port1, channel.port2, channel.port2] }).ports[2]", "channel.port2");
+
+var successfullyParsed = true;
+</script>
+<script src="../../js/resources/js-test-post.js"></script>
+</body>
+</html>
index 7215a0b..3a13a9d 100644 (file)
@@ -81,6 +81,9 @@ BUGWK68048 : fast/events/constructors/page-transition-event-constructor.html = F
 BUGWK60877 SKIP : loader/navigation-while-deferring-loads.html = FAIL
 BUGWK60877 SKIP : loader/load-defer-resume-crash.html = FAIL
 
+// This will soon be fixed after implementing a MessageEvent constructor for V8.
+BUGWK68883 : fast/events/constructors/message-event-constructor.html = FAIL
+
 // CSS3 Selectors3 test suite
 BUGCR89468 : css3/selectors3 = PASS FAIL
 
index cad5f32..fe437c1 100644 (file)
@@ -1,3 +1,45 @@
+2011-09-27  Kentaro Hara  <haraken@chromium.org>
+
+        Implement a MessageEvent constructor for JSC
+        https://bugs.webkit.org/show_bug.cgi?id=68883
+
+        Reviewed by Adam Barth.
+
+        The spec for MessageEvent is here:
+        http://www.whatwg.org/specs/web-apps/current-work/#messageevent
+
+        Currently, some tests in fast/events/constructors/message-event-constructor.html
+        are failing or crashing in DRT, as we commented in the test file.
+        This is because MessageEvent.data is implemented as SerializedScriptValue,
+        and thus it cannot keep ScriptValue passed by JavaScript.
+        This is the same issue as the bug (https://bugs.webkit.org/show_bug.cgi?id=68345).
+        We will soon make a follow-up patch to fix these failures, after this
+        patch is landed.
+
+        Test: fast/events/constructors/message-event-constructor.html
+
+        * bindings/generic/EventConstructors.h: Added a definition for the MessageEvent constructor.
+        * bindings/js/JSDictionary.cpp:
+        (WebCore::JSDictionary::convertValue): Generates MessagePortArray from the list of message ports in the format of JSValues.
+        * bindings/js/JSDictionary.h:
+        * bindings/js/JSEventConstructors.cpp: Added #includes for MessageEvent.
+        * dom/MessageEvent.cpp:
+        (WebCore::MessageEventInit::MessageEventInit):
+        (WebCore::MessageEvent::MessageEvent):
+        (WebCore::MessageEvent::initMessageEvent):
+        * dom/MessageEvent.h: Added a definition for MessageEvent. Removed an extra leading spaces.
+        (WebCore::MessageEvent::create):
+        (WebCore::MessageEvent::origin):
+        (WebCore::MessageEvent::lastEventId):
+        (WebCore::MessageEvent::source):
+        (WebCore::MessageEvent::ports):
+        (WebCore::MessageEvent::dataType):
+        (WebCore::MessageEvent::dataAsSerializedScriptValue):
+        (WebCore::MessageEvent::dataAsString):
+        (WebCore::MessageEvent::dataAsBlob):
+        (WebCore::MessageEvent::dataAsArrayBuffer):
+        * dom/MessageEvent.idl: Makes MessageEvent constructible.
+
 2011-09-27  Eric Uhrhane  <ericu@chromium.org>
 
         [Chromium/FileWriter] race condition in FileWriter completion can lead to assert
index e23bf16..82acf72 100644 (file)
@@ -99,6 +99,17 @@ namespace WebCore {
         FILL_PROPERTY(reason) \
     DICTIONARY_END(CloseEvent)
 
+#define INSTANTIATE_INITIALIZING_CONSTRUCTOR_FOR_MESSAGE_EVENT(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
+    \
+    DICTIONARY_START(MessageEvent) \
+        FILL_PARENT_PROPERTIES(Event) \
+        FILL_PROPERTY(data) \
+        FILL_PROPERTY(origin) \
+        FILL_PROPERTY(lastEventId) \
+        FILL_PROPERTY(source) \
+        FILL_PROPERTY(ports) \
+    DICTIONARY_END(MessageEvent)
+
 
 #define INSTANTIATE_ALL_EVENT_INITIALIZING_CONSTRUCTORS(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
     INSTANTIATE_INITIALIZING_CONSTRUCTOR_FOR_EVENT(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
@@ -110,6 +121,7 @@ namespace WebCore {
     INSTANTIATE_INITIALIZING_CONSTRUCTOR_FOR_POP_STATE_EVENT(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
     INSTANTIATE_INITIALIZING_CONSTRUCTOR_FOR_ERROR_EVENT(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
     INSTANTIATE_INITIALIZING_CONSTRUCTOR_FOR_CLOSE_EVENT(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
+    INSTANTIATE_INITIALIZING_CONSTRUCTOR_FOR_MESSAGE_EVENT(DICTIONARY_START, DICTIONARY_END, FILL_PARENT_PROPERTIES, FILL_PROPERTY) \
 
 } // namespace WebCore
 
index 18bb307..58531f3 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2011 Apple Inc. All rights reserved.
  *
@@ -29,6 +28,7 @@
 
 #include "JSDOMWindow.h"
 #include "JSEventTarget.h"
+#include "JSMessagePortCustom.h"
 #include "JSNode.h"
 #include "SerializedScriptValue.h"
 #include "ScriptValue.h"
@@ -119,4 +119,9 @@ void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Node>& result)
     result = toNode(value);
 }
 
+void JSDictionary::convertValue(ExecState* exec, JSValue value, MessagePortArray& result)
+{
+    fillMessagePortArray(exec, value, result);
+}
+
 } // namespace WebCore
index 2da9239..7790d70 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef JSDictionary_h
 #define JSDictionary_h
 
+#include "MessagePort.h"
 #include <interpreter/CallFrame.h>
 #include <wtf/Forward.h>
 
@@ -71,6 +72,7 @@ private:
     static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<DOMWindow>& result);
     static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<EventTarget>& result);
     static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<Node>& result);
+    static void convertValue(JSC::ExecState*, JSC::JSValue, MessagePortArray& result);
 
     JSC::ExecState* m_exec;
     JSC::JSObject* m_initializerObject;
index 2ec3445..f65bfec 100644 (file)
 #include "JSErrorEvent.h"
 #include "JSEvent.h"
 #include "JSHashChangeEvent.h"
+#include "JSMessageEvent.h"
 #include "JSPageTransitionEvent.h"
 #include "JSPopStateEvent.h"
 #include "JSProgressEvent.h"
 #include "JSWebKitAnimationEvent.h"
+#include "MessageEvent.h"
 #include "PageTransitionEvent.h"
 #include "PopStateEvent.h"
 #include "ProgressEvent.h"
index 2731fa3..6b9564b 100644 (file)
 
 namespace WebCore {
 
+MessageEventInit::MessageEventInit()
+    : data(SerializedScriptValue::create())
+{
+}
+
 MessageEvent::MessageEvent()
     : m_dataType(DataTypeSerializedScriptValue)
     , m_dataAsSerializedScriptValue(SerializedScriptValue::create())
 {
 }
 
+MessageEvent::MessageEvent(const AtomicString& type, const MessageEventInit& initializer)
+    : Event(type, initializer)
+    , m_dataType(DataTypeSerializedScriptValue)
+    , m_dataAsSerializedScriptValue(initializer.data)
+    , m_origin(initializer.origin)
+    , m_lastEventId(initializer.lastEventId)
+    , m_source(initializer.source)
+    , m_ports(adoptPtr(new MessagePortArray(initializer.ports)))
+{
+}
+
 MessageEvent::MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray> ports)
     : Event(eventNames().messageEvent, false, false)
     , m_dataType(DataTypeSerializedScriptValue)
@@ -85,7 +101,7 @@ void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bo
 {
     if (dispatched())
         return;
-        
+
     initEvent(type, canBubble, cancelable);
 
     m_dataType = DataTypeSerializedScriptValue;
index ded8074..6ac4dde 100644 (file)
 
 namespace WebCore {
 
-    class DOMWindow;
-
-    class MessageEvent : public Event {
-    public:
-        static PassRefPtr<MessageEvent> create()
-        {
-            return adoptRef(new MessageEvent);
-        }
-        static PassRefPtr<MessageEvent> create(PassOwnPtr<MessagePortArray> ports, PassRefPtr<SerializedScriptValue> data = 0, const String& origin = "", const String& lastEventId = "", PassRefPtr<DOMWindow> source = 0)
-        {
-            return adoptRef(new MessageEvent(data, origin, lastEventId, source, ports));
-        }
-        static PassRefPtr<MessageEvent> create(const String& data)
-        {
-            return adoptRef(new MessageEvent(data));
-        }
-        static PassRefPtr<MessageEvent> create(PassRefPtr<Blob> data)
-        {
-            return adoptRef(new MessageEvent(data));
-        }
-        static PassRefPtr<MessageEvent> create(PassRefPtr<ArrayBuffer> 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>);
-
-        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).
-        void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort*);
-
-        virtual bool isMessageEvent() const;
-
-        enum DataType {
-            DataTypeSerializedScriptValue,
-            DataTypeString,
-            DataTypeBlob,
-            DataTypeArrayBuffer
-        };
-        DataType dataType() const { return m_dataType; }
-        SerializedScriptValue* dataAsSerializedScriptValue() const { return m_dataAsSerializedScriptValue.get(); }
-        String dataAsString() const { return m_dataAsString; }
-        Blob* dataAsBlob() const { return m_dataAsBlob.get(); }
-        ArrayBuffer* dataAsArrayBuffer() const { return m_dataAsArrayBuffer.get(); }
-
-    private:
-        MessageEvent();
-        MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
-        explicit MessageEvent(const String& data);
-        explicit MessageEvent(PassRefPtr<Blob> data);
-        explicit MessageEvent(PassRefPtr<ArrayBuffer> data);
-
-        DataType m_dataType;
-        RefPtr<SerializedScriptValue> m_dataAsSerializedScriptValue;
-        String m_dataAsString;
-        RefPtr<Blob> m_dataAsBlob;
-        RefPtr<ArrayBuffer> m_dataAsArrayBuffer;
-        String m_origin;
-        String m_lastEventId;
-        RefPtr<DOMWindow> m_source;
-        OwnPtr<MessagePortArray> m_ports;
+class DOMWindow;
+
+struct MessageEventInit : public EventInit {
+    MessageEventInit();
+
+    RefPtr<SerializedScriptValue> data;
+    String origin;
+    String lastEventId;
+    RefPtr<DOMWindow> source;
+    MessagePortArray ports;
+};
+
+class MessageEvent : public Event {
+public:
+    static PassRefPtr<MessageEvent> create()
+    {
+        return adoptRef(new MessageEvent);
+    }
+    static PassRefPtr<MessageEvent> create(PassOwnPtr<MessagePortArray> ports, PassRefPtr<SerializedScriptValue> data = 0, const String& origin = "", const String& lastEventId = "", PassRefPtr<DOMWindow> source = 0)
+    {
+        return adoptRef(new MessageEvent(data, origin, lastEventId, source, ports));
+    }
+    static PassRefPtr<MessageEvent> create(const String& data)
+    {
+        return adoptRef(new MessageEvent(data));
+    }
+    static PassRefPtr<MessageEvent> create(PassRefPtr<Blob> data)
+    {
+        return adoptRef(new MessageEvent(data));
+    }
+    static PassRefPtr<MessageEvent> create(PassRefPtr<ArrayBuffer> data)
+    {
+        return adoptRef(new MessageEvent(data));
+    }
+    static PassRefPtr<MessageEvent> create(const AtomicString& type, const MessageEventInit& initializer)
+    {
+        return adoptRef(new MessageEvent(type, initializer));
+    }
+    virtual ~MessageEvent();
+
+    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>);
+
+    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).
+    void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort*);
+
+    virtual bool isMessageEvent() const;
+
+    enum DataType {
+        DataTypeSerializedScriptValue,
+        DataTypeString,
+        DataTypeBlob,
+        DataTypeArrayBuffer
     };
+    DataType dataType() const { return m_dataType; }
+    SerializedScriptValue* dataAsSerializedScriptValue() const { return m_dataAsSerializedScriptValue.get(); }
+    String dataAsString() const { return m_dataAsString; }
+    Blob* dataAsBlob() const { return m_dataAsBlob.get(); }
+    ArrayBuffer* dataAsArrayBuffer() const { return m_dataAsArrayBuffer.get(); }
+
+private:
+    MessageEvent();
+    MessageEvent(const AtomicString&, const MessageEventInit&);
+    MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
+
+    explicit MessageEvent(const String& data);
+    explicit MessageEvent(PassRefPtr<Blob> data);
+    explicit MessageEvent(PassRefPtr<ArrayBuffer> data);
+
+    DataType m_dataType;
+    RefPtr<SerializedScriptValue> m_dataAsSerializedScriptValue;
+    String m_dataAsString;
+    RefPtr<Blob> m_dataAsBlob;
+    RefPtr<ArrayBuffer> m_dataAsArrayBuffer;
+    String m_origin;
+    String m_lastEventId;
+    RefPtr<DOMWindow> m_source;
+    OwnPtr<MessagePortArray> m_ports;
+};
 
 } // namespace WebCore
 
index 6bb2b65..1c56326 100644 (file)
@@ -28,7 +28,9 @@
 module events {
 
     interface [
-        NoStaticTables
+        NoStaticTables,
+        CanBeConstructed,
+        CustomConstructFunction
     ] MessageEvent : Event {
         readonly attribute DOMString origin;
         readonly attribute DOMString lastEventId;