[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75

oliver at apple.com oliver at apple.com
Thu Oct 29 20:40:40 UTC 2009


The following commit has been merged in the webkit-1.1 branch:
commit 0ef2c5b4893921c5dcd9263d43c3f6f7bfd7b2df
Author: oliver at apple.com <oliver at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Oct 7 02:06:03 2009 +0000

    It should be possible to post (clone) built-in JS objects to Workers
    https://bugs.webkit.org/show_bug.cgi?id=22878
    
    Reviewed by Gavin Barraclough.
    
    Implement object cloning semantics for postMessage.  Currently only
    a partial implementation of the spec -- cloning of File, FileList,
    ImageData, and RegExp were left out as they would have significantly
    increased patch size.
    
    Cloning requires multiple tree walks so we use a templated tree
    walk function, allowing us to share a single implementation for
    serialization, deserialization, and eventual destruction of the
    serialized object tree.
    
    Test: fast/dom/Window/window-postmessage-clone.html
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49214 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index aea99c9..0805eb6 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,23 @@
+2009-10-05  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        It should be possible to post (clone) built-in JS objects to Workers
+        https://bugs.webkit.org/show_bug.cgi?id=22878
+
+        Expose helpers to throw correct exceptions during object graph walk
+        used for cloning and add a helper function to create Date instances
+        without going through the JS Date constructor function.
+
+        * JavaScriptCore.exp:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * runtime/DateInstance.cpp:
+        (JSC::DateInstance::DateInstance):
+        * runtime/DateInstance.h:
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::createTypeError):
+        * runtime/ExceptionHelpers.h:
+
 2009-10-06  David Levin  <levin at chromium.org>
 
         Reviewed by Oliver Hunt.
diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp
index 0937b26..d94dcfa 100644
--- a/JavaScriptCore/JavaScriptCore.exp
+++ b/JavaScriptCore/JavaScriptCore.exp
@@ -104,6 +104,7 @@ __ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEE
 __ZN3JSC11ParserArena5resetEv
 __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE
 __ZN3JSC12DateInstance4infoE
+__ZN3JSC12DateInstanceC1EPNS_9ExecStateEd
 __ZN3JSC12JSGlobalData10ClientDataD2Ev
 __ZN3JSC12JSGlobalData12createLeakedEv
 __ZN3JSC12JSGlobalData12stopSamplingEv
@@ -141,7 +142,9 @@ __ZN3JSC14JSGlobalObjectD2Ev
 __ZN3JSC14JSGlobalObjectnwEmPNS_12JSGlobalDataE
 __ZN3JSC14SamplingThread4stopEv
 __ZN3JSC14SamplingThread5startEj
+__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
 __ZN3JSC14TimeoutChecker5resetEv
+__ZN3JSC15createTypeErrorEPNS_9ExecStateEPKc
 __ZN3JSC15JSWrapperObject12markChildrenERNS_9MarkStackE
 __ZN3JSC15toInt32SlowCaseEdRb
 __ZN3JSC16InternalFunction4infoE
@@ -171,7 +174,9 @@ __ZN3JSC20MarkedArgumentBuffer10slowAppendENS_7JSValueE
 __ZN3JSC23AbstractSamplingCounter4dumpEv
 __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE
+__ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE
 __ZN3JSC4Heap11objectCountEv
 __ZN3JSC4Heap14primaryHeapEndEv
 __ZN3JSC4Heap15recordExtraCostEm
@@ -213,6 +218,7 @@ __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE
 __ZN3JSC7CStringD1Ev
 __ZN3JSC7CStringaSERKS0_
 __ZN3JSC7JSArray4infoE
+__ZN3JSC7JSArray9setLengthEj
 __ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE
 __ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE
 __ZN3JSC7Profile10restoreAllEv
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
index 7fe6b34..f108b77 100644
--- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
+++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
@@ -245,7 +245,7 @@
 		BC18C3FC0E16F5CD00B34460 /* Deque.h in Headers */ = {isa = PBXBuildFile; fileRef = 5186111D0CC824830081412B /* Deque.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BC18C3FD0E16F5CD00B34460 /* DisallowCType.h in Headers */ = {isa = PBXBuildFile; fileRef = 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BC18C3FE0E16F5CD00B34460 /* dtoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 651F6413039D5B5F0078395C /* dtoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
+		BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BC18C4020E16F5CD00B34460 /* FastMalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E217BA08E7EECC0023E5F6 /* FastMalloc.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BC18C4030E16F5CD00B34460 /* Forward.h in Headers */ = {isa = PBXBuildFile; fileRef = 935AF46909E9D9DB00ACD1D8 /* Forward.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BC18C4040E16F5CD00B34460 /* FunctionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
diff --git a/JavaScriptCore/runtime/DateInstance.cpp b/JavaScriptCore/runtime/DateInstance.cpp
index 6b479ae..e727445 100644
--- a/JavaScriptCore/runtime/DateInstance.cpp
+++ b/JavaScriptCore/runtime/DateInstance.cpp
@@ -45,6 +45,13 @@ DateInstance::DateInstance(NonNullPassRefPtr<Structure> structure)
 {
 }
 
+DateInstance::DateInstance(ExecState* exec, double time)
+    : JSWrapperObject(exec->lexicalGlobalObject()->dateStructure())
+    , m_cache(0)
+{
+    setInternalValue(jsNumber(exec, timeClip(time)));
+}
+
 DateInstance::~DateInstance()
 {
     delete m_cache;
diff --git a/JavaScriptCore/runtime/DateInstance.h b/JavaScriptCore/runtime/DateInstance.h
index c8edc2f..eecbb76 100644
--- a/JavaScriptCore/runtime/DateInstance.h
+++ b/JavaScriptCore/runtime/DateInstance.h
@@ -31,6 +31,7 @@ namespace JSC {
 
     class DateInstance : public JSWrapperObject {
     public:
+        DateInstance(ExecState*, double);
         explicit DateInstance(NonNullPassRefPtr<Structure>);
         virtual ~DateInstance();
 
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp
index cc18b95..5bead90 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.cpp
+++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp
@@ -66,6 +66,11 @@ JSValue createStackOverflowError(ExecState* exec)
     return createError(exec, RangeError, "Maximum call stack size exceeded.");
 }
 
+JSValue createTypeError(ExecState* exec, const char* message)
+{
+    return createError(exec, TypeError, message);
+}
+
 JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock)
 {
     int startOffset = 0;
diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h
index 4c5bec1..e739d09 100644
--- a/JavaScriptCore/runtime/ExceptionHelpers.h
+++ b/JavaScriptCore/runtime/ExceptionHelpers.h
@@ -44,6 +44,7 @@ namespace JSC {
     
     JSValue createInterruptedExecutionException(JSGlobalData*);
     JSValue createStackOverflowError(ExecState*);
+    JSValue createTypeError(ExecState*, const char* message);
     JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*);
     JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull);
     JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*);
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 4404466..995db36 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2009-10-05  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        It should be possible to post (clone) built-in JS objects to Workers
+        https://bugs.webkit.org/show_bug.cgi?id=22878
+
+        Add a test for object cloning for postMessage, and update existing tests
+        to reflect the new cloning semantics.
+
+        * fast/dom/Window/window-postmessage-clone-expected.txt: Added.
+        * fast/dom/Window/window-postmessage-clone.html: Added.
+        * fast/events/init-events-expected.txt:
+        * fast/events/script-tests/init-events.js:
+        * fast/workers/resources/use-machine-stack.js:
+
 2009-10-06  Dave Hyatt  <hyatt at apple.com>
 
         Reviewed by Adam Roben.
diff --git a/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt b/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt
new file mode 100644
index 0000000..eded697
--- /dev/null
+++ b/LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt
@@ -0,0 +1,22 @@
+CONSOLE MESSAGE: line 54: RangeError: Maximum call stack size exceeded.
+Tests that we clone object hierarchies
+PASS: 'postMessage(cyclicObject)' threw ReferenceError: Can't find variable: cyclicObject
+PASS: 'postMessage(cyclicObject)' threw TypeError: Cannot post cyclic structures.
+PASS: 'postMessage(cyclicArray)' threw TypeError: Cannot post cyclic structures.
+PASS: 'postMessage(reallyDeepArray)' threw RangeError: Maximum call stack size exceeded.
+PASS: 'postMessage(window)' threw TypeError: Cannot post cyclic structures.
+PASS: eventData is null of type object
+PASS: eventData is undefined of type undefined
+PASS: eventData is 1 of type number
+PASS: eventData is true of type boolean
+PASS: eventData is 1 of type string
+PASS: eventData is [object Object] of type object
+PASS: eventData is [object Object] of type object
+PASS: eventData is of type object
+PASS: eventData is 1,2,3 of type object
+PASS: eventData is ,,1 of type object
+PASS: eventData is null of type object
+PASS: eventData is Wed Dec 31 1969 16:00:00 GMT-0800 (PST) of type object
+PASS: eventData is of type object
+PASS: eventData is done of type string
+
diff --git a/LayoutTests/fast/dom/Window/window-postmessage-clone.html b/LayoutTests/fast/dom/Window/window-postmessage-clone.html
new file mode 100644
index 0000000..e9ab1e5
--- /dev/null
+++ b/LayoutTests/fast/dom/Window/window-postmessage-clone.html
@@ -0,0 +1,118 @@
+<html>
+<head></head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var console = document.getElementById("console");
+
+var messages = [];
+
+function equal(actual, expected)
+{
+    if (typeof actual !== typeof expected)
+        return false;
+    if (actual === expected)
+        return true;
+    if ((actual instanceof Date) || (expected instanceof Date)) {
+        if ((actual instanceof Date) && (expected instanceof Date))
+            return (expected instanceof Date) && actual.getTime() == expected.getTime();
+        return false;
+    }
+    if (Array.isArray(actual) || Array.isArray(expected)) {
+        if (!Array.isArray(actual) || !Array.isArray(expected))
+            return false;
+        if (actual.length != expected.length)
+            return false;
+        for (var i = 0; i < actual.length; i++) {
+            if ((i in actual) ^ (i in expected))
+                return false;
+            if (!equal(actual[i], expected[i]))
+                return false;
+        }
+        return true;
+    }
+    var keys = Object.keys(actual);
+    if (!equal(keys, Object.keys(expected)))
+        return false;
+    for (var i = 0; i < keys.length; i++)
+        if (!equal(actual[i], expected[i]))
+            return false;
+    return true;
+}
+
+function shouldBe(actual, expected)
+{
+    var actualValue = eval(actual);
+    var expectedValue = eval(expected);
+    if (equal(actualValue, expectedValue))
+        console.innerHTML += "PASS: " + actual + " is " + expectedValue + " of type " + typeof actualValue + "<br>";
+    else
+        console.innerHTML += "FAIL: " + actual + " is " + actualValue + " should be " + expectedValue + " of type " + typeof expectedValue + "<br>";
+}
+
+function onmessage(evt) {
+    eventData = evt.data
+    shouldBe("eventData", messages.shift());
+
+    if (evt.data == 'done' && window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+
+window.addEventListener('message', onmessage, false);
+
+function tryPostMessage(message, shouldThrow, expected) {
+    try {
+        var value = eval(message);
+        postMessage(value, "*");
+        if (shouldThrow)
+            console.innerHTML += "FAIL: 'postMessage("+message+")' should throw but didn't<br>";
+        messages.push(expected || message);
+    } catch(e) {
+        if (shouldThrow)
+            console.innerHTML += "PASS: 'postMessage("+message+")' threw " + e + "<br>";
+        else
+            console.innerHTML += "FAIL: 'postMessage("+message+")' should not throw but threw " + e + "<br>";
+    }
+}
+
+document.getElementById("description").innerHTML = "Tests that we clone object hierarchies";
+
+tryPostMessage('null');
+tryPostMessage('undefined');
+tryPostMessage('1');
+tryPostMessage('true');
+tryPostMessage('"1"');
+tryPostMessage('({})');
+tryPostMessage('({a:1})');
+tryPostMessage('[]');
+tryPostMessage('[1,2,3]');
+tryPostMessage('[,,1]');
+tryPostMessage('(function(){})', false, 'null');
+tryPostMessage('new Date(0)');
+tryPostMessage('cyclicObject', true);
+cyclicObject={};
+cyclicObject.self = cyclicObject;
+tryPostMessage('cyclicObject', true);
+cyclicArray=[];
+cyclicArray[0] = cyclicArray;
+tryPostMessage('cyclicArray', true);
+deepArray=[];
+for (var i = 0; i < 10000; i++)
+    deepArray=[deepArray];
+tryPostMessage('deepArray');
+reallyDeepArray=[];
+for (var i = 0; i < 100000; i++)
+    reallyDeepArray=[reallyDeepArray];
+tryPostMessage('reallyDeepArray', true);
+tryPostMessage('window', true);
+
+tryPostMessage('"done"');
+</script>
+</body>
+</html>
diff --git a/LayoutTests/fast/events/init-events-expected.txt b/LayoutTests/fast/events/init-events-expected.txt
index c87416b..b682a33 100644
--- a/LayoutTests/fast/events/init-events-expected.txt
+++ b/LayoutTests/fast/events/init-events-expected.txt
@@ -45,7 +45,7 @@ PASS testInitEvent('Message', '"a", true, false, "b", "c", "d", window, null').b
 PASS testInitEvent('Message', '"a", false, false, "b", "c", "d", window, null').cancelable is false
 PASS testInitEvent('Message', '"a", false, true, "b", "c", "d", window, null').cancelable is true
 PASS testInitEvent('Message', '"a", false, false, "b", "c", "d", window, null').data is 'b'
-PASS testInitEvent('Message', '"a", false, false, null, "c", "d", window, null').data is 'null'
+PASS testInitEvent('Message', '"a", false, false, null, "c", "d", window, null').data is null
 PASS testInitEvent('Message', '"a", false, false, "b", "c", "d", window, null').origin is 'c'
 PASS testInitEvent('Message', '"a", false, false, "b", null, "d", window, null').origin is 'null'
 PASS testInitEvent('Message', '"a", false, false, "b", "c", "d", window, null').lastEventId is 'd'
diff --git a/LayoutTests/fast/events/script-tests/init-events.js b/LayoutTests/fast/events/script-tests/init-events.js
index 34fa66f..e2f3d1f 100644
--- a/LayoutTests/fast/events/script-tests/init-events.js
+++ b/LayoutTests/fast/events/script-tests/init-events.js
@@ -56,7 +56,7 @@ shouldBe("testInitEvent('Message', '\"a\", true, false, \"b\", \"c\", \"d\", win
 shouldBe("testInitEvent('Message', '\"a\", false, false, \"b\", \"c\", \"d\", window, null').cancelable", "false");
 shouldBe("testInitEvent('Message', '\"a\", false, true, \"b\", \"c\", \"d\", window, null').cancelable", "true");
 shouldBe("testInitEvent('Message', '\"a\", false, false, \"b\", \"c\", \"d\", window, null').data", "'b'");
-shouldBe("testInitEvent('Message', '\"a\", false, false, null, \"c\", \"d\", window, null').data", "'null'");
+shouldBe("testInitEvent('Message', '\"a\", false, false, null, \"c\", \"d\", window, null').data", "null");
 shouldBe("testInitEvent('Message', '\"a\", false, false, \"b\", \"c\", \"d\", window, null').origin", "'c'");
 shouldBe("testInitEvent('Message', '\"a\", false, false, \"b\", null, \"d\", window, null').origin", "'null'");
 shouldBe("testInitEvent('Message', '\"a\", false, false, \"b\", \"c\", \"d\", window, null').lastEventId", "'d'");
diff --git a/LayoutTests/fast/workers/resources/use-machine-stack.js b/LayoutTests/fast/workers/resources/use-machine-stack.js
index 1501ea9..b3f8dc1 100644
--- a/LayoutTests/fast/workers/resources/use-machine-stack.js
+++ b/LayoutTests/fast/workers/resources/use-machine-stack.js
@@ -16,6 +16,6 @@ try {
     try {
         g();
     } catch (ex) {
-        postMessage(ex);
+        postMessage(ex.toString());
     }
 }
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 57294f7..fe593ee 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,190 @@
+2009-10-05  Oliver Hunt  <oliver at apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        It should be possible to post (clone) built-in JS objects to Workers
+        https://bugs.webkit.org/show_bug.cgi?id=22878
+
+        Implement object cloning semantics for postMessage.  Currently only
+        a partial implementation of the spec -- cloning of File, FileList,
+        ImageData, and RegExp were left out as they would have significantly
+        increased patch size.
+
+        Cloning requires multiple tree walks so we use a templated tree
+        walk function, allowing us to share a single implementation for
+        serialization, deserialization, and eventual destruction of the
+        serialized object tree.
+
+        Test: fast/dom/Window/window-postmessage-clone.html
+
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::postMessage):
+        * bindings/js/JSMessageEventCustom.cpp:
+        (WebCore::JSMessageEvent::initMessageEvent):
+        * bindings/js/JSMessagePortCustom.h:
+        (WebCore::handlePostMessage):
+        * bindings/js/SerializedScriptValue.cpp: Added.
+        (WebCore::SerializedObject::set):
+        (WebCore::SerializedObject::names):
+        (WebCore::SerializedObject::values):
+        (WebCore::SerializedObject::create):
+        (WebCore::SerializedObject::clear):
+        (WebCore::SerializedObject::SerializedObject):
+        (WebCore::SerializedArray::setIndex):
+        (WebCore::SerializedArray::canDoFastRead):
+        (WebCore::SerializedArray::getIndex):
+        (WebCore::SerializedArray::getSparseIndex):
+        (WebCore::SerializedArray::length):
+        (WebCore::SerializedArray::create):
+        (WebCore::SerializedArray::clear):
+        (WebCore::SerializedArray::SerializedArray):
+        (WebCore::SerializedScriptValueData::SerializedScriptValueData):
+        (WebCore::SharedSerializedData::asArray):
+        (WebCore::SharedSerializedData::asObject):
+        (WebCore::):
+        (WebCore::walk):
+        (WebCore::BaseWalker::BaseWalker):
+        (WebCore::BaseWalker::shouldTerminate):
+        (WebCore::BaseWalker::ticksUntilNextCheck):
+        (WebCore::BaseWalker::didTimeOut):
+        (WebCore::BaseWalker::throwStackOverflow):
+        (WebCore::BaseWalker::throwInterruptedException):
+        (WebCore::SerializingTreeWalker::SerializingTreeWalker):
+        (WebCore::SerializingTreeWalker::null):
+        (WebCore::SerializingTreeWalker::isArray):
+        (WebCore::SerializingTreeWalker::isObject):
+        (WebCore::SerializingTreeWalker::asInputArray):
+        (WebCore::SerializingTreeWalker::asInputObject):
+        (WebCore::SerializingTreeWalker::createOutputArray):
+        (WebCore::SerializingTreeWalker::createOutputObject):
+        (WebCore::SerializingTreeWalker::length):
+        (WebCore::SerializingTreeWalker::canDoFastRead):
+        (WebCore::SerializingTreeWalker::getIndex):
+        (WebCore::SerializingTreeWalker::getSparseIndex):
+        (WebCore::SerializingTreeWalker::getProperty):
+        (WebCore::SerializingTreeWalker::convertIfTerminal):
+        (WebCore::SerializingTreeWalker::getPropertyNames):
+        (WebCore::SerializingTreeWalker::putIndex):
+        (WebCore::SerializingTreeWalker::putProperty):
+        (WebCore::SerializingTreeWalker::startArray):
+        (WebCore::SerializingTreeWalker::endArray):
+        (WebCore::SerializingTreeWalker::startObject):
+        (WebCore::SerializingTreeWalker::endObject):
+        (WebCore::SerializedScriptValueData::serialize):
+        (WebCore::DeserializingTreeWalker::DeserializingTreeWalker):
+        (WebCore::DeserializingTreeWalker::null):
+        (WebCore::DeserializingTreeWalker::isArray):
+        (WebCore::DeserializingTreeWalker::isObject):
+        (WebCore::DeserializingTreeWalker::asInputArray):
+        (WebCore::DeserializingTreeWalker::asInputObject):
+        (WebCore::DeserializingTreeWalker::createOutputArray):
+        (WebCore::DeserializingTreeWalker::createOutputObject):
+        (WebCore::DeserializingTreeWalker::length):
+        (WebCore::DeserializingTreeWalker::canDoFastRead):
+        (WebCore::DeserializingTreeWalker::getIndex):
+        (WebCore::DeserializingTreeWalker::getSparseIndex):
+        (WebCore::DeserializingTreeWalker::getProperty):
+        (WebCore::DeserializingTreeWalker::convertIfTerminal):
+        (WebCore::DeserializingTreeWalker::getPropertyNames):
+        (WebCore::DeserializingTreeWalker::putIndex):
+        (WebCore::DeserializingTreeWalker::putProperty):
+        (WebCore::DeserializingTreeWalker::startArray):
+        (WebCore::DeserializingTreeWalker::endArray):
+        (WebCore::DeserializingTreeWalker::startObject):
+        (WebCore::DeserializingTreeWalker::endObject):
+        (WebCore::SerializedScriptValueData::deserialize):
+        (WebCore::TeardownTreeWalker::shouldTerminate):
+        (WebCore::TeardownTreeWalker::ticksUntilNextCheck):
+        (WebCore::TeardownTreeWalker::didTimeOut):
+        (WebCore::TeardownTreeWalker::throwStackOverflow):
+        (WebCore::TeardownTreeWalker::throwInterruptedException):
+        (WebCore::TeardownTreeWalker::null):
+        (WebCore::TeardownTreeWalker::isArray):
+        (WebCore::TeardownTreeWalker::isObject):
+        (WebCore::TeardownTreeWalker::asInputArray):
+        (WebCore::TeardownTreeWalker::asInputObject):
+        (WebCore::TeardownTreeWalker::createOutputArray):
+        (WebCore::TeardownTreeWalker::createOutputObject):
+        (WebCore::TeardownTreeWalker::length):
+        (WebCore::TeardownTreeWalker::canDoFastRead):
+        (WebCore::TeardownTreeWalker::getIndex):
+        (WebCore::TeardownTreeWalker::getSparseIndex):
+        (WebCore::TeardownTreeWalker::getProperty):
+        (WebCore::TeardownTreeWalker::convertIfTerminal):
+        (WebCore::TeardownTreeWalker::getPropertyNames):
+        (WebCore::TeardownTreeWalker::putIndex):
+        (WebCore::TeardownTreeWalker::putProperty):
+        (WebCore::TeardownTreeWalker::startArray):
+        (WebCore::TeardownTreeWalker::endArray):
+        (WebCore::TeardownTreeWalker::startObject):
+        (WebCore::TeardownTreeWalker::endObject):
+        (WebCore::SerializedScriptValueData::tearDownSerializedData):
+        * bindings/js/SerializedScriptValue.h: Added.
+        (WebCore::SharedSerializedData::~SharedSerializedData):
+        (WebCore::SerializedScriptValueData::):
+        (WebCore::SerializedScriptValueData::type):
+        (WebCore::SerializedScriptValueData::~SerializedScriptValueData):
+        (WebCore::SerializedScriptValueData::SerializedScriptValueData):
+        (WebCore::SerializedScriptValueData::asImmediate):
+        (WebCore::SerializedScriptValueData::asDouble):
+        (WebCore::SerializedScriptValueData::asString):
+        (WebCore::SerializedScriptValueData::asObject):
+        (WebCore::SerializedScriptValueData::asArray):
+        (WebCore::SerializedScriptValueData::operator bool ):
+        (WebCore::SerializedScriptValueData::release):
+        (WebCore::SerializedScriptValue::create):
+        (WebCore::SerializedScriptValue::release):
+        (WebCore::SerializedScriptValue::toString):
+        (WebCore::SerializedScriptValue::deserialize):
+        (WebCore::SerializedScriptValue::~SerializedScriptValue):
+        (WebCore::SerializedScriptValue::SerializedScriptValue):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        * bindings/scripts/CodeGeneratorObjC.pm:
+        * dom/MessageEvent.cpp:
+        (WebCore::MessageEvent::MessageEvent):
+        (WebCore::MessageEvent::initMessageEvent):
+        * dom/MessageEvent.h:
+        (WebCore::MessageEvent::create):
+        (WebCore::MessageEvent::data):
+        * dom/MessageEvent.idl:
+        * dom/MessagePort.cpp:
+        (WebCore::MessagePort::postMessage):
+        * dom/MessagePort.h:
+        * dom/MessagePortChannel.cpp:
+        (WebCore::MessagePortChannel::EventData::create):
+        (WebCore::MessagePortChannel::EventData::EventData):
+        * dom/MessagePortChannel.h:
+        (WebCore::MessagePortChannel::EventData::message):
+        * page/DOMWindow.cpp:
+        (WebCore::PostMessageTimer::PostMessageTimer):
+        (WebCore::DOMWindow::postMessage):
+        * page/DOMWindow.h:
+        * page/DOMWindow.idl:
+        * page/EventSource.cpp:
+        (WebCore::EventSource::createMessageEvent):
+        * websockets/WebSocket.cpp:
+        (WebCore::WebSocket::didReceiveMessage):
+        * workers/DedicatedWorkerContext.cpp:
+        (WebCore::DedicatedWorkerContext::postMessage):
+        * workers/DedicatedWorkerContext.h:
+        * workers/DedicatedWorkerContext.idl:
+        * workers/Worker.cpp:
+        (WebCore::Worker::postMessage):
+        * workers/Worker.h:
+        * workers/Worker.idl:
+        * workers/WorkerContextProxy.h:
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::MessageWorkerContextTask::create):
+        (WebCore::MessageWorkerContextTask::MessageWorkerContextTask):
+        (WebCore::MessageWorkerTask::create):
+        (WebCore::MessageWorkerTask::MessageWorkerTask):
+        (WebCore::WorkerMessagingProxy::postMessageToWorkerObject):
+        (WebCore::WorkerMessagingProxy::postMessageToWorkerContext):
+        * workers/WorkerMessagingProxy.h:
+        * workers/WorkerObjectProxy.h:
+
 2009-10-06  Adam Barth  <abarth at webkit.org>
 
         Unreviewed build fix for Windows.
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index ba06270..f81aae8 100644
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -29671,6 +29671,14 @@
 					>
 				</File>
 				<File
+					RelativePath="..\bindings\js\SerializedScriptValue.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\bindings\js\SerializedScriptValue.h"
+					>
+				</File>
+				<File
 					RelativePath="..\bindings\js\StringSourceProvider.h"
 					>
 				</File>
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 23c58d4..3f74406 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -2355,6 +2355,8 @@
 		A71878900B2D04AC00A16ECE /* DragControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A718788F0B2D04AC00A16ECE /* DragControllerMac.mm */; };
 		A7352C190B1BB89D00A986D0 /* RenderSVGBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7352C170B1BB89D00A986D0 /* RenderSVGBlock.cpp */; };
 		A7352C1A0B1BB89D00A986D0 /* RenderSVGBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = A7352C180B1BB89D00A986D0 /* RenderSVGBlock.h */; };
+		A75E497610752ACB00C9B896 /* SerializedScriptValue.h in Headers */ = {isa = PBXBuildFile; fileRef = A75E497410752ACB00C9B896 /* SerializedScriptValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		A75E497710752ACB00C9B896 /* SerializedScriptValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75E497510752ACB00C9B896 /* SerializedScriptValue.cpp */; };
 		A75E8B880E1DE2D6007F2481 /* FEBlend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75E8B800E1DE2D6007F2481 /* FEBlend.cpp */; };
 		A75E8B890E1DE2D6007F2481 /* FEBlend.h in Headers */ = {isa = PBXBuildFile; fileRef = A75E8B810E1DE2D6007F2481 /* FEBlend.h */; };
 		A75E8B8A0E1DE2D6007F2481 /* FEColorMatrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75E8B820E1DE2D6007F2481 /* FEColorMatrix.cpp */; };
@@ -7542,6 +7544,8 @@
 		A718788F0B2D04AC00A16ECE /* DragControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DragControllerMac.mm; sourceTree = "<group>"; };
 		A7352C170B1BB89D00A986D0 /* RenderSVGBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGBlock.cpp; sourceTree = "<group>"; };
 		A7352C180B1BB89D00A986D0 /* RenderSVGBlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderSVGBlock.h; sourceTree = "<group>"; };
+		A75E497410752ACB00C9B896 /* SerializedScriptValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SerializedScriptValue.h; sourceTree = "<group>"; };
+		A75E497510752ACB00C9B896 /* SerializedScriptValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerializedScriptValue.cpp; sourceTree = "<group>"; };
 		A75E8B800E1DE2D6007F2481 /* FEBlend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FEBlend.cpp; path = filters/FEBlend.cpp; sourceTree = "<group>"; };
 		A75E8B810E1DE2D6007F2481 /* FEBlend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FEBlend.h; path = filters/FEBlend.h; sourceTree = "<group>"; };
 		A75E8B820E1DE2D6007F2481 /* FEColorMatrix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FEColorMatrix.cpp; path = filters/FEColorMatrix.cpp; sourceTree = "<group>"; };
@@ -14227,6 +14231,8 @@
 				65488D6A0DD5A83D009D83B2 /* StringSourceProvider.h */,
 				E1A643FC0EC097A000779668 /* WorkerScriptController.cpp */,
 				E1A643F10EC0972500779668 /* WorkerScriptController.h */,
+				A75E497410752ACB00C9B896 /* SerializedScriptValue.h */,
+				A75E497510752ACB00C9B896 /* SerializedScriptValue.cpp */,
 			);
 			path = js;
 			sourceTree = "<group>";
@@ -17953,6 +17959,7 @@
 				BC9462D8107A7B4C00857193 /* BeforeLoadEvent.h in Headers */,
 				BC946348107A936600857193 /* JSBeforeLoadEvent.h in Headers */,
 				97BC63B91076C97F002C2142 /* PolicyCheck.h in Headers */,
+				A75E497610752ACB00C9B896 /* SerializedScriptValue.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -20073,6 +20080,7 @@
 				979F43D31075E44A0000F83B /* RedirectScheduler.cpp in Sources */,
 				BC946346107A934B00857193 /* JSBeforeLoadEvent.cpp in Sources */,
 				97BC63B81076C97F002C2142 /* PolicyCheck.cpp in Sources */,
+				A75E497710752ACB00C9B896 /* SerializedScriptValue.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 6a66a4d..47339d4 100644
--- a/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -79,6 +79,7 @@
 #include "RegisteredEventListener.h"
 #include "ScheduledAction.h"
 #include "ScriptController.h"
+#include "SerializedScriptValue.h"
 #include "Settings.h"
 #include "SharedWorkerRepository.h"
 #include "WindowFeatures.h"
@@ -952,7 +953,7 @@ JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args)
     DOMWindow* window = impl();
 
     DOMWindow* source = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
-    String message = args.at(0).toString(exec);
+    PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, args.at(0));
 
     if (exec->hadException())
         return jsUndefined();
diff --git a/WebCore/bindings/js/JSMessageEventCustom.cpp b/WebCore/bindings/js/JSMessageEventCustom.cpp
index 4c61c04..2e7b2d0 100644
--- a/WebCore/bindings/js/JSMessageEventCustom.cpp
+++ b/WebCore/bindings/js/JSMessageEventCustom.cpp
@@ -59,7 +59,7 @@ JSC::JSValue JSMessageEvent::initMessageEvent(JSC::ExecState* exec, const JSC::A
     const UString& typeArg = args.at(0).toString(exec);
     bool canBubbleArg = args.at(1).toBoolean(exec);
     bool cancelableArg = args.at(2).toBoolean(exec);
-    const UString& dataArg = args.at(3).toString(exec);
+    PassRefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(exec, args.at(3));
     const UString& originArg = args.at(4).toString(exec);
     const UString& lastEventIdArg = args.at(5).toString(exec);
     DOMWindow* sourceArg = toDOMWindow(args.at(6));
diff --git a/WebCore/bindings/js/JSMessagePortCustom.h b/WebCore/bindings/js/JSMessagePortCustom.h
index 7e90943..17b1eae 100644
--- a/WebCore/bindings/js/JSMessagePortCustom.h
+++ b/WebCore/bindings/js/JSMessagePortCustom.h
@@ -49,7 +49,7 @@ namespace WebCore {
     template <typename T>
     inline JSC::JSValue handlePostMessage(JSC::ExecState* exec, const JSC::ArgList& args, T* impl)
     {
-        String message = args.at(0).toString(exec);
+        PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, args.at(0));
         MessagePortArray portArray;
         fillMessagePortArray(exec, args.at(1), portArray);
         if (exec->hadException())
diff --git a/WebCore/bindings/js/SerializedScriptValue.cpp b/WebCore/bindings/js/SerializedScriptValue.cpp
new file mode 100644
index 0000000..ab97f2f
--- /dev/null
+++ b/WebCore/bindings/js/SerializedScriptValue.cpp
@@ -0,0 +1,833 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include "SerializedScriptValue.h"
+
+#include <runtime/DateInstance.h>
+#include <runtime/ExceptionHelpers.h>
+#include <runtime/PropertyNameArray.h>
+#include <wtf/HashTraits.h>
+#include <wtf/Vector.h>
+
+using namespace JSC;
+
+namespace WebCore
+{
+
+class SerializedObject : public SharedSerializedData
+{
+public:
+    typedef Vector<RefPtr<StringImpl> > PropertyNameList;
+    typedef Vector<SerializedScriptValueData> ValueList;
+    void set(const Identifier& propertyName, const SerializedScriptValueData& value)
+    {
+        ASSERT(m_names.size() == m_values.size());
+        m_names.append(String(propertyName.ustring()).crossThreadString().impl());
+        m_values.append(value);
+    }
+    PropertyNameList& names() { return m_names; }
+    ValueList& values() { return m_values; }
+    static PassRefPtr<SerializedObject> create()
+    {
+        return adoptRef(new SerializedObject);
+    }
+    void clear()
+    {
+        m_names.clear();
+        m_values.clear();
+    }
+private:
+    SerializedObject() { }
+    PropertyNameList m_names;
+    ValueList m_values;
+};
+
+class SerializedArray : public SharedSerializedData
+{
+    typedef HashMap<unsigned, SerializedScriptValueData, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > SparseMap;
+public:
+    void setIndex(unsigned index, const SerializedScriptValueData& value)
+    {
+        ASSERT(index < m_length);
+        if (index == m_compactStorage.size())
+            m_compactStorage.append(value);
+        else
+            m_sparseStorage.set(index, value);
+    }
+
+    bool canDoFastRead(unsigned index) const
+    {
+        ASSERT(index < m_length);
+        return index < m_compactStorage.size();
+    }
+
+    const SerializedScriptValueData& getIndex(unsigned index)
+    {
+        ASSERT(index < m_compactStorage.size());
+        return m_compactStorage[index];
+    }
+
+    SerializedScriptValueData getSparseIndex(unsigned index, bool& hasIndex)
+    {
+        ASSERT(index >= m_compactStorage.size());
+        ASSERT(index < m_length);
+        SparseMap::iterator iter = m_sparseStorage.find(index);
+        if (iter == m_sparseStorage.end()) {
+            hasIndex = false;
+            return SerializedScriptValueData();
+        }
+        hasIndex = true;
+        return iter->second;
+    }
+
+    unsigned length() const
+    {
+        return m_length;
+    }
+
+    static PassRefPtr<SerializedArray> create(unsigned length)
+    {
+        return adoptRef(new SerializedArray(length));
+    }
+
+    void clear()
+    {
+        m_compactStorage.clear();
+        m_sparseStorage.clear();
+        m_length = 0;
+    }
+private:
+    SerializedArray(unsigned length)
+        : m_length(length)
+    {
+    }
+
+    Vector<SerializedScriptValueData> m_compactStorage;
+    SparseMap m_sparseStorage;
+    unsigned m_length;
+};
+
+SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedObject> data)
+    : m_type(ObjectType)
+    , m_sharedData(data)
+{
+}
+
+SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedArray> data)
+    : m_type(ArrayType)
+    , m_sharedData(data)
+{
+}
+
+SerializedArray* SharedSerializedData::asArray()
+{
+    return static_cast<SerializedArray*>(this);
+}
+
+SerializedObject* SharedSerializedData::asObject()
+{
+    return static_cast<SerializedObject*>(this);
+}
+
+static const unsigned maximumFilterRecursion = 40000;
+enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
+    ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
+template <typename TreeWalker> typename TreeWalker::OutputType walk(TreeWalker& context, typename TreeWalker::InputType in)
+{
+    typedef typename TreeWalker::InputObject InputObject;
+    typedef typename TreeWalker::InputArray InputArray;
+    typedef typename TreeWalker::OutputObject OutputObject;
+    typedef typename TreeWalker::OutputArray OutputArray;
+    typedef typename TreeWalker::InputType InputType;
+    typedef typename TreeWalker::OutputType OutputType;
+    typedef typename TreeWalker::PropertyList PropertyList;
+
+    Vector<uint32_t, 16> indexStack;
+    Vector<uint32_t, 16> lengthStack;
+    Vector<PropertyList, 16> propertyStack;
+    Vector<InputObject, 16> inputObjectStack;
+    Vector<InputArray, 16> inputArrayStack;
+    Vector<OutputObject, 16> outputObjectStack;
+    Vector<OutputArray, 16> outputArrayStack;
+    Vector<WalkerState, 16> stateStack;
+    WalkerState state = StateUnknown;
+    InputType inValue = in;
+    OutputType outValue = context.null();
+
+    unsigned tickCount = context.ticksUntilNextCheck();
+    while (1) {
+        switch (state) {
+            arrayStartState:
+            case ArrayStartState: {
+                ASSERT(context.isArray(inValue));
+                if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) {
+                    context.throwStackOverflow();
+                    return context.null();
+                }
+
+                InputArray inArray = context.asInputArray(inValue);
+                unsigned length = context.length(inArray);
+                OutputArray outArray = context.createOutputArray(length);
+                if (!context.startArray(inArray, outArray))
+                    return context.null();
+                inputArrayStack.append(inArray);
+                outputArrayStack.append(outArray);
+                indexStack.append(0);
+                lengthStack.append(length);
+                // fallthrough
+            }
+            arrayStartVisitMember:
+            case ArrayStartVisitMember: {
+                if (!--tickCount) {
+                    if (context.didTimeOut()) {
+                        context.throwInterruptedException();
+                        return context.null();
+                    }
+                    tickCount = context.ticksUntilNextCheck();
+                }
+
+                InputArray array = inputArrayStack.last();
+                uint32_t index = indexStack.last();
+                if (index == lengthStack.last()) {
+                    InputArray inArray = inputArrayStack.last();
+                    OutputArray outArray = outputArrayStack.last();
+                    context.endArray(inArray, outArray);
+                    outValue = outArray;
+                    inputArrayStack.removeLast();
+                    outputArrayStack.removeLast();
+                    indexStack.removeLast();
+                    lengthStack.removeLast();
+                    break;
+                }
+                if (context.canDoFastRead(array, index))
+                    inValue = context.getIndex(array, index);
+                else {
+                    bool hasIndex = false;
+                    inValue = context.getSparseIndex(array, index, hasIndex);
+                    if (!hasIndex) {
+                        indexStack.last()++;
+                        goto arrayStartVisitMember;
+                    }
+                }
+
+                if (OutputType transformed = context.convertIfTerminal(inValue))
+                    outValue = transformed;
+                else {
+                    stateStack.append(ArrayEndVisitMember);
+                    goto stateUnknown;
+                }
+                // fallthrough
+            }
+            case ArrayEndVisitMember: {
+                OutputArray outArray = outputArrayStack.last();
+                context.putProperty(outArray, indexStack.last(), outValue);
+                indexStack.last()++;
+                goto arrayStartVisitMember;
+            }
+            objectStartState:
+            case ObjectStartState: {
+                ASSERT(context.isObject(inValue));
+                if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) {
+                    context.throwStackOverflow();
+                    return context.null();
+                }
+                InputObject inObject = context.asInputObject(inValue);
+                OutputObject outObject = context.createOutputObject();
+                if (!context.startObject(inObject, outObject))
+                    return context.null();
+                inputObjectStack.append(inObject);
+                outputObjectStack.append(outObject);
+                indexStack.append(0);
+                context.getPropertyNames(inObject, propertyStack);
+                // fallthrough
+            }
+            objectStartVisitMember:
+            case ObjectStartVisitMember: {
+                if (!--tickCount) {
+                    if (context.didTimeOut()) {
+                        context.throwInterruptedException();
+                        return context.null();
+                    }
+                    tickCount = context.ticksUntilNextCheck();
+                }
+
+                InputObject object = inputObjectStack.last();
+                uint32_t index = indexStack.last();
+                PropertyList& properties = propertyStack.last();
+                if (index == properties.size()) {
+                    InputObject inObject = inputObjectStack.last();
+                    OutputObject outObject = outputObjectStack.last();
+                    context.endObject(inObject, outObject);
+                    outValue = outObject;
+                    inputObjectStack.removeLast();
+                    outputObjectStack.removeLast();
+                    indexStack.removeLast();
+                    propertyStack.removeLast();
+                    break;
+                }
+                inValue = context.getProperty(object, properties[index], index);
+
+                if (context.shouldTerminate())
+                    return context.null();
+
+                if (OutputType transformed = context.convertIfTerminal(inValue))
+                    outValue = transformed;
+                else {
+                    stateStack.append(ObjectEndVisitMember);
+                    goto stateUnknown;
+                }
+                // fallthrough
+            }
+            case ObjectEndVisitMember: {
+                context.putProperty(outputObjectStack.last(), propertyStack.last()[indexStack.last()], outValue);
+                if (context.shouldTerminate())
+                    return context.null();
+
+                indexStack.last()++;
+                goto objectStartVisitMember;
+            }
+            stateUnknown:
+            case StateUnknown:
+                if (OutputType transformed = context.convertIfTerminal(inValue)) {
+                    outValue = transformed;
+                    break;
+                }
+                if (context.isArray(inValue))
+                    goto arrayStartState;
+                goto objectStartState;
+        }
+        if (stateStack.isEmpty())
+            break;
+
+        state = stateStack.last();
+        stateStack.removeLast();
+
+        if (!--tickCount) {
+            if (context.didTimeOut()) {
+                context.throwInterruptedException();
+                return context.null();
+            }
+            tickCount = context.ticksUntilNextCheck();
+        }
+    }
+    return outValue;
+}
+
+struct BaseWalker {
+    BaseWalker(ExecState* exec)
+        : m_exec(exec)
+        , m_timeoutChecker(exec->globalData().timeoutChecker)
+    {
+        m_timeoutChecker.reset();
+    }
+    ExecState* m_exec;
+    TimeoutChecker m_timeoutChecker;
+    MarkedArgumentBuffer m_gcBuffer;
+
+    bool shouldTerminate()
+    {
+        return m_exec->hadException();
+    }
+
+    unsigned ticksUntilNextCheck()
+    {
+        return m_timeoutChecker.ticksUntilNextCheck();
+    }
+
+    bool didTimeOut()
+    {
+        return m_timeoutChecker.didTimeOut(m_exec);
+    }
+
+    void throwStackOverflow()
+    {
+        m_exec->setException(createStackOverflowError(m_exec));
+    }
+
+    void throwInterruptedException()
+    {
+        m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+    }
+};
+
+struct SerializingTreeWalker : public BaseWalker {
+    typedef JSValue InputType;
+    typedef JSArray* InputArray;
+    typedef JSObject* InputObject;
+    typedef SerializedScriptValueData OutputType;
+    typedef RefPtr<SerializedArray> OutputArray;
+    typedef RefPtr<SerializedObject> OutputObject;
+    typedef PropertyNameArray PropertyList;
+
+    SerializingTreeWalker(ExecState* exec)
+        : BaseWalker(exec)
+    {
+    }
+
+    OutputType null() { return SerializedScriptValueData(); }
+
+    bool isArray(JSValue value)
+    {
+        if (!value.isObject())
+            return false;
+        JSObject* object = asObject(value);
+        return isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info);
+    }
+
+    bool isObject(JSValue value)
+    {
+        return value.isObject();
+    }
+
+    JSArray* asInputArray(JSValue value)
+    {
+        return asArray(value);
+    }
+
+    JSObject* asInputObject(JSValue value)
+    {
+        return asObject(value);
+    }
+
+    PassRefPtr<SerializedArray> createOutputArray(unsigned length)
+    {
+        return SerializedArray::create(length);
+    }
+
+    PassRefPtr<SerializedObject> createOutputObject()
+    {
+        return SerializedObject::create();
+    }
+
+    uint32_t length(JSValue array)
+    {
+        ASSERT(array.isObject());
+        JSObject* object = asObject(array);
+        return object->get(m_exec, m_exec->propertyNames().length).toUInt32(m_exec);
+    }
+
+    bool canDoFastRead(JSArray* array, unsigned index)
+    {
+        return isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index);
+    }
+
+    JSValue getIndex(JSArray* array, unsigned index)
+    {
+        return array->getIndex(index);
+    }
+
+    JSValue getSparseIndex(JSObject* object, unsigned propertyName, bool& hasIndex)
+    {
+        PropertySlot slot(object);
+        if (object->getOwnPropertySlot(m_exec, propertyName, slot)) {
+            hasIndex = true;
+            return slot.getValue(m_exec, propertyName);
+        }
+        hasIndex = false;
+        return jsNull();
+    }
+
+    JSValue getProperty(JSObject* object, const Identifier& propertyName, unsigned)
+    {
+        PropertySlot slot(object);
+        if (object->getOwnPropertySlot(m_exec, propertyName, slot))
+            return slot.getValue(m_exec, propertyName);
+        return jsNull();
+    }
+
+    SerializedScriptValueData convertIfTerminal(JSValue value)
+    {
+        if (!value.isCell())
+            return SerializedScriptValueData(value);
+
+        if (value.isString())
+            return SerializedScriptValueData(asString(value)->value());
+
+        if (value.isNumber())
+            return SerializedScriptValueData(SerializedScriptValueData::NumberType, value.uncheckedGetNumber());
+
+        if (value.isObject() && asObject(value)->inherits(&DateInstance::info))
+            return SerializedScriptValueData(SerializedScriptValueData::DateType, asDateInstance(value)->internalNumber());
+
+        if (isArray(value))
+            return SerializedScriptValueData();
+
+        CallData unusedData;
+        if (value.isObject() && value.getCallData(unusedData) == CallTypeNone)
+            return SerializedScriptValueData();
+
+        // Any other types are expected to serialize as null.
+        return SerializedScriptValueData(jsNull());
+    }
+
+    void getPropertyNames(JSObject* object, Vector<PropertyNameArray, 16>& propertyStack)
+    {
+        propertyStack.append(PropertyNameArray(m_exec));
+        object->getOwnPropertyNames(m_exec, propertyStack.last());
+    }
+
+    void putProperty(RefPtr<SerializedArray> array, unsigned propertyName, const SerializedScriptValueData& value)
+    {
+        array->setIndex(propertyName, value);
+    }
+
+    void putProperty(RefPtr<SerializedObject> object, const Identifier& propertyName, const SerializedScriptValueData& value)
+    {
+        object->set(propertyName, value);
+    }
+
+    bool startArray(JSArray* inArray, RefPtr<SerializedArray>)
+    {
+        // Cycle detection
+        if (!m_cycleDetector.add(inArray).second) {
+            m_exec->setException(createTypeError(m_exec, "Cannot post cyclic structures."));
+            return false;
+        }
+        m_gcBuffer.append(inArray);
+        return true;
+    }
+
+    void endArray(JSArray* inArray, RefPtr<SerializedArray>)
+    {
+        m_cycleDetector.remove(inArray);
+        m_gcBuffer.removeLast();
+    }
+
+    bool startObject(JSObject* inObject, RefPtr<SerializedObject>)
+    {
+        // Cycle detection
+        if (!m_cycleDetector.add(inObject).second) {
+            m_exec->setException(createTypeError(m_exec, "Cannot post cyclic structures."));
+            return false;
+        }
+        m_gcBuffer.append(inObject);
+        return true;
+    }
+
+    void endObject(JSObject* inObject, RefPtr<SerializedObject>)
+    {
+        m_cycleDetector.remove(inObject);
+        m_gcBuffer.removeLast();
+    }
+
+private:
+    HashSet<JSObject*> m_cycleDetector;
+};
+
+SerializedScriptValueData SerializedScriptValueData::serialize(ExecState* exec, JSValue inValue)
+{
+    SerializingTreeWalker context(exec);
+    return walk<SerializingTreeWalker>(context, inValue);
+}
+
+
+struct DeserializingTreeWalker : public BaseWalker {
+    typedef SerializedScriptValueData InputType;
+    typedef RefPtr<SerializedArray> InputArray;
+    typedef RefPtr<SerializedObject> InputObject;
+    typedef JSValue OutputType;
+    typedef JSArray* OutputArray;
+    typedef JSObject* OutputObject;
+    typedef SerializedObject::PropertyNameList PropertyList;
+
+    DeserializingTreeWalker(ExecState* exec, bool mustCopy)
+        : BaseWalker(exec)
+        , m_mustCopy(mustCopy)
+    {
+    }
+
+    OutputType null() { return jsNull(); }
+
+    bool isArray(const SerializedScriptValueData& value)
+    {
+        return value.type() == SerializedScriptValueData::ArrayType;
+    }
+
+    bool isObject(const SerializedScriptValueData& value)
+    {
+        return value.type() == SerializedScriptValueData::ObjectType;
+    }
+
+    SerializedArray* asInputArray(const SerializedScriptValueData& value)
+    {
+        return value.asArray();
+    }
+
+    SerializedObject* asInputObject(const SerializedScriptValueData& value)
+    {
+        return value.asObject();
+    }
+
+    JSArray* createOutputArray(unsigned length)
+    {
+        JSArray* array = constructEmptyArray(m_exec);
+        array->setLength(length);
+        return array;
+    }
+
+    JSObject* createOutputObject()
+    {
+        return constructEmptyObject(m_exec);
+    }
+
+    uint32_t length(RefPtr<SerializedArray> array)
+    {
+        return array->length();
+    }
+
+    bool canDoFastRead(RefPtr<SerializedArray> array, unsigned index)
+    {
+        return array->canDoFastRead(index);
+    }
+
+    SerializedScriptValueData getIndex(RefPtr<SerializedArray> array, unsigned index)
+    {
+        return array->getIndex(index);
+    }
+
+    SerializedScriptValueData getSparseIndex(RefPtr<SerializedArray> array, unsigned propertyName, bool& hasIndex)
+    {
+        return array->getSparseIndex(propertyName, hasIndex);
+    }
+
+    SerializedScriptValueData getProperty(RefPtr<SerializedObject> object, const RefPtr<StringImpl>& propertyName, unsigned propertyIndex)
+    {
+        ASSERT(object->names()[propertyIndex] == propertyName);
+        return object->values()[propertyIndex];
+    }
+
+    JSValue convertIfTerminal(SerializedScriptValueData& value)
+    {
+        switch (value.type()) {
+            case SerializedScriptValueData::ArrayType:
+            case SerializedScriptValueData::ObjectType:
+                return JSValue();
+            case SerializedScriptValueData::StringType:
+                return jsString(m_exec, value.asString().crossThreadString());
+            case SerializedScriptValueData::ImmediateType:
+                return value.asImmediate();
+            case SerializedScriptValueData::NumberType:
+                return jsNumber(m_exec, value.asDouble());
+            case SerializedScriptValueData::DateType:
+                return new (m_exec) DateInstance(m_exec, value.asDouble());
+            default:
+                ASSERT_NOT_REACHED();
+                return JSValue();
+        }
+    }
+
+    void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties)
+    {
+        properties.append(object->names());
+    }
+
+    void putProperty(JSArray* array, unsigned propertyName, JSValue value)
+    {
+        array->put(m_exec, propertyName, value);
+    }
+
+    void putProperty(JSObject* object, const RefPtr<StringImpl> propertyName, JSValue value)
+    {
+        object->putDirect(Identifier(m_exec, String(propertyName)), value);
+    }
+
+    bool startArray(RefPtr<SerializedArray>, JSArray* outArray)
+    {
+        m_gcBuffer.append(outArray);
+        return true;
+    }
+    void endArray(RefPtr<SerializedArray>, JSArray*)
+    {
+        m_gcBuffer.removeLast();
+    }
+    bool startObject(RefPtr<SerializedObject>, JSObject* outObject)
+    {
+        m_gcBuffer.append(outObject);
+        return true;
+    }
+    void endObject(RefPtr<SerializedObject>, JSObject*)
+    {
+        m_gcBuffer.removeLast();
+    }
+
+private:
+    bool m_mustCopy;
+};
+
+JSValue SerializedScriptValueData::deserialize(ExecState* exec, bool mustCopy) const
+{
+    DeserializingTreeWalker context(exec, mustCopy);
+    return walk<DeserializingTreeWalker>(context, *this);
+}
+
+struct TeardownTreeWalker {
+    typedef SerializedScriptValueData InputType;
+    typedef RefPtr<SerializedArray> InputArray;
+    typedef RefPtr<SerializedObject> InputObject;
+    typedef bool OutputType;
+    typedef bool OutputArray;
+    typedef bool OutputObject;
+    typedef SerializedObject::PropertyNameList PropertyList;
+
+    bool shouldTerminate()
+    {
+        return false;
+    }
+
+    unsigned ticksUntilNextCheck()
+    {
+        return 0xFFFFFFFF;
+    }
+
+    bool didTimeOut()
+    {
+        return false;
+    }
+
+    void throwStackOverflow()
+    {
+    }
+
+    void throwInterruptedException()
+    {
+    }
+
+    bool null() { return false; }
+
+    bool isArray(const SerializedScriptValueData& value)
+    {
+        return value.type() == SerializedScriptValueData::ArrayType;
+    }
+
+    bool isObject(const SerializedScriptValueData& value)
+    {
+        return value.type() == SerializedScriptValueData::ObjectType;
+    }
+
+    SerializedArray* asInputArray(const SerializedScriptValueData& value)
+    {
+        return value.asArray();
+    }
+
+    SerializedObject* asInputObject(const SerializedScriptValueData& value)
+    {
+        return value.asObject();
+    }
+
+    bool createOutputArray(unsigned)
+    {
+        return false;
+    }
+
+    bool createOutputObject()
+    {
+        return false;
+    }
+
+    uint32_t length(RefPtr<SerializedArray> array)
+    {
+        return array->length();
+    }
+
+    bool canDoFastRead(RefPtr<SerializedArray> array, unsigned index)
+    {
+        return array->canDoFastRead(index);
+    }
+
+    SerializedScriptValueData getIndex(RefPtr<SerializedArray> array, unsigned index)
+    {
+        return array->getIndex(index);
+    }
+
+    SerializedScriptValueData getSparseIndex(RefPtr<SerializedArray> array, unsigned propertyName, bool& hasIndex)
+    {
+        return array->getSparseIndex(propertyName, hasIndex);
+    }
+
+    SerializedScriptValueData getProperty(RefPtr<SerializedObject> object, const RefPtr<StringImpl>& propertyName, unsigned propertyIndex)
+    {
+        ASSERT(object->names()[propertyIndex] == propertyName);
+        return object->values()[propertyIndex];
+    }
+
+    bool convertIfTerminal(SerializedScriptValueData& value)
+    {
+        switch (value.type()) {
+            case SerializedScriptValueData::ArrayType:
+            case SerializedScriptValueData::ObjectType:
+                return false;
+            case SerializedScriptValueData::StringType:
+            case SerializedScriptValueData::ImmediateType:
+            case SerializedScriptValueData::NumberType:
+                return true;
+            default:
+                ASSERT_NOT_REACHED();
+                return JSValue();
+        }
+    }
+
+    void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties)
+    {
+        properties.append(object->names());
+    }
+
+    void putProperty(bool, unsigned, bool)
+    {
+    }
+
+    void putProperty(bool, const RefPtr<StringImpl>&, bool)
+    {
+    }
+
+    bool startArray(RefPtr<SerializedArray>, bool)
+    {
+        return true;
+    }
+    void endArray(RefPtr<SerializedArray> array, bool)
+    {
+        array->clear();
+    }
+    bool startObject(RefPtr<SerializedObject>, bool)
+    {
+        return true;
+    }
+    void endObject(RefPtr<SerializedObject> object, bool)
+    {
+        object->clear();
+    }
+};
+
+void SerializedScriptValueData::tearDownSerializedData()
+{
+    if (m_sharedData && m_sharedData->refCount() > 1)
+        return;
+    TeardownTreeWalker context;
+    walk<TeardownTreeWalker>(context, *this);
+}
+
+}
diff --git a/WebCore/bindings/js/SerializedScriptValue.h b/WebCore/bindings/js/SerializedScriptValue.h
new file mode 100644
index 0000000..74c5962
--- /dev/null
+++ b/WebCore/bindings/js/SerializedScriptValue.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef SerializedScriptValue_h
+#define SerializedScriptValue_h
+
+#include "ScriptValue.h"
+
+namespace WebCore {
+    class SerializedObject;
+    class SerializedArray;
+
+    class SharedSerializedData : public RefCounted<SharedSerializedData>
+    {
+    public:
+        virtual ~SharedSerializedData() { }
+        SerializedArray* asArray();
+        SerializedObject* asObject();
+    };
+
+    class SerializedScriptValue;
+
+    class SerializedScriptValueData
+    {
+    public:
+        enum SerializedType {
+            EmptyType,
+            DateType,
+            NumberType,
+            ImmediateType,
+            ObjectType,
+            ArrayType,
+            StringType
+        };
+
+        SerializedType type() const { return m_type; }
+        static SerializedScriptValueData serialize(JSC::ExecState*, JSC::JSValue);
+        JSC::JSValue deserialize(JSC::ExecState*, bool mustCopy) const;
+
+        ~SerializedScriptValueData()
+        {
+            if (m_sharedData)
+                tearDownSerializedData();
+        }
+
+        SerializedScriptValueData()
+            : m_type(EmptyType)
+        {
+        }
+
+        explicit SerializedScriptValueData(const String& string)
+            : m_type(StringType)
+            , m_string(string.crossThreadString()) // FIXME: Should be able to just share the Rep
+        {
+        }
+
+        explicit SerializedScriptValueData(JSC::JSValue value)
+            : m_type(ImmediateType)
+        {
+            ASSERT(!value.isCell());
+            m_data.m_immediate = JSC::JSValue::encode(value);
+        }
+
+        SerializedScriptValueData(SerializedType type, double value)
+            : m_type(type)
+        {
+            m_data.m_double = value;
+        }
+
+        SerializedScriptValueData(RefPtr<SerializedObject>);
+        SerializedScriptValueData(RefPtr<SerializedArray>);
+
+        JSC::JSValue asImmediate() const
+        {
+            ASSERT(m_type == ImmediateType);
+            return JSC::JSValue::decode(m_data.m_immediate);
+        }
+
+        double asDouble() const
+        {
+            ASSERT(m_type == NumberType || m_type == DateType);
+            return m_data.m_double;
+        }
+
+        String asString() const
+        {
+            ASSERT(m_type == StringType);
+            return m_string;
+        }
+
+        SerializedObject* asObject() const
+        {
+            ASSERT(m_type == ObjectType);
+            ASSERT(m_sharedData);
+            return m_sharedData->asObject();
+        }
+
+        SerializedArray* asArray() const
+        {
+            ASSERT(m_type == ArrayType);
+            ASSERT(m_sharedData);
+            return m_sharedData->asArray();
+        }
+
+        operator bool () const { return m_type != EmptyType; }
+
+        SerializedScriptValueData release() {
+            SerializedScriptValueData result = *this;
+            *this = SerializedScriptValueData();
+            return result;
+        }
+
+    private:
+        void tearDownSerializedData();
+        SerializedType m_type;
+        RefPtr<SharedSerializedData> m_sharedData;
+        String m_string;
+        union {
+            double m_double;
+            JSC::EncodedJSValue m_immediate;
+        } m_data;
+    };
+
+    class SerializedScriptValue : public RefCounted<SerializedScriptValue>
+    {
+    public:
+        static PassRefPtr<SerializedScriptValue> create(JSC::ExecState* exec, JSC::JSValue value)
+        {
+            return adoptRef(new SerializedScriptValue(SerializedScriptValueData::serialize(exec, value)));
+        }
+
+        static PassRefPtr<SerializedScriptValue> create(String string)
+        {
+            return adoptRef(new SerializedScriptValue(SerializedScriptValueData(string)));
+        }
+
+        static PassRefPtr<SerializedScriptValue> create()
+        {
+            return adoptRef(new SerializedScriptValue(SerializedScriptValueData()));
+        }
+
+        PassRefPtr<SerializedScriptValue> release() {
+            PassRefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_value));
+            m_value = SerializedScriptValueData();
+            result->m_mustCopy = true;
+            return result;
+        }
+
+        String toString() {
+            if (m_value.type() != SerializedScriptValueData::StringType)
+                return "";
+            return m_value.asString();
+        }
+
+        JSC::JSValue deserialize(JSC::ExecState* exec)
+        {
+            if (!m_value)
+                return JSC::jsNull();
+            return m_value.deserialize(exec, m_mustCopy);
+        }
+
+        ~SerializedScriptValue()
+        {
+        }
+    private:
+        SerializedScriptValue(SerializedScriptValueData value)
+            : m_value(value)
+            , m_mustCopy(false)
+        {
+        }
+        SerializedScriptValueData m_value;
+        bool m_mustCopy;
+    };
+}
+
+#endif
diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm
index d552aa0..095c75f 100644
--- a/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -1842,6 +1842,11 @@ sub JSValueToNative
         return "$value.toString(exec)";
     }
 
+    if ($type eq "SerializedScriptValue") {
+        $implIncludes{"SerializedScriptValue.h"} = 1;
+        return "SerializedScriptValue::create(exec, $value)";
+    }
+
     $implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint";
     $implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect";
     $implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
@@ -1947,6 +1952,9 @@ sub NativeToJSValue
         $joinedName = $type;
         $joinedName =~ s/Abs|Rel//;
         $implIncludes{"$joinedName.h"} = 1;
+    } elsif ($type eq "SerializedScriptValue") {
+        $implIncludes{"$type.h"} = 1;
+        return "$value->deserialize(exec)";
     } else {
         # Default, include header with same name.
         $implIncludes{"JS$type.h"} = 1;
diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm
index 0026ba1..317086b 100644
--- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm
@@ -311,7 +311,7 @@ sub GetClassName
     my $name = $codeGenerator->StripModule(shift);
 
     # special cases
-    return "NSString" if $codeGenerator->IsStringType($name);
+    return "NSString" if $codeGenerator->IsStringType($name) or $name eq "SerializedScriptValue";
     return "NS$name" if IsNativeObjCType($name);
     return "BOOL" if $name eq "boolean";
     return "unsigned" if $name eq "unsigned long";
@@ -492,6 +492,11 @@ sub GetObjCTypeGetter
     return "WTF::getPtr(nativeEventListener)" if $type eq "EventListener";
     return "WTF::getPtr(nativeNodeFilter)" if $type eq "NodeFilter";
     return "WTF::getPtr(nativeResolver)" if $type eq "XPathNSResolver";
+    
+    if ($type eq "SerializedScriptValue") {
+        $implIncludes{"SerializedScriptValue.h"} = 1;
+        return "WebCore::SerializedScriptValue::create(WebCore::String($argName))";
+    }
     return "core($argName)";
 }
 
@@ -607,6 +612,11 @@ sub AddIncludesForType
         return;
     }
 
+    if ($type eq "SerializedScriptValue") {
+        $implIncludes{"SerializedScriptValue.h"} = 1;
+        return;
+    }
+
     # FIXME: won't compile without these
     $implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
     $implIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList";
@@ -1212,6 +1222,9 @@ sub GenerateImplementation
             } elsif ($idlType eq "Color") {
                 $getterContentHead = "WebCore::nsColor($getterContentHead";
                 $getterContentTail .= ")";
+            } elsif ($attribute->signature->type eq "SerializedScriptValue") {
+                $getterContentHead = "$getterContentHead";
+                $getterContentTail .= "->toString()";                
             } elsif (ConversionNeeded($attribute->signature->type)) {
                 $getterContentHead = "kit(WTF::getPtr($getterContentHead";
                 $getterContentTail .= "))";
@@ -1446,6 +1459,8 @@ sub GenerateImplementation
                     push(@functionContent, "        return $toReturn;\n");
                     push(@functionContent, "    return nil;\n");
                 }
+            } elsif ($returnType eq "SerializedScriptValue") {
+                $content = "foo";
             } else {
                 if (ConversionNeeded($function->signature->type)) {
                     if ($codeGenerator->IsPodType($function->signature->type)) {
diff --git a/WebCore/dom/MessageEvent.cpp b/WebCore/dom/MessageEvent.cpp
index 2ef8bc2..3c84642 100644
--- a/WebCore/dom/MessageEvent.cpp
+++ b/WebCore/dom/MessageEvent.cpp
@@ -34,10 +34,11 @@
 namespace WebCore {
 
 MessageEvent::MessageEvent()
+    : m_data(SerializedScriptValue::create())
 {
 }
 
-MessageEvent::MessageEvent(const String& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray> ports)
+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_origin(origin)
@@ -51,7 +52,7 @@ MessageEvent::~MessageEvent()
 {
 }
 
-void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray> ports)
+void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray> ports)
 {
     if (dispatched())
         return;
@@ -74,7 +75,7 @@ MessagePort* MessageEvent::messagePort()
     return (*m_ports)[0].get();
 }
 
-void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort* port)
+void MessageEvent::initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort* port)
 {
     MessagePortArray* ports = 0;
     if (port) {
diff --git a/WebCore/dom/MessageEvent.h b/WebCore/dom/MessageEvent.h
index 555ed47..b7f9b02 100644
--- a/WebCore/dom/MessageEvent.h
+++ b/WebCore/dom/MessageEvent.h
@@ -31,6 +31,7 @@
 #include "DOMWindow.h"
 #include "Event.h"
 #include "MessagePort.h"
+#include "SerializedScriptValue.h"
 
 namespace WebCore {
 
@@ -42,15 +43,15 @@ namespace WebCore {
         {
             return adoptRef(new MessageEvent);
         }
-        static PassRefPtr<MessageEvent> create(PassOwnPtr<MessagePortArray> ports, const String& data = "", const String& origin = "", const String& lastEventId = "", PassRefPtr<DOMWindow> source = 0)
+        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));
         }
         virtual ~MessageEvent();
 
-        void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, const String& data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>);
+        void initMessageEvent(const AtomicString& type, bool canBubble, bool cancelable, PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, DOMWindow* source, PassOwnPtr<MessagePortArray>);
 
-        const String& data() const { return m_data; }
+        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(); }
@@ -59,15 +60,15 @@ namespace WebCore {
         // 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, const String& data, const String& origin, const String& lastEventId, DOMWindow* source, MessagePort*);
+        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;
 
     private:
         MessageEvent();
-        MessageEvent(const String& data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
+        MessageEvent(PassRefPtr<SerializedScriptValue> data, const String& origin, const String& lastEventId, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortArray>);
 
-        String m_data;
+        RefPtr<SerializedScriptValue> m_data;
         String m_origin;
         String m_lastEventId;
         RefPtr<DOMWindow> m_source;
diff --git a/WebCore/dom/MessageEvent.idl b/WebCore/dom/MessageEvent.idl
index a32cc93..7e497fc 100644
--- a/WebCore/dom/MessageEvent.idl
+++ b/WebCore/dom/MessageEvent.idl
@@ -30,20 +30,20 @@ module events {
         GenerateConstructor,
         NoStaticTables
     ] MessageEvent : Event {
+        readonly attribute SerializedScriptValue data;
 
-        readonly attribute DOMString data;
         readonly attribute DOMString origin;
         readonly attribute DOMString lastEventId;
         readonly attribute DOMWindow source;
 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
         readonly attribute [CustomGetter] Array ports;
 
-        [Custom] void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in Array messagePorts);
+        [Custom] void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in SerializedScriptValue dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in Array messagePorts);
 #else
         // 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;
 
-        void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in MessagePort messagePort);
+        void initMessageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in SerializedScriptValue dataArg, in DOMString originArg, in DOMString lastEventIdArg, in DOMWindow sourceArg, in MessagePort messagePort);
 #endif
 
     };
diff --git a/WebCore/dom/MessagePort.cpp b/WebCore/dom/MessagePort.cpp
index 50a0106..9f6e649 100644
--- a/WebCore/dom/MessagePort.cpp
+++ b/WebCore/dom/MessagePort.cpp
@@ -56,7 +56,7 @@ MessagePort::~MessagePort()
 }
 
 // FIXME: remove this when we update the ObjC bindings (bug #28774).
-void MessagePort::postMessage(const String& message, MessagePort* port, ExceptionCode& ec)
+void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec)
 {
     MessagePortArray ports;
     if (port)
@@ -64,12 +64,12 @@ void MessagePort::postMessage(const String& message, MessagePort* port, Exceptio
     postMessage(message, &ports, ec);
 }
 
-void MessagePort::postMessage(const String& message, ExceptionCode& ec)
+void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode& ec)
 {
     postMessage(message, static_cast<MessagePortArray*>(0), ec);
 }
 
-void MessagePort::postMessage(const String& message, const MessagePortArray* ports, ExceptionCode& ec)
+void MessagePort::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec)
 {
     if (!m_entangledChannel)
         return;
diff --git a/WebCore/dom/MessagePort.h b/WebCore/dom/MessagePort.h
index e649d5d..0ab0f50 100644
--- a/WebCore/dom/MessagePort.h
+++ b/WebCore/dom/MessagePort.h
@@ -56,10 +56,10 @@ namespace WebCore {
         static PassRefPtr<MessagePort> create(ScriptExecutionContext& scriptExecutionContext) { return adoptRef(new MessagePort(scriptExecutionContext)); }
         ~MessagePort();
 
-        void postMessage(const String& message, ExceptionCode&);
-        void postMessage(const String& message, const MessagePortArray*, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, ExceptionCode&);
         // FIXME: remove this when we update the ObjC bindings (bug #28774).
-        void postMessage(const String& message, MessagePort*, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, ExceptionCode&);
 
         void start();
         void close();
diff --git a/WebCore/dom/MessagePortChannel.cpp b/WebCore/dom/MessagePortChannel.cpp
index 544cabd..e1a3ac6 100644
--- a/WebCore/dom/MessagePortChannel.cpp
+++ b/WebCore/dom/MessagePortChannel.cpp
@@ -33,13 +33,13 @@
 namespace WebCore {
 
 
-PassOwnPtr<MessagePortChannel::EventData> MessagePortChannel::EventData::create(const String& message, PassOwnPtr<MessagePortChannelArray> channels)
+PassOwnPtr<MessagePortChannel::EventData> MessagePortChannel::EventData::create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
 {
     return new EventData(message, channels);
 }
 
-MessagePortChannel::EventData::EventData(const String& message, PassOwnPtr<MessagePortChannelArray> channels)
-    : m_message(message.crossThreadString())
+MessagePortChannel::EventData::EventData(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+    : m_message(message->release())
     , m_channels(channels)
 {
 }
diff --git a/WebCore/dom/MessagePortChannel.h b/WebCore/dom/MessagePortChannel.h
index 4acfe7f..2321b1f 100644
--- a/WebCore/dom/MessagePortChannel.h
+++ b/WebCore/dom/MessagePortChannel.h
@@ -33,6 +33,8 @@
 
 #include "PlatformString.h"
 
+#include "SerializedScriptValue.h"
+
 #include <wtf/OwnPtr.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/PassRefPtr.h>
@@ -45,6 +47,7 @@ namespace WebCore {
     class MessagePortChannel;
     class PlatformMessagePortChannel;
     class ScriptExecutionContext;
+    class SerializedScriptValue;
     class String;
 
     // The overwhelmingly common case is sending a single port, so handle that efficiently with an inline buffer of size 1.
@@ -77,14 +80,14 @@ namespace WebCore {
 
         class EventData {
         public:
-            static PassOwnPtr<EventData> create(const String&, PassOwnPtr<MessagePortChannelArray>);
+            static PassOwnPtr<EventData> create(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>);
 
-            const String& message() { return m_message; }
+            SerializedScriptValue* message() { return m_message.get(); }
             PassOwnPtr<MessagePortChannelArray> channels() { return m_channels.release(); }
 
         private:
-            EventData(const String& message, PassOwnPtr<MessagePortChannelArray>);
-            String m_message;
+            EventData(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray>);
+            RefPtr<SerializedScriptValue> m_message;
             OwnPtr<MessagePortChannelArray> m_channels;
         };
 
diff --git a/WebCore/page/DOMWindow.cpp b/WebCore/page/DOMWindow.cpp
index aa6012b..c30b6b9 100644
--- a/WebCore/page/DOMWindow.cpp
+++ b/WebCore/page/DOMWindow.cpp
@@ -64,6 +64,7 @@
 #include "PlatformString.h"
 #include "Screen.h"
 #include "SecurityOrigin.h"
+#include "SerializedScriptValue.h"
 #include "Settings.h"
 #include "Storage.h"
 #include "StorageArea.h"
@@ -80,7 +81,7 @@ namespace WebCore {
 
 class PostMessageTimer : public TimerBase {
 public:
-    PostMessageTimer(DOMWindow* window, const String& message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin)
+    PostMessageTimer(DOMWindow* window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin)
         : m_window(window)
         , m_message(message)
         , m_origin(sourceOrigin)
@@ -104,7 +105,7 @@ private:
     }
 
     RefPtr<DOMWindow> m_window;
-    String m_message;
+    RefPtr<SerializedScriptValue> m_message;
     String m_origin;
     RefPtr<DOMWindow> m_source;
     OwnPtr<MessagePortChannelArray> m_channels;
@@ -635,7 +636,7 @@ NotificationCenter* DOMWindow::webkitNotifications() const
 }
 #endif
 
-void DOMWindow::postMessage(const String& message, MessagePort* port, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
+void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
 {
     MessagePortArray ports;
     if (port)
@@ -643,7 +644,7 @@ void DOMWindow::postMessage(const String& message, MessagePort* port, const Stri
     postMessage(message, &ports, targetOrigin, source, ec);
 }
 
-void DOMWindow::postMessage(const String& message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
+void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
 {
     if (!m_frame)
         return;
diff --git a/WebCore/page/DOMWindow.h b/WebCore/page/DOMWindow.h
index f2177ee..25eadc8 100644
--- a/WebCore/page/DOMWindow.h
+++ b/WebCore/page/DOMWindow.h
@@ -59,6 +59,7 @@ namespace WebCore {
     class NotificationCenter;
     class PostMessageTimer;
     class ScheduledAction;
+    class SerializedScriptValue;
     class Screen;
     class WebKitPoint;
 
@@ -214,9 +215,9 @@ namespace WebCore {
         NotificationCenter* webkitNotifications() const;
 #endif
 
-        void postMessage(const String& message, const MessagePortArray*, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray*, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
         // FIXME: remove this when we update the ObjC bindings (bug #28774).
-        void postMessage(const String& message, MessagePort*, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, const String& targetOrigin, DOMWindow* source, ExceptionCode&);
         void postMessageTimerFired(PostMessageTimer*);
 
         void scrollBy(int x, int y) const;
diff --git a/WebCore/page/DOMWindow.idl b/WebCore/page/DOMWindow.idl
index 3b3cce0..9e3df48 100644
--- a/WebCore/page/DOMWindow.idl
+++ b/WebCore/page/DOMWindow.idl
@@ -182,11 +182,11 @@ module window {
 
         // cross-document messaging
 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
-        [DoNotCheckDomainSecurity, Custom] void postMessage(in DOMString message, in [Optional] Array messagePorts, in DOMString targetOrigin)
+        [DoNotCheckDomainSecurity, Custom] void postMessage(in SerializedScriptValue message, in [Optional] Array messagePorts, in DOMString targetOrigin)
             raises(DOMException);
 #else
         // There's no good way to expose an array via the ObjC bindings, so for now just allow passing in a single port.
-        [DoNotCheckDomainSecurity, Custom] void postMessage(in DOMString message, in [Optional] MessagePort messagePort, in DOMString targetOrigin)
+        [DoNotCheckDomainSecurity, Custom] void postMessage(in SerializedScriptValue message, in [Optional] MessagePort messagePort, in DOMString targetOrigin)
             raises(DOMException);
 #endif
 
diff --git a/WebCore/page/EventSource.cpp b/WebCore/page/EventSource.cpp
index ae3c0c3..2c9a343 100644
--- a/WebCore/page/EventSource.cpp
+++ b/WebCore/page/EventSource.cpp
@@ -45,6 +45,7 @@
 #include "ResourceRequest.h"
 #include "ResourceResponse.h"
 #include "ScriptExecutionContext.h"
+#include "SerializedScriptValue.h"
 #include "TextResourceDecoder.h"
 #include "ThreadableLoader.h"
 
@@ -294,7 +295,7 @@ void EventSource::stop()
 PassRefPtr<MessageEvent> EventSource::createMessageEvent()
 {
     RefPtr<MessageEvent> event = MessageEvent::create();
-    event->initMessageEvent(m_eventName.isEmpty() ? eventNames().messageEvent : AtomicString(m_eventName), false, false, String::adopt(m_data), m_origin, m_lastEventId, 0, 0);
+    event->initMessageEvent(m_eventName.isEmpty() ? eventNames().messageEvent : AtomicString(m_eventName), false, false, SerializedScriptValue::create(String::adopt(m_data)), m_origin, m_lastEventId, 0, 0);
     return event.release();
 }
 
diff --git a/WebCore/websockets/WebSocket.cpp b/WebCore/websockets/WebSocket.cpp
index dd89c14..16211a7 100644
--- a/WebCore/websockets/WebSocket.cpp
+++ b/WebCore/websockets/WebSocket.cpp
@@ -189,7 +189,7 @@ void WebSocket::didReceiveMessage(const String& msg)
         return;
     RefPtr<MessageEvent> evt = MessageEvent::create();
     // FIXME: origin, lastEventId, source, messagePort.
-    evt->initMessageEvent(eventNames().messageEvent, false, false, msg, "", "", 0, 0);
+    evt->initMessageEvent(eventNames().messageEvent, false, false, SerializedScriptValue::create(msg), "", "", 0, 0);
     scriptExecutionContext()->postTask(ProcessWebSocketEventTask::create(this, evt));
 }
 
diff --git a/WebCore/workers/DedicatedWorkerContext.cpp b/WebCore/workers/DedicatedWorkerContext.cpp
index 5206fd9..82dc4b3 100644
--- a/WebCore/workers/DedicatedWorkerContext.cpp
+++ b/WebCore/workers/DedicatedWorkerContext.cpp
@@ -47,7 +47,7 @@ DedicatedWorkerContext::DedicatedWorkerContext(const KURL& url, const String& us
 }
 
 // FIXME: remove this when we update the ObjC bindings (bug #28774).
-void DedicatedWorkerContext::postMessage(const String& message, MessagePort* port, ExceptionCode& ec)
+void DedicatedWorkerContext::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec)
 {
     MessagePortArray ports;
     if (port)
@@ -55,12 +55,12 @@ void DedicatedWorkerContext::postMessage(const String& message, MessagePort* por
     postMessage(message, &ports, ec);
 }
 
-void DedicatedWorkerContext::postMessage(const String& message, ExceptionCode& ec)
+void DedicatedWorkerContext::postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode& ec)
 {
     postMessage(message, static_cast<MessagePortArray*>(0), ec);
 }
 
-void DedicatedWorkerContext::postMessage(const String& message, const MessagePortArray* ports, ExceptionCode& ec)
+void DedicatedWorkerContext::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec)
 {
     if (isClosing())
         return;
diff --git a/WebCore/workers/DedicatedWorkerContext.h b/WebCore/workers/DedicatedWorkerContext.h
index 7609fcd..74a39d9 100644
--- a/WebCore/workers/DedicatedWorkerContext.h
+++ b/WebCore/workers/DedicatedWorkerContext.h
@@ -55,10 +55,10 @@ namespace WebCore {
 
         // EventTarget
         virtual DedicatedWorkerContext* toDedicatedWorkerContext() { return this; }
-        void postMessage(const String&, ExceptionCode&);
-        void postMessage(const String&, const MessagePortArray*, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue>, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue>, const MessagePortArray*, ExceptionCode&);
         // FIXME: remove this when we update the ObjC bindings (bug #28774).
-        void postMessage(const String&, MessagePort*, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue>, MessagePort*, ExceptionCode&);
 
         DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
 
diff --git a/WebCore/workers/DedicatedWorkerContext.idl b/WebCore/workers/DedicatedWorkerContext.idl
index 899bbae..f421b9a 100644
--- a/WebCore/workers/DedicatedWorkerContext.idl
+++ b/WebCore/workers/DedicatedWorkerContext.idl
@@ -39,7 +39,7 @@ module threads {
     ] DedicatedWorkerContext : WorkerContext {
 
 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
-        [Custom] void postMessage(in DOMString message, in [Optional] Array messagePorts)
+        [Custom] void postMessage(in any message, in [Optional] Array messagePorts)
             raises(DOMException);
 #else
         // There's no good way to expose an array via the ObjC bindings, so for now just allow passing in a single port.
diff --git a/WebCore/workers/Worker.cpp b/WebCore/workers/Worker.cpp
index c2c25c1..864b7c6 100644
--- a/WebCore/workers/Worker.cpp
+++ b/WebCore/workers/Worker.cpp
@@ -70,7 +70,7 @@ Worker::~Worker()
 }
 
 // FIXME: remove this when we update the ObjC bindings (bug #28774).
-void Worker::postMessage(const String& message, MessagePort* port, ExceptionCode& ec)
+void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, ExceptionCode& ec)
 {
     MessagePortArray ports;
     if (port)
@@ -78,12 +78,12 @@ void Worker::postMessage(const String& message, MessagePort* port, ExceptionCode
     postMessage(message, &ports, ec);
 }
 
-void Worker::postMessage(const String& message, ExceptionCode& ec)
+void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, ExceptionCode& ec)
 {
     postMessage(message, static_cast<MessagePortArray*>(0), ec);
 }
 
-void Worker::postMessage(const String& message, const MessagePortArray* ports, ExceptionCode& ec)
+void Worker::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, ExceptionCode& ec)
 {
     // Disentangle the port in preparation for sending it to the remote context.
     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec);
diff --git a/WebCore/workers/Worker.h b/WebCore/workers/Worker.h
index 41d39a2..6b8fa84 100644
--- a/WebCore/workers/Worker.h
+++ b/WebCore/workers/Worker.h
@@ -58,10 +58,10 @@ namespace WebCore {
 
         virtual Worker* toWorker() { return this; }
 
-        void postMessage(const String&, ExceptionCode&);
-        void postMessage(const String&, const MessagePortArray*, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue>, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue>, const MessagePortArray*, ExceptionCode&);
         // FIXME: remove this when we update the ObjC bindings (bug #28774).
-        void postMessage(const String& message, MessagePort*, ExceptionCode&);
+        void postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort*, ExceptionCode&);
 
         void terminate();
 
diff --git a/WebCore/workers/Worker.idl b/WebCore/workers/Worker.idl
index 9c9342b..0382739 100644
--- a/WebCore/workers/Worker.idl
+++ b/WebCore/workers/Worker.idl
@@ -35,11 +35,11 @@ module threads {
         attribute EventListener onmessage;
 
 #if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
-        [Custom] void postMessage(in DOMString message, in [Optional] Array messagePorts)
+        [Custom] void postMessage(in SerialisedScriptValue message, in [Optional] Array messagePorts)
             raises(DOMException);
 #else
         // There's no good way to expose an array via the ObjC bindings, so for now just allow passing in a single port.
-        void postMessage(in DOMString message, in [Optional] MessagePort messagePort)
+        void postMessage(in SerializedScriptValue message, in [Optional] MessagePort messagePort)
             raises(DOMException);
 #endif
 
diff --git a/WebCore/workers/WorkerContextProxy.h b/WebCore/workers/WorkerContextProxy.h
index d55452e..e1ca139 100644
--- a/WebCore/workers/WorkerContextProxy.h
+++ b/WebCore/workers/WorkerContextProxy.h
@@ -53,7 +53,7 @@ namespace WebCore {
 
         virtual void terminateWorkerContext() = 0;
 
-        virtual void postMessageToWorkerContext(const String&, PassOwnPtr<MessagePortChannelArray>) = 0;
+        virtual void postMessageToWorkerContext(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>) = 0;
 
         virtual bool hasPendingActivity() const = 0;
 
diff --git a/WebCore/workers/WorkerMessagingProxy.cpp b/WebCore/workers/WorkerMessagingProxy.cpp
index 381bc4a..0b66694 100644
--- a/WebCore/workers/WorkerMessagingProxy.cpp
+++ b/WebCore/workers/WorkerMessagingProxy.cpp
@@ -46,14 +46,14 @@ namespace WebCore {
 
 class MessageWorkerContextTask : public ScriptExecutionContext::Task {
 public:
-    static PassRefPtr<MessageWorkerContextTask> create(const String& message, PassOwnPtr<MessagePortChannelArray> channels)
+    static PassRefPtr<MessageWorkerContextTask> create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
     {
         return adoptRef(new MessageWorkerContextTask(message, channels));
     }
 
 private:
-    MessageWorkerContextTask(const String& message, PassOwnPtr<MessagePortChannelArray> channels)
-        : m_message(message.crossThreadString())
+    MessageWorkerContextTask(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
+        : m_message(message->release())
         , m_channels(channels)
     {
     }
@@ -68,20 +68,20 @@ private:
     }
 
 private:
-    String m_message;
+    RefPtr<SerializedScriptValue> m_message;
     OwnPtr<MessagePortChannelArray> m_channels;
 };
 
 class MessageWorkerTask : public ScriptExecutionContext::Task {
 public:
-    static PassRefPtr<MessageWorkerTask> create(const String& message, PassOwnPtr<MessagePortChannelArray> channels, WorkerMessagingProxy* messagingProxy)
+    static PassRefPtr<MessageWorkerTask> create(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels, WorkerMessagingProxy* messagingProxy)
     {
         return adoptRef(new MessageWorkerTask(message, channels, messagingProxy));
     }
 
 private:
-    MessageWorkerTask(const String& message, PassOwnPtr<MessagePortChannelArray> channels, WorkerMessagingProxy* messagingProxy)
-        : m_message(message.crossThreadString())
+    MessageWorkerTask(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels, WorkerMessagingProxy* messagingProxy)
+        : m_message(message->release())
         , m_channels(channels)
         , m_messagingProxy(messagingProxy)
     {
@@ -98,7 +98,7 @@ private:
     }
 
 private:
-    String m_message;
+    RefPtr<SerializedScriptValue> m_message;
     OwnPtr<MessagePortChannelArray> m_channels;
     WorkerMessagingProxy* m_messagingProxy;
 };
@@ -240,12 +240,12 @@ void WorkerMessagingProxy::startWorkerContext(const KURL& scriptURL, const Strin
     thread->start();
 }
 
-void WorkerMessagingProxy::postMessageToWorkerObject(const String& message, PassOwnPtr<MessagePortChannelArray> channels)
+void WorkerMessagingProxy::postMessageToWorkerObject(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
 {
     m_scriptExecutionContext->postTask(MessageWorkerTask::create(message, channels.release(), this));
 }
 
-void WorkerMessagingProxy::postMessageToWorkerContext(const String& message, PassOwnPtr<MessagePortChannelArray> channels)
+void WorkerMessagingProxy::postMessageToWorkerContext(PassRefPtr<SerializedScriptValue> message, PassOwnPtr<MessagePortChannelArray> channels)
 {
     if (m_askedToTerminate)
         return;
diff --git a/WebCore/workers/WorkerMessagingProxy.h b/WebCore/workers/WorkerMessagingProxy.h
index 8ab0cb6..754102a 100644
--- a/WebCore/workers/WorkerMessagingProxy.h
+++ b/WebCore/workers/WorkerMessagingProxy.h
@@ -54,13 +54,13 @@ namespace WebCore {
         // (Only use these methods in the worker object thread.)
         virtual void startWorkerContext(const KURL& scriptURL, const String& userAgent, const String& sourceCode);
         virtual void terminateWorkerContext();
-        virtual void postMessageToWorkerContext(const String&, PassOwnPtr<MessagePortChannelArray>);
+        virtual void postMessageToWorkerContext(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>);
         virtual bool hasPendingActivity() const;
         virtual void workerObjectDestroyed();
 
         // Implementations of WorkerObjectProxy.
         // (Only use these methods in the worker context thread.)
-        virtual void postMessageToWorkerObject(const String&, PassOwnPtr<MessagePortChannelArray>);
+        virtual void postMessageToWorkerObject(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>);
         virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, const String& sourceURL);
         virtual void postConsoleMessageToWorkerObject(MessageDestination, MessageSource, MessageType, MessageLevel, const String& message, int lineNumber, const String& sourceURL);
         virtual void confirmMessageFromWorkerObject(bool hasPendingActivity);
diff --git a/WebCore/workers/WorkerObjectProxy.h b/WebCore/workers/WorkerObjectProxy.h
index 77a7d7d..33e0bc3 100644
--- a/WebCore/workers/WorkerObjectProxy.h
+++ b/WebCore/workers/WorkerObjectProxy.h
@@ -44,7 +44,7 @@ namespace WebCore {
     // A proxy to talk to the worker object.
     class WorkerObjectProxy : public WorkerReportingProxy {
     public:
-        virtual void postMessageToWorkerObject(const String&, PassOwnPtr<MessagePortChannelArray>) = 0;
+        virtual void postMessageToWorkerObject(PassRefPtr<SerializedScriptValue>, PassOwnPtr<MessagePortChannelArray>) = 0;
 
         virtual void confirmMessageFromWorkerObject(bool hasPendingActivity) = 0;
         virtual void reportPendingActivity(bool hasPendingActivity) = 0;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list