Serialization of JavaScript values does not appear to respect new HTML5 Structured...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Aug 2012 19:08:54 +0000 (19:08 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Aug 2012 19:08:54 +0000 (19:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=65292

Patch by Christophe Dumez <christophe.dumez@intel.com> on 2012-08-23
Reviewed by Oliver Hunt.

Source/JavaScriptCore:

Add function to construct a StringObject from a JSValue.
Similar functions already exist for NumberObject and
BooleanObject for example.

Export several symbols so address linking errors in
WebCore.

* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
* runtime/BooleanObject.h:
(BooleanObject):
* runtime/NumberObject.h:
(NumberObject):
(JSC):
* runtime/StringObject.cpp:
(JSC::constructString):
(JSC):
* runtime/StringObject.h:
(JSC):

Source/WebCore:

JSC now correctly serialize Boolean, Number and String objects as per
the structured clone algorithm specification. This patch reduces the
delta with the V8 implementation of SerializedScriptValue.

No new tests, already tested by fast/dom/Window/window-postmessage-clone.html

* bindings/js/SerializedScriptValue.cpp:
(WebCore):
(WebCore::CloneSerializer::dumpStringObject):
(CloneSerializer):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneDeserializer::readTerminal):

LayoutTests:

Update expected results for fast/dom/Window/window-postmessage-clone.html
now that String, Boolean and Number object are correctly serialized with
JSC.

* fast/dom/Window/window-postmessage-clone-expected.txt:
* platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/fast/dom/Window/window-postmessage-clone-expected.txt
LayoutTests/platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
Source/JavaScriptCore/runtime/BooleanObject.h
Source/JavaScriptCore/runtime/NumberObject.h
Source/JavaScriptCore/runtime/StringObject.cpp
Source/JavaScriptCore/runtime/StringObject.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/SerializedScriptValue.cpp

index 847d60b..ef228ed 100644 (file)
@@ -1,3 +1,17 @@
+2012-08-23  Christophe Dumez  <christophe.dumez@intel.com>
+
+        Serialization of JavaScript values does not appear to respect new HTML5 Structured Clone semantics
+        https://bugs.webkit.org/show_bug.cgi?id=65292
+
+        Reviewed by Oliver Hunt.
+
+        Update expected results for fast/dom/Window/window-postmessage-clone.html
+        now that String, Boolean and Number object are correctly serialized with
+        JSC.
+
+        * fast/dom/Window/window-postmessage-clone-expected.txt:
+        * platform/gtk/fast/dom/Window/window-postmessage-clone-expected.txt:
+
 2012-08-23  Kenneth Russell  <kbr@google.com>
 
         Web Inspector: three layout tests crashing with assertion failure
index 13d9b62..9861d53 100644 (file)
@@ -1,8 +1,8 @@
 Tests that we clone object hierarchies
 
-FAIL: 'postMessage((function(){}))' should throw but didn't
-FAIL: 'postMessage(var x = 0; try { eval("badref"); } catch(e) { x = e; } x)' should throw but didn't
-PASS: 'postMessage(window)' threw TypeError: Type error
+PASS: 'postMessage((function(){}))' threw Error: DATA_CLONE_ERR: DOM Exception 25
+PASS: 'postMessage(var x = 0; try { eval("badref"); } catch(e) { x = e; } x)' threw Error: DATA_CLONE_ERR: DOM Exception 25
+PASS: 'postMessage(window)' threw Error: DATA_CLONE_ERR: DOM Exception 25
 PASS: 'postMessage(({get a() { throw "x" }}))' threw x
 PASS: 'postMessage((function() {return {get a() { throw "accessor-exn"; }};})())' threw accessor-exn
 PASS: 'postMessage((function() {var obja = {get p() { throw "accessor-exn"; }}; return {get a() { return obja; }};})())' threw accessor-exn
@@ -27,14 +27,12 @@ PASS: eventData is a,a,b,a,b of type object
 PASS: eventData is a,a,b,[object Object] of type object
 PASS: eventData is 1,2,3 of type object
 PASS: eventData is ,,1 of type object
-FAIL: eventData is null should be function () {} of type function
-FAIL: eventData is [object Object] should be ReferenceError: Can't find variable: badref of type object
 PASS: eventData is 2009-02-13T23:31:30.000Z of type object
 PASS: eventData is [object Object] of type object
-FAIL: eventData is [object Object] should be true of type object
-FAIL: eventData is [object Object] should be false of type object
-FAIL: eventData is [object Object] should be gnirts of type object
-FAIL: eventData is [object Object] should be 42 of type object
+PASS: eventData is true of type object
+PASS: eventData is false of type object
+PASS: eventData is gnirts of type object
+PASS: eventData is 42 of type object
 PASS: eventData is === to eventData.self
 PASS: eventData is === to eventData[0]
 PASS: eventData.graph1 is === to eventData.graph2
@@ -90,25 +88,25 @@ FAIL: accessor value was nullified
 PASS: window.pcalled === true
 PASS: window.acalled === true
 FAIL: window.bcalled === undefined
-FAIL: Boolean values correct (0)
-FAIL: Boolean values correct (3)
+PASS: Boolean values correct (0)
+PASS: Boolean values correct (3)
 PASS: Boolean values correct (1,2)
 PASS: Boolean values correct (4,5)
 PASS: References to Booleans correct (0,1)
 PASS: References to Booleans correct (3,4)
 PASS: References to Booleans correct (0,2)
 PASS: References to Booleans correct (3,5)
-FAIL: Number values correct (0)
+PASS: Number values correct (0)
 PASS: Number values correct (0,2)
 PASS: References to numbers correct (0,1)
 PASS: References to numbers correct (0,2)
-FAIL: String values correct (0)
+PASS: String values correct (0)
 PASS: String values correct (0,2)
 PASS: References to strings correct (0,1)
 PASS: References to strings correct (0,2)
-FAIL: String object properties not serialized
-FAIL: Number object properties not serialized
-FAIL: Boolean object properties not serialized
+PASS: String object properties not serialized
+PASS: Number object properties not serialized
+PASS: Boolean object properties not serialized
 PASS: Date values correct (0)
 PASS: Date values correct (1)
 FAIL: References to dates correct (0)
index 11a2440..ae83bda 100644 (file)
@@ -1,10 +1,8 @@
-CONSOLE MESSAGE: line 86: TypeError: No default value
-CONSOLE MESSAGE: line 86: TypeError: No default value
 Tests that we clone object hierarchies
 
-FAIL: 'postMessage((function(){}))' should throw but didn't
-FAIL: 'postMessage(var x = 0; try { eval("badref"); } catch(e) { x = e; } x)' should throw but didn't
-PASS: 'postMessage(window)' threw TypeError: Type error
+PASS: 'postMessage((function(){}))' threw Error: DATA_CLONE_ERR: DOM Exception 25
+PASS: 'postMessage(var x = 0; try { eval("badref"); } catch(e) { x = e; } x)' threw Error: DATA_CLONE_ERR: DOM Exception 25
+PASS: 'postMessage(window)' threw Error: DATA_CLONE_ERR: DOM Exception 25
 PASS: 'postMessage(({get a() { throw "x" }}))' threw x
 PASS: eventData is null of type object
 PASS: eventData is undefined of type undefined
@@ -25,14 +23,12 @@ PASS: eventData is a,a,b,a,b of type object
 PASS: eventData is a,a,b,[object Object] of type object
 PASS: eventData is 1,2,3 of type object
 PASS: eventData is ,,1 of type object
-FAIL: eventData is null should be function () {} of type function
-FAIL: eventData is [object Object] should be ReferenceError: Can't find variable: badref of type object
 PASS: eventData is 2009-02-13T23:31:30.000Z of type object
 PASS: eventData is [object Object] of type object
-FAIL: eventData is [object Object] should be true of type object
-FAIL: eventData is [object Object] should be false of type object
-FAIL: eventData is [object Object] should be gnirts of type object
-FAIL: eventData is [object Object] should be 42 of type object
+PASS: eventData is true of type object
+PASS: eventData is false of type object
+PASS: eventData is gnirts of type object
+PASS: eventData is 42 of type object
 PASS: eventData is === to eventData.self
 PASS: eventData is === to eventData[0]
 PASS: eventData.graph1 is === to eventData.graph2
@@ -92,25 +88,25 @@ FAIL: accessor value was nullified
 PASS: window.pcalled === true
 PASS: window.acalled === true
 FAIL: window.bcalled === undefined
-FAIL: Boolean values correct (0)
-FAIL: Boolean values correct (3)
+PASS: Boolean values correct (0)
+PASS: Boolean values correct (3)
 PASS: Boolean values correct (1,2)
 PASS: Boolean values correct (4,5)
 PASS: References to Booleans correct (0,1)
 PASS: References to Booleans correct (3,4)
 PASS: References to Booleans correct (0,2)
 PASS: References to Booleans correct (3,5)
-FAIL: Number values correct (0)
+PASS: Number values correct (0)
 PASS: Number values correct (0,2)
 PASS: References to numbers correct (0,1)
 PASS: References to numbers correct (0,2)
-FAIL: String values correct (0)
+PASS: String values correct (0)
 PASS: String values correct (0,2)
 PASS: References to strings correct (0,1)
 PASS: References to strings correct (0,2)
-FAIL: String object properties not serialized
-FAIL: Number object properties not serialized
-FAIL: Boolean object properties not serialized
+PASS: String object properties not serialized
+PASS: Number object properties not serialized
+PASS: Boolean object properties not serialized
 PASS: Date values correct (0)
 PASS: Date values correct (1)
 FAIL: References to dates correct (0)
index 987ca8e..74f0567 100644 (file)
@@ -1,3 +1,29 @@
+2012-08-23  Christophe Dumez  <christophe.dumez@intel.com>
+
+        Serialization of JavaScript values does not appear to respect new HTML5 Structured Clone semantics
+        https://bugs.webkit.org/show_bug.cgi?id=65292
+
+        Reviewed by Oliver Hunt.
+
+        Add function to construct a StringObject from a JSValue.
+        Similar functions already exist for NumberObject and
+        BooleanObject for example.
+
+        Export several symbols so address linking errors in
+        WebCore.
+
+        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
+        * runtime/BooleanObject.h:
+        (BooleanObject):
+        * runtime/NumberObject.h:
+        (NumberObject):
+        (JSC):
+        * runtime/StringObject.cpp:
+        (JSC::constructString):
+        (JSC):
+        * runtime/StringObject.h:
+        (JSC):
+
 2012-08-22  Filip Pizlo  <fpizlo@apple.com>
 
         Array accesses should remember what kind of array they are predicted to access
index 8032ed1..b130a0b 100755 (executable)
@@ -1,6 +1,7 @@
 EXPORTS
 
     ??0ArrayBufferView@WTF@@IAE@V?$PassRefPtr@VArrayBuffer@WTF@@@1@I@Z
+    ??0BooleanObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@@Z
     ??0CString@WTF@@QAE@PBD@Z
     ??0CString@WTF@@QAE@PBDI@Z
     ??0Collator@WTF@@QAE@PBD@Z
@@ -107,6 +108,8 @@ EXPORTS
     ?constructArray@JSC@@YAPAVJSArray@1@PAVExecState@1@ABVArgList@1@@Z
     ?constructEmptyObject@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z
     ?constructFunctionSkippingEvalEnabledCheck@JSC@@YAPAVJSObject@1@PAVExecState@1@PAVJSGlobalObject@1@ABVArgList@1@ABVIdentifier@1@ABVUString@1@ABVTextPosition@WTF@@@Z
+    ?constructNumber@JSC@@YAPAVNumberObject@1@PAVExecState@1@PAVJSGlobalObject@1@VJSValue@1@@Z
+    ?constructString@JSC@@YAPAVStringObject@1@PAVExecState@1@PAVJSGlobalObject@1@VJSValue@1@@Z
     ?convertLatin1ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBEPBEPAPADPAD@Z
     ?convertUTF16ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPB_WPB_WPAPADPAD_N@Z
     ?convertUTF8ToUTF16@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBDPBDPAPA_WPA_W_N@Z
@@ -186,6 +189,7 @@ EXPORTS
     ?fillGetterPropertySlot@JSObject@JSC@@AAEXAAVPropertySlot@2@PAV?$WriteBarrierBase@W4Unknown@JSC@@@2@@Z
     ?finalize@WeakHandleOwner@JSC@@UAEXV?$Handle@W4Unknown@JSC@@@2@PAX@Z
     ?findAllocator@WeakSet@JSC@@AAEPAUFreeCell@WeakBlock@2@XZ
+    ?finishCreation@BooleanObject@JSC@@IAEXAAVJSGlobalData@2@@Z
     ?finishCreation@DateInstance@JSC@@IAEXAAVJSGlobalData@2@N@Z
     ?finishCreation@InternalFunction@JSC@@IAEXAAVJSGlobalData@2@ABVUString@2@@Z
     ?finishCreation@JSArray@JSC@@IAEXAAVJSGlobalData@2@I@Z
index 2704ff3..bd0f669 100644 (file)
@@ -27,8 +27,8 @@ namespace JSC {
 
     class BooleanObject : public JSWrapperObject {
     protected:
-        BooleanObject(JSGlobalData&, Structure*);
-        void finishCreation(JSGlobalData&);
+        JS_EXPORT_PRIVATE BooleanObject(JSGlobalData&, Structure*);
+        JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&);
 
     public:
         typedef JSWrapperObject Base;
@@ -40,7 +40,7 @@ namespace JSC {
             return boolean;
         }
         
-        static const ClassInfo s_info;
+        static JS_EXPORTDATA const ClassInfo s_info;
         
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
index 0733472..ed84207 100644 (file)
@@ -40,7 +40,7 @@ namespace JSC {
             return number;
         }
 
-        static const ClassInfo s_info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
         {
@@ -48,7 +48,7 @@ namespace JSC {
         }
     };
 
-    NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
+    JS_EXPORT_PRIVATE NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue);
 
 } // namespace JSC
 
index 1dac06b..3c037bc 100644 (file)
@@ -22,6 +22,7 @@
 #include "StringObject.h"
 
 #include "Error.h"
+#include "JSGlobalObject.h"
 #include "PropertyNameArray.h"
 
 namespace JSC {
@@ -143,4 +144,11 @@ void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, Proper
     return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
 }
 
+StringObject* constructString(ExecState* exec, JSGlobalObject* globalObject, JSValue string)
+{
+    StringObject* object = StringObject::create(exec, globalObject->stringObjectStructure());
+    object->setInternalValue(exec->globalData(), string);
+    return object;
+}
+
 } // namespace JSC
index 7089e89..f0c445e 100644 (file)
@@ -78,6 +78,8 @@ namespace JSC {
         return static_cast<StringObject*>(asObject(value));
     }
 
+    JS_EXPORT_PRIVATE StringObject* constructString(ExecState*, JSGlobalObject*, JSValue);
+
 } // namespace JSC
 
 #endif // StringObject_h
index 64796d3..09ca32b 100644 (file)
@@ -1,3 +1,23 @@
+2012-08-23  Christophe Dumez  <christophe.dumez@intel.com>
+
+        Serialization of JavaScript values does not appear to respect new HTML5 Structured Clone semantics
+        https://bugs.webkit.org/show_bug.cgi?id=65292
+
+        Reviewed by Oliver Hunt.
+
+        JSC now correctly serialize Boolean, Number and String objects as per
+        the structured clone algorithm specification. This patch reduces the
+        delta with the V8 implementation of SerializedScriptValue.
+
+        No new tests, already tested by fast/dom/Window/window-postmessage-clone.html
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore):
+        (WebCore::CloneSerializer::dumpStringObject):
+        (CloneSerializer):
+        (WebCore::CloneSerializer::dumpIfTerminal):
+        (WebCore::CloneDeserializer::readTerminal):
+
 2012-08-23  Joshua Bell  <jsbell@chromium.org>
 
         IndexedDB: Move onSuccess(IDBDatabaseBackendInterface) to IDBOpenDBRequest
