Serialization of JavaScript values does not appear to respect new HTML5 Structured Clone semantics

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: http://svn.webkit.org/repository/webkit/trunk@126464 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f9ca5c4c
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
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)
......
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)
......
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
......
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
......
......@@ -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)
{
......
......@@ -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
......
......@@ -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
......@@ -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
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
......@@ -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))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment