WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
add [CallWith] support for attributes and cleanup from review comments
bug-76035-20120115203328.patch (text/plain), 46.46 KB, created by
Pablo Flouret
on 2012-01-15 20:33:29 PST
(
hide
)
Description:
add [CallWith] support for attributes and cleanup from review comments
Filename:
MIME Type:
Creator:
Pablo Flouret
Created:
2012-01-15 20:33:29 PST
Size:
46.46 KB
patch
obsolete
>Subversion Revision: 104981 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 1a8f1315499983d69391fec4df98a38559a3893d..35a41491a2917aff1d355933041e0dd4912e631f 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,62 @@ >+2012-01-14 Pablo Flouret <pablof@motorola.com> >+ >+ Add state attribute to history's dom interface. >+ https://bugs.webkit.org/show_bug.cgi?id=76035 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ To be able to keep a single deserialization of the state object, the >+ deserialized script value is kept alongside the serialized state object >+ in the HistoryItem, which also takes care of the deserialization. To be >+ able to do the deserialization there instead of doing it in the binding >+ code, [CallWith] support for attributes was added in the JS/V8 idl code >+ generators. >+ >+ Tests: fast/loader/stateobjects/pushstate-state-attribute-object-types.html >+ fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization.html >+ >+ * bindings/js/JSHistoryCustom.cpp: >+ * bindings/js/ScriptValue.cpp: >+ (WebCore::ScriptValue::ScriptValue): >+ * bindings/js/ScriptValue.h: >+ * bindings/scripts/CodeGeneratorJS.pm: >+ (GenerateImplementation): >+ (GenerateAttributeCallWith): >+ * bindings/scripts/CodeGeneratorV8.pm: >+ (GenerateNormalAttrGetter): >+ (GenerateNormalAttrSetter): >+ (GenerateAttributeCallWith): >+ * bindings/scripts/test/JS/JSTestObj.cpp: >+ (WebCore::jsTestObjWithScriptStateAttribute): >+ (WebCore::jsTestObjWithScriptExecutionContextAttribute): >+ (WebCore::jsTestObjWithScriptStateAttributeRaises): >+ (WebCore::jsTestObjWithScriptExecutionContextAttributeRaises): >+ (WebCore::setJSTestObjWithScriptStateAttribute): >+ (WebCore::setJSTestObjWithScriptExecutionContextAttribute): >+ (WebCore::setJSTestObjWithScriptStateAttributeRaises): >+ (WebCore::setJSTestObjWithScriptExecutionContextAttributeRaises): >+ * bindings/scripts/test/JS/JSTestObj.h: >+ * bindings/scripts/test/TestObj.idl: >+ * bindings/scripts/test/V8/V8TestObj.cpp: >+ (WebCore::TestObjInternal::withScriptStateAttributeAttrGetter): >+ (WebCore::TestObjInternal::withScriptStateAttributeAttrSetter): >+ (WebCore::TestObjInternal::withScriptExecutionContextAttributeAttrGetter): >+ (WebCore::TestObjInternal::withScriptExecutionContextAttributeAttrSetter): >+ (WebCore::TestObjInternal::withScriptStateAttributeRaisesAttrGetter): >+ (WebCore::TestObjInternal::withScriptStateAttributeRaisesAttrSetter): >+ (WebCore::TestObjInternal::withScriptExecutionContextAttributeRaisesAttrGetter): >+ (WebCore::TestObjInternal::withScriptExecutionContextAttributeRaisesAttrSetter): >+ * history/HistoryItem.cpp: >+ (WebCore::HistoryItem::reset): >+ (WebCore::HistoryItem::setURL): >+ (WebCore::HistoryItem::setStateObject): >+ (WebCore::HistoryItem::getOrCreateDeserializedStateObject): >+ * history/HistoryItem.h: >+ * page/History.cpp: >+ (WebCore::History::state): >+ * page/History.h: >+ * page/History.idl: >+ > 2012-01-13 Pablo Flouret <pablof@motorola.com> > > Fix compilation errors on build-webkit --debug --no-video on mac. >diff --git a/Source/WebCore/bindings/js/JSHistoryCustom.cpp b/Source/WebCore/bindings/js/JSHistoryCustom.cpp >index 72ea5424c7c12f3a672bc7d739e11dedfb4818c7..0a169224d882d16380c09914b71bef7b988cfbfa 100644 >--- a/Source/WebCore/bindings/js/JSHistoryCustom.cpp >+++ b/Source/WebCore/bindings/js/JSHistoryCustom.cpp >@@ -31,6 +31,7 @@ > > #include "Frame.h" > #include "History.h" >+#include "ScriptValue.h" > #include "SerializedScriptValue.h" > #include <runtime/JSFunction.h> > >diff --git a/Source/WebCore/bindings/js/ScriptValue.cpp b/Source/WebCore/bindings/js/ScriptValue.cpp >index bfa93aa8707b09a9e3b4b63137a2bd3e8e632f2c..a6f629bb9cbf4b7484cdfb60a7bfef06d6a5ec88 100644 >--- a/Source/WebCore/bindings/js/ScriptValue.cpp >+++ b/Source/WebCore/bindings/js/ScriptValue.cpp >@@ -44,6 +44,14 @@ using namespace JSC; > > namespace WebCore { > >+ScriptValue::ScriptValue(const ScriptValue& value) >+{ >+ if (!value.m_value) >+ return; >+ >+ m_value = JSC::Strong<JSC::Unknown>(value.m_value); >+} >+ > bool ScriptValue::getString(ScriptState* scriptState, String& result) const > { > if (!m_value) >diff --git a/Source/WebCore/bindings/js/ScriptValue.h b/Source/WebCore/bindings/js/ScriptValue.h >index a4d597a917566e9c21057e5d5fd43377ac59e9a4..a91a7d70386ac90559232c2b6a46efc1643cb283 100644 >--- a/Source/WebCore/bindings/js/ScriptValue.h >+++ b/Source/WebCore/bindings/js/ScriptValue.h >@@ -49,6 +49,7 @@ class ScriptValue { > public: > ScriptValue() { } > ScriptValue(JSC::JSGlobalData& globalData, JSC::JSValue value) : m_value(globalData, value) {} >+ ScriptValue(const ScriptValue&); > virtual ~ScriptValue() {} > > JSC::JSValue jsValue() const { return m_value.get(); } >diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm >index 04fa7bb67ecd217c698f5a84659f0cb5673fcdbc..8270fa66bc6acf5387998381d49124aabdec5520 100644 >--- a/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm >+++ b/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm >@@ -1764,7 +1764,11 @@ sub GenerateImplementation > # Once JSDOMWrappers have a back-pointer to the globalObject we can pass castedThis->globalObject() > push(@implContent, " return JS" . $constructorType . "::getConstructor(exec, castedThis);\n"); > } elsif (!@{$attribute->getterExceptions}) { >- push(@implContent, " UNUSED_PARAM(exec);\n"); >+ my $callWith = $attribute->signature->extendedAttributes->{"CallWith"}; >+ my $callWithArg = ""; >+ >+ push(@implContent, " UNUSED_PARAM(exec);\n") if (!$callWith); >+ > my $cacheIndex = 0; > if ($attribute->signature->extendedAttributes->{"CachedAttribute"}) { > $cacheIndex = $currentCachedAttribute; >@@ -1773,14 +1777,19 @@ sub GenerateImplementation > push(@implContent, " return cachedValue;\n"); > } > >+ if ($callWith) { >+ $callWithArg = GenerateAttributeCallWith($callWith, \@implContent); >+ } >+ > if ($svgListPropertyType) { >- push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "castedThis->impl()->$implGetterFunctionName()", "castedThis") . ";\n"); >+ push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "castedThis->impl()->$implGetterFunctionName($callWithArg)", "castedThis") . ";\n"); > } elsif ($svgPropertyOrListPropertyType) { > push(@implContent, " $svgPropertyOrListPropertyType& impl = castedThis->impl()->propertyReference();\n"); > if ($svgPropertyOrListPropertyType eq "float") { # Special case for JSSVGNumber > push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl", "castedThis") . ";\n"); > } else { >- push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl.$implGetterFunctionName()", "castedThis") . ";\n"); >+ push(@implContent, " JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl.$implGetterFunctionName($callWithArg)", "castedThis") . ";\n"); >+ > } > } else { > my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute); >@@ -1793,6 +1802,10 @@ sub GenerateImplementation > $functionName = "impl->${functionName}"; > } > >+ if ($callWith) { >+ unshift(@arguments, $callWithArg); >+ } >+ > my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, "${functionName}(" . join(", ", @arguments) . ")", "castedThis"); > push(@implContent, " $implClassName* impl = static_cast<$implClassName*>(castedThis->impl());\n"); > if ($codeGenerator->IsSVGAnimatedType($type)) { >@@ -1807,13 +1820,21 @@ sub GenerateImplementation > push(@implContent, " return result;\n"); > > } else { >+ my $callWith = $attribute->signature->extendedAttributes->{"CallWith"}; >+ my @arguments = ("ec"); >+ > push(@implContent, " ExceptionCode ec = 0;\n"); >+ >+ if ($callWith) { >+ unshift(@arguments, GenerateAttributeCallWith($callWith, \@implContent)); >+ } >+ > if ($svgPropertyOrListPropertyType) { > push(@implContent, " $svgPropertyOrListPropertyType impl(*castedThis->impl());\n"); >- push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl.$implGetterFunctionName(ec)", "castedThis") . ";\n"); >+ push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl.$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n"); > } else { > push(@implContent, " $implClassName* impl = static_cast<$implClassName*>(castedThis->impl());\n"); >- push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl->$implGetterFunctionName(ec)", "castedThis") . ";\n"); >+ push(@implContent, " JSC::JSValue result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "impl->$implGetterFunctionName(" . join(", ", @arguments) . ")", "castedThis") . ";\n"); > } > > push(@implContent, " setDOMException(exec, ec);\n"); >@@ -2009,6 +2030,17 @@ sub GenerateImplementation > } else { > $functionName = "impl->${functionName}"; > } >+ >+ my $callWith = $attribute->signature->extendedAttributes->{"CallWith"}; >+ if ($callWith) { >+ if ($callWith eq "ScriptState") { >+ unshift(@arguments, "exec"); >+ } else { >+ push(@implContent, " ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n"); >+ unshift(@arguments, "scriptContext"); >+ } >+ } >+ > push(@arguments, "ec") if @{$attribute->setterExceptions}; > push(@implContent, " ${functionName}(" . join(", ", @arguments) . ");\n"); > push(@implContent, " setDOMException(exec, ec);\n") if @{$attribute->setterExceptions}; >@@ -2361,6 +2393,24 @@ sub GenerateImplementation > push(@implContent, "\n#endif // ${conditionalString}\n") if $conditionalString; > } > >+sub GenerateAttributeCallWith >+{ >+ my $callWith = shift; >+ my $outputArray = shift; >+ my $callWithArg = "COMPILE_ASSERT(false)"; >+ >+ if ($callWith eq "ScriptState") { >+ $callWithArg = "exec"; >+ } elsif ($callWith eq "ScriptExecutionContext") { >+ push(@$outputArray, " ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();\n"); >+ push(@$outputArray, " if (!scriptContext)\n"); >+ push(@$outputArray, " return jsUndefined();\n"); >+ $callWithArg = "scriptContext"; >+ } >+ >+ return $callWithArg; >+} >+ > sub GenerateArgumentsCountCheck > { > my $outputArray = shift; >diff --git a/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm b/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm >index 7b184a7a1c84fec041e896ced7f0509853413d79..6cadff28e4fdde703f47fbd3a318f3cfe7489e05 100644 >--- a/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm >+++ b/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm >@@ -899,8 +899,19 @@ END > > my $returnType = GetTypeFromSignature($attribute->signature); > my $getterString; >+ my $hasScriptState = 0; >+ > if ($getterStringUsesImp) { > my ($functionName, @arguments) = $codeGenerator->GetterExpression(\%implIncludes, $interfaceName, $attribute); >+ >+ my $callWith = $attribute->signature->extendedAttributes->{"CallWith"}; >+ my $callWithArg; >+ >+ if ($callWith) { >+ ($callWithArg, $hasScriptState) = GenerateAttributeCallWith($callWith, \@implContentDecls, 1); >+ push(@arguments, $callWithArg); >+ } >+ > push(@arguments, "ec") if $useExceptions; > if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) { > my $implementedBy = $attribute->signature->extendedAttributes->{"ImplementedBy"}; >@@ -930,6 +941,12 @@ END > push(@implContentDecls, " $nativeType v = $getterString;\n"); > } > push(@implContentDecls, GenerateSetDOMException(" ")); >+ >+ if ($hasScriptState) { >+ push(@implContentDecls, " if (state.hadException())\n"); >+ push(@implContentDecls, " return throwError(state.exception());\n"); >+ } >+ > $result = "v"; > $result .= ".release()" if (IsRefPtrType($returnType)); > } else { >@@ -1122,6 +1139,7 @@ END > } > > my $useExceptions = 1 if @{$attribute->setterExceptions}; >+ my $hasScriptState = 0; > > if ($useExceptions) { > AddToImplIncludes("ExceptionCode.h"); >@@ -1152,6 +1170,15 @@ END > push(@implContentDecls, ");\n"); > } else { > my ($functionName, @arguments) = $codeGenerator->SetterExpression(\%implIncludes, $interfaceName, $attribute); >+ >+ my $callWith = $attribute->signature->extendedAttributes->{"CallWith"}; >+ my $callWithArg; >+ >+ if ($callWith) { >+ ($callWithArg, $hasScriptState) = GenerateAttributeCallWith($callWith, \@implContentDecls, 0); >+ unshift(@arguments, $callWithArg); >+ } >+ > push(@arguments, $result); > push(@arguments, "ec") if $useExceptions; > if ($attribute->signature->extendedAttributes->{"ImplementedBy"}) { >@@ -1454,6 +1481,30 @@ END > push(@implContentDecls, "#endif // ${conditionalString}\n\n") if $conditionalString; > } > >+sub GenerateAttributeCallWith >+{ >+ my $callWith = shift; >+ my $outputArray = shift; >+ my $returnIfNullScriptContext = shift; >+ my $callWithArg = "COMPILE_ASSERT(false)"; >+ my $hasScriptState = 0; >+ >+ if ($callWith eq "ScriptState") { >+ push(@$outputArray, " EmptyScriptState state;\n"); >+ $callWithArg = "&state"; >+ $hasScriptState = 1; >+ } elsif ($callWith eq "ScriptExecutionContext") { >+ push(@$outputArray, " ScriptExecutionContext* scriptContext = getScriptExecutionContext();\n"); >+ if ($returnIfNullScriptContext) { >+ push(@$outputArray, " if (!scriptContext)\n"); >+ push(@$outputArray, " return v8::Undefined();\n"); >+ } >+ $callWithArg = "scriptContext"; >+ } >+ >+ return ($callWithArg, $hasScriptState); >+} >+ > sub GenerateArgumentsCountCheck > { > my $function = shift; >diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp >index e91a114038966fc72d8957647b25655a5e9032f5..e488a518b324022be3ab39eb6cb2aea77906f7dc 100644 >--- a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp >+++ b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp >@@ -107,6 +107,10 @@ static const HashTableValue JSTestObjTableValues[] = > { "stringAttrWithGetterException", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringAttrWithGetterException), (intptr_t)setJSTestObjStringAttrWithGetterException, NoIntrinsic }, > { "stringAttrWithSetterException", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjStringAttrWithSetterException), (intptr_t)setJSTestObjStringAttrWithSetterException, NoIntrinsic }, > { "customAttr", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCustomAttr), (intptr_t)setJSTestObjCustomAttr, NoIntrinsic }, >+ { "withScriptStateAttribute", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjWithScriptStateAttribute), (intptr_t)setJSTestObjWithScriptStateAttribute, NoIntrinsic }, >+ { "withScriptExecutionContextAttribute", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjWithScriptExecutionContextAttribute), (intptr_t)setJSTestObjWithScriptExecutionContextAttribute, NoIntrinsic }, >+ { "withScriptStateAttributeRaises", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjWithScriptStateAttributeRaises), (intptr_t)setJSTestObjWithScriptStateAttributeRaises, NoIntrinsic }, >+ { "withScriptExecutionContextAttributeRaises", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjWithScriptExecutionContextAttributeRaises), (intptr_t)setJSTestObjWithScriptExecutionContextAttributeRaises, NoIntrinsic }, > { "scriptStringAttr", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjScriptStringAttr), (intptr_t)0, NoIntrinsic }, > #if ENABLE(Condition1) > { "conditionalAttr1", DontDelete, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjConditionalAttr1), (intptr_t)setJSTestObjConditionalAttr1, NoIntrinsic }, >@@ -139,7 +143,7 @@ static const HashTableValue JSTestObjTableValues[] = > { 0, 0, 0, 0, NoIntrinsic } > }; > >-static const HashTable JSTestObjTable = { 136, 127, JSTestObjTableValues, 0 }; >+static const HashTable JSTestObjTable = { 137, 127, JSTestObjTableValues, 0 }; > /* Hash table for constructor */ > > static const HashTableValue JSTestObjConstructorTableValues[] = >@@ -631,6 +635,52 @@ JSValue jsTestObjCustomAttr(ExecState* exec, JSValue slotBase, const Identifier& > } > > >+JSValue jsTestObjWithScriptStateAttribute(ExecState* exec, JSValue slotBase, const Identifier&) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ JSValue result = jsNumber(impl->withScriptStateAttribute(exec)); >+ return result; >+} >+ >+ >+JSValue jsTestObjWithScriptExecutionContextAttribute(ExecState* exec, JSValue slotBase, const Identifier&) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); >+ ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); >+ if (!scriptContext) >+ return jsUndefined(); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ JSValue result = (impl->withScriptExecutionContextAttribute(scriptContext).hasNoValue() ? jsNull() : impl->withScriptExecutionContextAttribute(scriptContext).jsValue()); >+ return result; >+} >+ >+ >+JSValue jsTestObjWithScriptStateAttributeRaises(ExecState* exec, JSValue slotBase, const Identifier&) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); >+ ExceptionCode ec = 0; >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ JSC::JSValue result = (impl->withScriptStateAttributeRaises(exec, ec).hasNoValue() ? jsNull() : impl->withScriptStateAttributeRaises(exec, ec).jsValue()); >+ setDOMException(exec, ec); >+ return result; >+} >+ >+ >+JSValue jsTestObjWithScriptExecutionContextAttributeRaises(ExecState* exec, JSValue slotBase, const Identifier&) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); >+ ExceptionCode ec = 0; >+ ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); >+ if (!scriptContext) >+ return jsUndefined(); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ JSC::JSValue result = (impl->withScriptExecutionContextAttributeRaises(scriptContext, ec).hasNoValue() ? jsNull() : impl->withScriptExecutionContextAttributeRaises(scriptContext, ec).jsValue()); >+ setDOMException(exec, ec); >+ return result; >+} >+ >+ > JSValue jsTestObjScriptStringAttr(ExecState* exec, JSValue slotBase, const Identifier&) > { > JSTestObj* castedThis = static_cast<JSTestObj*>(asObject(slotBase)); >@@ -1017,6 +1067,44 @@ void setJSTestObjCustomAttr(ExecState* exec, JSObject* thisObject, JSValue value > } > > >+void setJSTestObjWithScriptStateAttribute(ExecState* exec, JSObject* thisObject, JSValue value) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ impl->setWithScriptStateAttribute(exec, value.toInt32(exec)); >+} >+ >+ >+void setJSTestObjWithScriptExecutionContextAttribute(ExecState* exec, JSObject* thisObject, JSValue value) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); >+ impl->setWithScriptExecutionContextAttribute(scriptContext, exec->globalData(), value); >+} >+ >+ >+void setJSTestObjWithScriptStateAttributeRaises(ExecState* exec, JSObject* thisObject, JSValue value) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ ExceptionCode ec = 0; >+ impl->setWithScriptStateAttributeRaises(exec, exec->globalData(), value, ec); >+ setDOMException(exec, ec); >+} >+ >+ >+void setJSTestObjWithScriptExecutionContextAttributeRaises(ExecState* exec, JSObject* thisObject, JSValue value) >+{ >+ JSTestObj* castedThis = static_cast<JSTestObj*>(thisObject); >+ TestObj* impl = static_cast<TestObj*>(castedThis->impl()); >+ ExceptionCode ec = 0; >+ ScriptExecutionContext* scriptContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); >+ impl->setWithScriptExecutionContextAttributeRaises(scriptContext, exec->globalData(), value, ec); >+ setDOMException(exec, ec); >+} >+ >+ > #if ENABLE(Condition1) > void setJSTestObjConditionalAttr1(ExecState* exec, JSObject* thisObject, JSValue value) > { >diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h >index ae4041de67a9bceaf5b4b136977ce8759416ff23..45f9fb7317cb3f512375dd73a320d811c915a2f8 100644 >--- a/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h >+++ b/Source/WebCore/bindings/scripts/test/JS/JSTestObj.h >@@ -249,6 +249,14 @@ JSC::JSValue jsTestObjStringAttrWithSetterException(JSC::ExecState*, JSC::JSValu > void setJSTestObjStringAttrWithSetterException(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); > JSC::JSValue jsTestObjCustomAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); > void setJSTestObjCustomAttr(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); >+JSC::JSValue jsTestObjWithScriptStateAttribute(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); >+void setJSTestObjWithScriptStateAttribute(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); >+JSC::JSValue jsTestObjWithScriptExecutionContextAttribute(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); >+void setJSTestObjWithScriptExecutionContextAttribute(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); >+JSC::JSValue jsTestObjWithScriptStateAttributeRaises(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); >+void setJSTestObjWithScriptStateAttributeRaises(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); >+JSC::JSValue jsTestObjWithScriptExecutionContextAttributeRaises(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); >+void setJSTestObjWithScriptExecutionContextAttributeRaises(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); > JSC::JSValue jsTestObjScriptStringAttr(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); > JSC::JSValue jsTestObjConditionalAttr1(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); > void setJSTestObjConditionalAttr1(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); >diff --git a/Source/WebCore/bindings/scripts/test/TestObj.idl b/Source/WebCore/bindings/scripts/test/TestObj.idl >index ed338c6b21d718bcef3328c14122fab382648485..0bab693609411013a76bc6e18f74e8a2f0ef32b5 100644 >--- a/Source/WebCore/bindings/scripts/test/TestObj.idl >+++ b/Source/WebCore/bindings/scripts/test/TestObj.idl >@@ -109,6 +109,13 @@ module test { > raises(DOMException); > [CallWith=ScriptExecutionContext] void withScriptExecutionContext(); > >+ attribute [CallWith=ScriptState] long withScriptStateAttribute; >+ attribute [CallWith=ScriptExecutionContext] DOMObject withScriptExecutionContextAttribute; >+ attribute [CallWith=ScriptState] DOMObject withScriptStateAttributeRaises >+ getter raises(DOMException); >+ attribute [CallWith=ScriptExecutionContext] DOMObject withScriptExecutionContextAttributeRaises >+ getter raises(DOMException); >+ > // 'Optional' extended attribute > void methodWithOptionalArg(in [Optional] long opt); > void methodWithNonOptionalArgAndOptionalArg(in long nonOpt, in [Optional] long opt); >diff --git a/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp b/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp >index 17c0a03ad2ae74a49bbb11bc76191f8ba17e2ae2..5cb5028b7f8ef2fcc3f5ca52519734d440f50137 100644 >--- a/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp >+++ b/Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp >@@ -32,6 +32,7 @@ > #include "ScriptArguments.h" > #include "ScriptCallStack.h" > #include "ScriptCallStackFactory.h" >+#include "ScriptValue.h" > #include "SerializedScriptValue.h" > #include "V8Binding.h" > #include "V8BindingMacros.h" >@@ -514,6 +515,102 @@ static void stringAttrWithSetterExceptionAttrSetter(v8::Local<v8::String> name, > return; > } > >+static v8::Handle<v8::Value> withScriptStateAttributeAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptStateAttribute._get"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ EmptyScriptState state; >+ return v8::Integer::New(imp->withScriptStateAttribute(&state)); >+} >+ >+static void withScriptStateAttributeAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptStateAttribute._set"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ int v = toInt32(value); >+ EmptyScriptState state; >+ imp->setWithScriptStateAttribute(&state, v); >+ return; >+} >+ >+static v8::Handle<v8::Value> withScriptExecutionContextAttributeAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptExecutionContextAttribute._get"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ ScriptExecutionContext* scriptContext = getScriptExecutionContext(); >+ if (!scriptContext) >+ return v8::Undefined(); >+ return imp->withScriptExecutionContextAttribute(scriptContext).v8Value(); >+} >+ >+static void withScriptExecutionContextAttributeAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptExecutionContextAttribute._set"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ ScriptValue v = ScriptValue(value); >+ ScriptExecutionContext* scriptContext = getScriptExecutionContext(); >+ imp->setWithScriptExecutionContextAttribute(scriptContext, WTF::getPtr(v)); >+ return; >+} >+ >+static v8::Handle<v8::Value> withScriptStateAttributeRaisesAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptStateAttributeRaises._get"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ ExceptionCode ec = 0; >+ EmptyScriptState state; >+ ScriptValue v = imp->withScriptStateAttributeRaises(&state, ec); >+ if (UNLIKELY(ec)) { >+ V8Proxy::setDOMException(ec); >+ return v8::Handle<v8::Value>(); >+ } >+ if (state.hadException()) >+ return throwError(state.exception()); >+ return v.release().v8Value(); >+} >+ >+static void withScriptStateAttributeRaisesAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptStateAttributeRaises._set"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ ScriptValue v = ScriptValue(value); >+ ExceptionCode ec = 0; >+ EmptyScriptState state; >+ imp->setWithScriptStateAttributeRaises(&state, WTF::getPtr(v), ec); >+ if (UNLIKELY(ec)) >+ V8Proxy::setDOMException(ec); >+ return; >+} >+ >+static v8::Handle<v8::Value> withScriptExecutionContextAttributeRaisesAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptExecutionContextAttributeRaises._get"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ ExceptionCode ec = 0; >+ ScriptExecutionContext* scriptContext = getScriptExecutionContext(); >+ if (!scriptContext) >+ return v8::Undefined(); >+ ScriptValue v = imp->withScriptExecutionContextAttributeRaises(scriptContext, ec); >+ if (UNLIKELY(ec)) { >+ V8Proxy::setDOMException(ec); >+ return v8::Handle<v8::Value>(); >+ } >+ return v.release().v8Value(); >+} >+ >+static void withScriptExecutionContextAttributeRaisesAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) >+{ >+ INC_STATS("DOM.TestObj.withScriptExecutionContextAttributeRaises._set"); >+ TestObj* imp = V8TestObj::toNative(info.Holder()); >+ ScriptValue v = ScriptValue(value); >+ ExceptionCode ec = 0; >+ ScriptExecutionContext* scriptContext = getScriptExecutionContext(); >+ imp->setWithScriptExecutionContextAttributeRaises(scriptContext, WTF::getPtr(v), ec); >+ if (UNLIKELY(ec)) >+ V8Proxy::setDOMException(ec); >+ return; >+} >+ > static v8::Handle<v8::Value> scriptStringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) > { > INC_STATS("DOM.TestObj.scriptStringAttr._get"); >@@ -1522,6 +1619,14 @@ static const BatchedAttribute TestObjAttrs[] = { > {"stringAttrWithSetterException", TestObjInternal::stringAttrWithSetterExceptionAttrGetter, TestObjInternal::stringAttrWithSetterExceptionAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, > // Attribute 'customAttr' (Type: 'attribute' ExtAttr: 'Custom') > {"customAttr", V8TestObj::customAttrAccessorGetter, V8TestObj::customAttrAccessorSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, >+ // Attribute 'withScriptStateAttribute' (Type: 'attribute' ExtAttr: 'CallWith') >+ {"withScriptStateAttribute", TestObjInternal::withScriptStateAttributeAttrGetter, TestObjInternal::withScriptStateAttributeAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, >+ // Attribute 'withScriptExecutionContextAttribute' (Type: 'attribute' ExtAttr: 'CallWith') >+ {"withScriptExecutionContextAttribute", TestObjInternal::withScriptExecutionContextAttributeAttrGetter, TestObjInternal::withScriptExecutionContextAttributeAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, >+ // Attribute 'withScriptStateAttributeRaises' (Type: 'attribute' ExtAttr: 'CallWith') >+ {"withScriptStateAttributeRaises", TestObjInternal::withScriptStateAttributeRaisesAttrGetter, TestObjInternal::withScriptStateAttributeRaisesAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, >+ // Attribute 'withScriptExecutionContextAttributeRaises' (Type: 'attribute' ExtAttr: 'CallWith') >+ {"withScriptExecutionContextAttributeRaises", TestObjInternal::withScriptExecutionContextAttributeRaisesAttrGetter, TestObjInternal::withScriptExecutionContextAttributeRaisesAttrSetter, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, > // Attribute 'scriptStringAttr' (Type: 'readonly attribute' ExtAttr: 'ConvertScriptString') > {"scriptStringAttr", TestObjInternal::scriptStringAttrAttrGetter, 0, 0 /* no data */, static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None), 0 /* on instance */}, > #if ENABLE(Condition1) >diff --git a/Source/WebCore/history/HistoryItem.cpp b/Source/WebCore/history/HistoryItem.cpp >index 21c81ede7efe261ad869751dcf9e8f2a40a5e892..e3c95970d56e4ad3fd6b5c7ee405dafe28edd836 100644 >--- a/Source/WebCore/history/HistoryItem.cpp >+++ b/Source/WebCore/history/HistoryItem.cpp >@@ -31,6 +31,7 @@ > #include "IconDatabase.h" > #include "PageCache.h" > #include "ResourceRequest.h" >+#include "ScriptValue.h" > #include "SerializedScriptValue.h" > #include "SharedBuffer.h" > #include <stdio.h> >@@ -200,6 +201,7 @@ void HistoryItem::reset() > m_itemSequenceNumber = generateSequenceNumber(); > > m_stateObject = 0; >+ m_deserializedStateObject.clear(); > m_documentSequenceNumber = generateSequenceNumber(); > > m_formData = 0; >@@ -282,6 +284,7 @@ void HistoryItem::setURL(const KURL& url) > pageCache()->remove(this); > setURLString(url.string()); > clearDocumentState(); >+ m_deserializedStateObject.clear(); > } > > void HistoryItem::setOriginalURLString(const String& urlString) >@@ -456,6 +459,21 @@ void HistoryItem::setIsTargetItem(bool flag) > void HistoryItem::setStateObject(PassRefPtr<SerializedScriptValue> object) > { > m_stateObject = object; >+ m_deserializedStateObject.clear(); >+} >+ >+ScriptValue* HistoryItem::getOrCreateDeserializedStateObject(ScriptState* scriptState) >+{ >+ if (!m_deserializedStateObject) { >+ if (!m_stateObject) >+ m_deserializedStateObject = adoptPtr(new ScriptValue()); >+ else { >+ ScriptValue deserializedStateObject = ScriptValue::deserialize(scriptState, m_stateObject.get()); >+ m_deserializedStateObject = adoptPtr(new ScriptValue(deserializedStateObject)); >+ } >+ } >+ >+ return m_deserializedStateObject.get(); > } > > void HistoryItem::addChildItem(PassRefPtr<HistoryItem> child) >diff --git a/Source/WebCore/history/HistoryItem.h b/Source/WebCore/history/HistoryItem.h >index 8619d0c346bf86b9e729269629d3825b702f6b73..64f4b76634408de4533abdc47e0aeff53c7e0a01 100644 >--- a/Source/WebCore/history/HistoryItem.h >+++ b/Source/WebCore/history/HistoryItem.h >@@ -28,6 +28,7 @@ > > #include "IntPoint.h" > #include "PlatformString.h" >+#include "ScriptState.h" > #include <wtf/HashMap.h> > #include <wtf/OwnPtr.h> > #include <wtf/PassOwnPtr.h> >@@ -53,6 +54,7 @@ class HistoryItem; > class Image; > class KURL; > class ResourceRequest; >+class ScriptValue; > class SerializedScriptValue; > > typedef Vector<RefPtr<HistoryItem> > HistoryItemVector; >@@ -141,6 +143,7 @@ public: > > void setStateObject(PassRefPtr<SerializedScriptValue> object); > SerializedScriptValue* stateObject() const { return m_stateObject.get(); } >+ ScriptValue* getOrCreateDeserializedStateObject(ScriptState*); > > void setItemSequenceNumber(long long number) { m_itemSequenceNumber = number; } > long long itemSequenceNumber() const { return m_itemSequenceNumber; } >@@ -270,6 +273,7 @@ private: > > // Support for HTML5 History > RefPtr<SerializedScriptValue> m_stateObject; >+ OwnPtr<ScriptValue> m_deserializedStateObject; > > // info used to repost form data > RefPtr<FormData> m_formData; >diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp >index 1f5a39f287584f7c2748b33e1099e664d192ae68..ac685108d9556bc42fd0df7ccf0c8c09b1524ade 100644 >--- a/Source/WebCore/page/History.cpp >+++ b/Source/WebCore/page/History.cpp >@@ -32,8 +32,10 @@ > #include "Frame.h" > #include "FrameLoader.h" > #include "FrameLoaderClient.h" >+#include "HistoryController.h" > #include "HistoryItem.h" > #include "Page.h" >+#include "ScriptValue.h" > #include "SecurityOrigin.h" > #include "SerializedScriptValue.h" > #include <wtf/MainThread.h> >@@ -107,6 +109,16 @@ KURL History::urlForState(const String& urlString) > return KURL(baseURL, urlString); > } > >+ScriptValue History::state(ScriptState* scriptState) const >+{ >+ if (!m_frame) >+ return ScriptValue(); >+ >+ HistoryItem* historyItem = m_frame->loader()->history()->currentItem(); >+ >+ return historyItem ? *historyItem->getOrCreateDeserializedStateObject(scriptState) : ScriptValue(); >+} >+ > void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const String& title, const String& urlString, StateObjectType stateObjectType, ExceptionCode& ec) > { > if (!m_frame || !m_frame->page()) >diff --git a/Source/WebCore/page/History.h b/Source/WebCore/page/History.h >index bd50fccd2b861d9e6418e974f42dfb2b2b5f91ce..df6fd1673a76c7805bbc2b9af1fde89e769bdbea 100644 >--- a/Source/WebCore/page/History.h >+++ b/Source/WebCore/page/History.h >@@ -28,6 +28,8 @@ > > #include "DOMWindowProperty.h" > #include "KURL.h" >+#include "ScriptState.h" >+#include "ScriptValue.h" > #include <wtf/Forward.h> > #include <wtf/PassRefPtr.h> > #include <wtf/RefCounted.h> >@@ -56,6 +58,9 @@ public: > StateObjectPush, > StateObjectReplace > }; >+ >+ ScriptValue state(ScriptState*) const; >+ > void stateObjectAdded(PassRefPtr<SerializedScriptValue>, const String& title, const String& url, StateObjectType, ExceptionCode&); > > private: >diff --git a/Source/WebCore/page/History.idl b/Source/WebCore/page/History.idl >index ff3701ed276d4f5698da6a0530e066380a33b1c1..0d0709d487d387dc5b12fd895fda1a713c08836b 100644 >--- a/Source/WebCore/page/History.idl >+++ b/Source/WebCore/page/History.idl >@@ -37,6 +37,7 @@ module window { > OmitConstructor > ] History { > readonly attribute unsigned long length; >+ readonly attribute [CallWith=ScriptState] DOMObject state; > > [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void back(); > [DoNotCheckDomainSecurity, CallWith=ScriptExecutionContext] void forward(); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 1037d0a3587ce0d0afb651da1b9a38bd54578332..04d37554ce05fa16889eaeb8bbfaaf1020021956 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,15 @@ >+2012-01-14 Pablo Flouret <pablof@motorola.com> >+ >+ Add state attribute to history's dom interface. >+ https://bugs.webkit.org/show_bug.cgi?id=76035 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/loader/stateobjects/pushstate-state-attribute-object-types-expected.txt: Added. >+ * fast/loader/stateobjects/pushstate-state-attribute-object-types.html: Added. >+ * fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization-expected.txt: Added. >+ * fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization.html: Added. >+ > 2012-01-13 Simon Fraser <simon.fraser@apple.com> > > Add new baselines for various compositing tests which didn't have Mac results. >diff --git a/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-object-types-expected.txt b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-object-types-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..c1a87a78fbc6893f0c6e1f99584cedb53eb86611 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-object-types-expected.txt >@@ -0,0 +1,15 @@ >+This test calls pushState with state objects of all the different object types supported by the HTML5 "internal structured cloning algorithm" and makes sure the state attribute returns the expected objects. >+ >+State is initially null (type object) >+State pushed - undefined (type undefined) >+State pushed - null (type object) >+State pushed - false (type boolean) >+State pushed - true (type boolean) >+State pushed - 42 (type number) >+State pushed - String (type string) >+State pushed - 0 (type object) >+State pushed - /foo/gi (type object) >+State pushed - (type object) >+State pushed - [object Object] (type object) >+State pushed - [object ImageData] (type object) >+ >diff --git a/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-object-types.html b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-object-types.html >new file mode 100644 >index 0000000000000000000000000000000000000000..f35a3d79336178bc2bc4a02f2e289903f4f9b074 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-object-types.html >@@ -0,0 +1,57 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script> >+ >+if (window.layoutTestController) { >+ layoutTestController.clearBackForwardList(); >+ layoutTestController.dumpAsText(); >+} >+ >+function log(txt) >+{ >+ document.getElementById("logger").appendChild(document.createTextNode(txt + "\n")); >+} >+ >+function runTest() >+{ >+ log("State is initially " + history.state + " (type " + typeof history.state + ")"); >+ pushAndTestState(undefined, "undefined entry"); >+ pushAndTestState(null, "null entry"); >+ pushAndTestState(false, "false entry"); >+ pushAndTestState(true, "true entry"); >+ pushAndTestState(42, "Number entry"); >+ pushAndTestState("String", "String entry"); >+ pushAndTestState(new Date(0), "Date entry"); >+ pushAndTestState(new RegExp("foo", "gi"), "RegExp entry"); >+ pushAndTestState(new Array, "Array entry"); >+ pushAndTestState(new Object, "Object entry"); >+ pushAndTestState(document.createElement("canvas").getContext("2d").createImageData(10,10), "ImageData entry"); >+ >+/* The following are not yet well enough supported in WebKit to meaningfully test here: >+ history.pushAndState([Blob], "Blob entry"); >+ history.pushAndState([File], "File entry"); >+ history.pushAndState([FileList], "FileList entry"); >+*/ >+} >+ >+function pushAndTestState(data, title) >+{ >+ history.pushState(data, title); >+ var state = history.state; >+ >+ if (state instanceof Date) >+ log("State pushed - " + state.getTime() + " (type " + typeof state + ")"); >+ else >+ log("State pushed - " + state + " (type " + typeof state + ")"); >+} >+ >+</script> >+<body onload="runTest()"> >+<p> >+This test calls pushState with state objects of all the different object types supported by the >+HTML5 "internal structured cloning algorithm" and makes sure the state attribute returns the expected objects. >+</p> >+<pre id="logger"></pre> >+</body> >+</html> >diff --git a/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization-expected.txt b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..1fd75d7fa0805966b5cd8eb3299adbd303102e72 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization-expected.txt >@@ -0,0 +1,17 @@ >+Make sure the same deserialization of the state object is used every time (both in the history object and popstate events). >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS history.state !== stateObject is true >+PASS history.state === stateObject is true >+ >+Inside popstate event >+ >+PASS history.state !== stateObject is true >+PASS event.state !== stateObject is true >+FAIL event.state === history.state should be true. Was false. >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization.html b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization.html >new file mode 100644 >index 0000000000000000000000000000000000000000..5ebebcf63e52ddb0105af2174be3456d5340fd84 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/pushstate-state-attribute-only-one-deserialization.html >@@ -0,0 +1,60 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <script src="../../js/resources/js-test-pre.js"></script> >+</head/> >+<body> >+<p id=description> >+</p> >+<div id="console"></div> >+<script> >+ description("Make sure the same deserialization of the state object is used every time (both in the history object and popstate events)."); >+ >+ if (window.layoutTestController) { >+ layoutTestController.clearBackForwardList(); >+ layoutTestController.dumpAsText(); >+ layoutTestController.waitUntilDone(); >+ } >+ >+ window.jsTestIsAsync = true; >+ >+ // Create a new object. >+ var stateObject = ["a"]; >+ >+ // Use it as the state object in a replaceState. This clones the object. >+ history.replaceState(stateObject, null, null); >+ >+ // Since the actual history.state is a structured clone, it should not match our original object. >+ shouldBeTrue("history.state !== stateObject"); >+ >+ // Now let's refetch a copy of history.state to store; >+ stateObject = history.state; >+ >+ // Our reference and the history.state itself should be the same. This is now Adam's original assertion. >+ shouldBeTrue("history.state === stateObject"); >+ >+ // Now let's do a pushstate to add a history entry. >+ history.pushState(null, null, null); >+ >+ // Now add a handler for the popstate event. >+ window.onpopstate = function(event) { >+ debug("\nInside popstate event\n"); >+ // Our stored reference to stateObject will not match the current state object, as it is a structured clone of the history item's state object. >+ shouldBeTrue("history.state !== stateObject"); >+ // Our stored reference to stateObject will not match the state object in this pop state event, as it is the same as history.state which is a structured clone of the history item's state object. >+ shouldBeTrue("event.state !== stateObject"); >+ // The event's state object and the current state object should match. >+ shouldBeTrue("event.state === history.state"); // This fails for now, needs to be fixed. >+ >+ var s = document.createElement("script"); >+ s.src = "../../js/resources/js-test-post.js"; >+ document.body.appendChild(s); >+ setTimeout(finishJSTest, 0); >+ } >+ >+ // Now let's go back to our original history entry which has a state object that we've stored a reference to already. >+ // This will fire our popstate event handler above. >+ history.back(); >+</script> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 76035
:
121987
|
122471
|
122518
|
122586
|
122857
|
122860
|
123150
|
124811
|
124856
|
125274
|
126022