index 9d5ca65..0bab786 100644 (file)
@@ -56,6 +56,7 @@
 #include <limits>
 #include <JavaScriptCore/APICast.h>
 #include <JavaScriptCore/APIShims.h>
+#include <runtime/BooleanObject.h>
 #include <runtime/DateInstance.h>
 #include <runtime/Error.h>
 #include <runtime/ExceptionHelpers.h>
@@ -108,6 +109,11 @@ enum SerializationTag {
     ArrayBufferTag = 21,
     ArrayBufferViewTag = 22,
     ArrayBufferTransferTag = 23,
+    TrueObjectTag = 24,
+    FalseObjectTag = 25,
+    StringObjectTag = 26,
+    EmptyStringObjectTag = 27,
+    NumberObjectTag = 28,
     ErrorTag = 255
 };
 
@@ -152,8 +158,10 @@ static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
  *
  * Initial version was 1.
  * Version 2. added the ObjectReferenceTag and support for serialization of cyclic graphs.
+ * Version 3. added the FalseObjectTag, TrueObjectTag, NumberObjectTag, StringObjectTag
+ * and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
  */
-static const unsigned int CurrentVersion = 2;
+static const unsigned int CurrentVersion = 3;
 static const unsigned int TerminatorTag = 0xFFFFFFFF;
 static const unsigned int StringPoolTag = 0xFFFFFFFE;
 
@@ -182,10 +190,14 @@ static const unsigned int StringPoolTag = 0xFFFFFFFE;
  *    | OneTag
  *    | FalseTag
  *    | TrueTag
+ *    | FalseObjectTag
+ *    | TrueObjectTag
  *    | DoubleTag <value:double>
+ *    | NumberObjectTag <value:double>
  *    | DateTag <value:double>
  *    | String
  *    | EmptyStringTag
+ *    | EmptyStringObjectTag
  *    | File
  *    | FileList
  *    | ImageData
@@ -200,6 +212,10 @@ static const unsigned int StringPoolTag = 0xFFFFFFFE;
  *      EmptyStringTag
  *      StringTag StringData
  *
+ * StringObject:
+ *      EmptyStringObjectTag
+ *      StringObjectTag StringData
+ *
  * StringData :-
  *      StringPoolTag <cpIndex:IndexType>
  *      (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
@@ -517,6 +533,16 @@ private:
         }
     }
 
+    void dumpStringObject(UString str)
+    {
+        if (str.isEmpty())
+            write(EmptyStringObjectTag);
+        else {
+            write(StringObjectTag);
+            write(str);
+        }
+    }
+
     bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code)
     {
         write(ArrayBufferViewTag);
@@ -585,6 +611,27 @@ private:
 
         if (value.isObject()) {
             JSObject* obj = asObject(value);
+            if (obj->inherits(&BooleanObject::s_info)) {
+                if (!startObjectInternal(obj)) // handle duplicates
+                    return true;
+                write(asBooleanObject(value)->internalValue().toBoolean() ? TrueObjectTag : FalseObjectTag);
+                return true;
+            }
+            if (obj->inherits(&StringObject::s_info)) {
+                if (!startObjectInternal(obj)) // handle duplicates
+                    return true;
+                UString str = asString(asStringObject(value)->internalValue())->value(m_exec);
+                dumpStringObject(str);
+                return true;
+            }
+            if (obj->inherits(&NumberObject::s_info)) {
+                if (!startObjectInternal(obj)) // handle duplicates
+                    return true;
+                write(NumberObjectTag);
+                NumberObject* obj = static_cast<NumberObject*>(asObject(value));
+                write(obj->internalValue().asNumber());
+                return true;
+            }
             if (obj->inherits(&JSFile::s_info)) {
                 write(FileTag);
                 write(toFile(obj));
@@ -1398,12 +1445,32 @@ private:
             return jsBoolean(false);
         case TrueTag:
             return jsBoolean(true);
+        case FalseObjectTag: {
+            BooleanObject* obj = BooleanObject::create(m_exec->globalData(), m_globalObject->booleanObjectStructure());
+            obj->setInternalValue(m_exec->globalData(), jsBoolean(false));
+            m_gcBuffer.append(obj);
+            return obj;
+        }
+        case TrueObjectTag: {
+            BooleanObject* obj = BooleanObject::create(m_exec->globalData(), m_globalObject->booleanObjectStructure());
+            obj->setInternalValue(m_exec->globalData(), jsBoolean(true));
+             m_gcBuffer.append(obj);
+            return obj;
+        }
         case DoubleTag: {
             double d;
             if (!read(d))
                 return JSValue();
             return jsNumber(d);
         }
+        case NumberObjectTag: {
+            double d;
+            if (!read(d))
+                return JSValue();
+            NumberObject* obj = constructNumber(m_exec, m_globalObject, jsNumber(d));
+            m_gcBuffer.append(obj);
+            return obj;
+        }
         case DateTag: {
             double d;
             if (!read(d))
@@ -1479,6 +1546,19 @@ private:
         }
         case EmptyStringTag:
             return jsEmptyString(&m_exec->globalData());
+        case StringObjectTag: {
+            CachedStringRef cachedString;
+            if (!readStringData(cachedString))
+                return JSValue();
+            StringObject* obj = constructString(m_exec, m_globalObject, cachedString->jsString(m_exec));
+            m_gcBuffer.append(obj);
+            return obj;
+        }
+        case EmptyStringObjectTag: {
+            StringObject* obj = constructString(m_exec, m_globalObject, jsEmptyString(&m_exec->globalData()));
+            m_gcBuffer.append(obj);
+            return obj;
+        }
         case RegExpTag: {
             CachedStringRef pattern;
             if (!readStringData(pattern))