WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-77493-20120210153107.patch (text/plain), 20.49 KB, created by
Pablo Flouret
on 2012-02-10 15:31:09 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Pablo Flouret
Created:
2012-02-10 15:31:09 PST
Size:
20.49 KB
patch
obsolete
>Subversion Revision: 107109 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 6bc0c8d5a63ef0eb831632aa1b86a1fd794cc7d8..d6c60532e8f376fc800d8c7e0d10aa31080d970a 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,34 @@ >+2012-02-10 Pablo Flouret <pablof@motorola.com> >+ >+ PopStateEvent.state should use the same object as history.state >+ https://bugs.webkit.org/show_bug.cgi?id=77493 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Tests: fast/loader/stateobjects/state-attribute-history-getter.html >+ fast/loader/stateobjects/state-attribute-popstate-event.html >+ >+ * bindings/js/JSPopStateEventCustom.cpp: >+ (WebCore::JSPopStateEvent::state): >+ * bindings/v8/custom/V8PopStateEventCustom.cpp: >+ (WebCore::V8PopStateEvent::stateAccessorGetter): >+ * dom/Document.cpp: >+ (WebCore::Document::enqueuePopstateEvent): >+ * dom/PopStateEvent.cpp: >+ (WebCore::PopStateEvent::PopStateEvent): >+ (WebCore::PopStateEvent::create): >+ * dom/PopStateEvent.h: >+ (WebCore): >+ (PopStateEvent): >+ (WebCore::PopStateEvent::history): >+ * dom/PopStateEvent.idl: >+ * page/History.cpp: >+ (WebCore::History::stateChanged): >+ (WebCore): >+ (WebCore::History::isSameAsCurrentState): >+ * page/History.h: >+ (History): >+ > 2012-02-08 Dirk Schulze <krit@webkit.org> > > viewBox on nested SVG causes wrong content size for relative values >diff --git a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp >index 38edfb68dd61f69128039804867c5d160957a2a1..2539031d2fd1227d047ec92e01f85ccb86223f4b 100644 >--- a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp >+++ b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp >@@ -30,6 +30,8 @@ > > #include "config.h" > >+#include "History.h" >+#include "JSHistory.h" > #include "JSPopStateEvent.h" > > using namespace JSC; >@@ -38,13 +40,41 @@ namespace WebCore { > > JSValue JSPopStateEvent::state(ExecState* exec) const > { >+ JSValue cachedValue = m_state.get(); >+ if (!cachedValue.isEmpty()) >+ return cachedValue; >+ > PopStateEvent* event = static_cast<PopStateEvent*>(impl()); >- SerializedScriptValue* serializedState = event->serializedState(); >- if (serializedState) >- return serializedState->deserialize(exec, globalObject(), 0); >- if (!event->state().hasNoValue()) >- return event->state().jsValue(); >- return jsNull(); >+ JSValue result = jsNull(); >+ History* history; >+ bool isSameState; >+ >+ if (!event->state().hasNoValue()) { >+ result = event->state().jsValue(); >+ goto saveResultAndReturnIt; >+ } >+ >+ history = event->history(); >+ if (!history || !event->serializedState()) >+ goto saveResultAndReturnIt; >+ >+ // There's no cached value from a previous invocation, nor a state value was provided by the >+ // event, but there is a history object, so first we need to see if the state object has been >+ // deserialized through the history object already. >+ // The current history state object might've changed in the meantime, so we need to take care >+ // of using the correct one, and always share the same deserialization with history.state. >+ >+ isSameState = history->isSameAsCurrentState(event->serializedState()); >+ >+ if (isSameState) { >+ JSHistory* jsHistory = static_cast<JSHistory*>(toJS(exec, globalObject(), history).asCell()); >+ result = jsHistory->state(exec); >+ } else >+ result = event->serializedState()->deserialize(exec, globalObject(), 0); >+ >+saveResultAndReturnIt: >+ const_cast<JSPopStateEvent*>(this)->m_state.set(exec->globalData(), this, result); >+ return result; > } > > } // namespace WebCore >diff --git a/Source/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp b/Source/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp >index 57ce238fee42e0a6b203adfe240af89f4b597ff7..2ddcfa7824052a29615ff27fa116bae5538139c3 100644 >--- a/Source/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp >+++ b/Source/WebCore/bindings/v8/custom/V8PopStateEventCustom.cpp >@@ -31,8 +31,10 @@ > #include "config.h" > #include "V8PopStateEvent.h" > >+#include "History.h" > #include "PopStateEvent.h" > #include "SerializedScriptValue.h" >+#include "V8History.h" > #include "V8Proxy.h" > > namespace WebCore { >@@ -41,13 +43,50 @@ v8::Handle<v8::Value> V8PopStateEvent::stateAccessorGetter(v8::Local<v8::String> > { > INC_STATS("DOM.PopStateEvent.state"); > >+ v8::Handle<v8::String> propertyName = v8::String::NewSymbol("state"); >+ v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(propertyName); >+ >+ if (!result.IsEmpty()) >+ return result; >+ > PopStateEvent* event = V8PopStateEvent::toNative(info.Holder()); >- SerializedScriptValue* serializedState = event->serializedState(); >- if (serializedState) >- return serializedState->deserialize(); >- if (!event->state().hasNoValue()) >- return event->state().v8Value(); >- return v8::Null(); >+ v8::Handle<v8::Object> v8History; >+ History* history; >+ bool isSameState; >+ result = v8::Null(); >+ >+ if (!event->state().hasNoValue()) { >+ result = event->state().v8Value(); >+ goto saveResultAndReturnIt; >+ } >+ >+ history = event->history(); >+ if (!history || !event->serializedState()) >+ goto saveResultAndReturnIt; >+ >+ // There's no cached value from a previous invocation, nor a state value was provided by the >+ // event, but there is a history object, so first we need to see if the state object has been >+ // deserialized through the history object already. >+ // The current history state object might've changed in the meantime, so we need to take care >+ // of using the correct one, and always share the same deserialization with history.state. >+ >+ isSameState = history->isSameAsCurrentState(event->serializedState()); >+ >+ if (isSameState) { >+ v8History = toV8(history).As<v8::Object>(); >+ if (!history->stateChanged()) { >+ result = v8History->GetHiddenValue(propertyName); >+ if (!result.IsEmpty()) >+ goto saveResultAndReturnIt; >+ } >+ result = event->serializedState()->deserialize(); >+ v8History->SetHiddenValue(propertyName, result); >+ } else >+ result = event->serializedState()->deserialize(); >+ >+saveResultAndReturnIt: >+ info.Holder()->SetHiddenValue(propertyName, result); >+ return result; > } > > } // namespace WebCore >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 39a97b2c4d8a5be363b581a0a50a7d3c59817228..9905628c6817f7134906912103d062a6b442ab93 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -78,6 +78,7 @@ > #include "GeolocationController.h" > #include "HashChangeEvent.h" > #include "HistogramSupport.h" >+#include "History.h" > #include "HTMLAllCollection.h" > #include "HTMLAnchorElement.h" > #include "HTMLBodyElement.h" >@@ -5013,7 +5014,7 @@ void Document::enqueueHashchangeEvent(const String& oldURL, const String& newURL > void Document::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject) > { > // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously >- dispatchWindowEvent(PopStateEvent::create(stateObject)); >+ dispatchWindowEvent(PopStateEvent::create(stateObject, domWindow() ? domWindow()->history() : 0)); > } > > void Document::addMediaCanStartListener(MediaCanStartListener* listener) >diff --git a/Source/WebCore/dom/PopStateEvent.cpp b/Source/WebCore/dom/PopStateEvent.cpp >index 8d0cb729249f5c2efdf9d2fb21cea24e167f8bbf..d1e0c758a49766c6f6ff156e83d6a66657d6b149 100644 >--- a/Source/WebCore/dom/PopStateEvent.cpp >+++ b/Source/WebCore/dom/PopStateEvent.cpp >@@ -28,6 +28,8 @@ > #include "PopStateEvent.h" > > #include "EventNames.h" >+#include "History.h" >+#include "SerializedScriptValue.h" > > namespace WebCore { > >@@ -38,6 +40,7 @@ PopStateEventInit::PopStateEventInit() > PopStateEvent::PopStateEvent() > : Event(eventNames().popstateEvent, false, true) > , m_serializedState(0) >+ , m_history(0) > { > } > >@@ -45,19 +48,14 @@ PopStateEvent::PopStateEvent(const AtomicString& type, const PopStateEventInit& > : Event(type, initializer) > , m_state(initializer.state) > , m_serializedState(0) >+ , m_history(0) > { > } > >-PopStateEvent::PopStateEvent(const ScriptValue& state) >- : Event(eventNames().popstateEvent, false, true) >- , m_state(state) >- , m_serializedState(0) >-{ >-} >- >-PopStateEvent::PopStateEvent(PassRefPtr<SerializedScriptValue> serializedState) >+PopStateEvent::PopStateEvent(PassRefPtr<SerializedScriptValue> serializedState, PassRefPtr<History> history) > : Event(eventNames().popstateEvent, false, true) > , m_serializedState(serializedState) >+ , m_history(history) > { > } > >@@ -70,14 +68,9 @@ PassRefPtr<PopStateEvent> PopStateEvent::create() > return adoptRef(new PopStateEvent); > } > >-PassRefPtr<PopStateEvent> PopStateEvent::create(const ScriptValue& state) >-{ >- return adoptRef(new PopStateEvent(state)); >-} >- >-PassRefPtr<PopStateEvent> PopStateEvent::create(PassRefPtr<SerializedScriptValue> serializedState) >+PassRefPtr<PopStateEvent> PopStateEvent::create(PassRefPtr<SerializedScriptValue> serializedState, PassRefPtr<History> history) > { >- return adoptRef(new PopStateEvent(serializedState)); >+ return adoptRef(new PopStateEvent(serializedState, history)); > } > > PassRefPtr<PopStateEvent> PopStateEvent::create(const AtomicString& type, const PopStateEventInit& initializer) >diff --git a/Source/WebCore/dom/PopStateEvent.h b/Source/WebCore/dom/PopStateEvent.h >index 5125fc1ca8a08e40849b128a7aefa18753ff30bb..8de0ae6d1cc57a1bacef65dd9793243ac8e53000 100644 >--- a/Source/WebCore/dom/PopStateEvent.h >+++ b/Source/WebCore/dom/PopStateEvent.h >@@ -29,7 +29,6 @@ > > #include "Event.h" > #include "ScriptValue.h" >-#include "SerializedScriptValue.h" > > namespace WebCore { > >@@ -39,27 +38,30 @@ struct PopStateEventInit : public EventInit { > ScriptValue state; > }; > >+class History; >+class SerializedScriptValue; >+ > class PopStateEvent : public Event { > public: > virtual ~PopStateEvent(); > static PassRefPtr<PopStateEvent> create(); >- static PassRefPtr<PopStateEvent> create(const ScriptValue&); >- static PassRefPtr<PopStateEvent> create(PassRefPtr<SerializedScriptValue>); >+ static PassRefPtr<PopStateEvent> create(PassRefPtr<SerializedScriptValue>, PassRefPtr<History>); > static PassRefPtr<PopStateEvent> create(const AtomicString&, const PopStateEventInit&); > > SerializedScriptValue* serializedState() const { return m_serializedState.get(); } > ScriptValue state() const { return m_state; } >+ History* history() const { return m_history.get(); } > > virtual const AtomicString& interfaceName() const; > > private: > PopStateEvent(); > PopStateEvent(const AtomicString&, const PopStateEventInit&); >- explicit PopStateEvent(const ScriptValue&); >- explicit PopStateEvent(PassRefPtr<SerializedScriptValue>); >+ explicit PopStateEvent(PassRefPtr<SerializedScriptValue>, PassRefPtr<History>); > > ScriptValue m_state; > RefPtr<SerializedScriptValue> m_serializedState; >+ RefPtr<History> m_history; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/dom/PopStateEvent.idl b/Source/WebCore/dom/PopStateEvent.idl >index 6326a9d7a4601d286be178fee6cb955fa71b1872..c9343ca80ed179242b1db4f5b167ee8c6603a57d 100644 >--- a/Source/WebCore/dom/PopStateEvent.idl >+++ b/Source/WebCore/dom/PopStateEvent.idl >@@ -30,7 +30,7 @@ module events { > interface [ > ConstructorTemplate=Event > ] PopStateEvent : Event { >- readonly attribute [InitializedByEventConstructor, CustomGetter] DOMObject state; >+ readonly attribute [InitializedByEventConstructor, CachedAttribute, CustomGetter] DOMObject state; > }; > #endif > >diff --git a/Source/WebCore/page/History.cpp b/Source/WebCore/page/History.cpp >index a1f9a05f661c13ff2ad6d629ea87ae74e85a2afc..f38a8c92b111ba855b78c0a50683e75cedc0f957 100644 >--- a/Source/WebCore/page/History.cpp >+++ b/Source/WebCore/page/History.cpp >@@ -77,6 +77,11 @@ bool History::stateChanged() const > return m_lastStateObjectRequested != stateInternal(); > } > >+bool History::isSameAsCurrentState(SerializedScriptValue* state) const >+{ >+ return state == stateInternal(); >+} >+ > void History::back() > { > go(-1); >diff --git a/Source/WebCore/page/History.h b/Source/WebCore/page/History.h >index bd6f6aa21315fa55feedc4527d0d32cb390c2e58..889c37410c6b7ca94184d3615a2f87dcc7b14ecb 100644 >--- a/Source/WebCore/page/History.h >+++ b/Source/WebCore/page/History.h >@@ -45,7 +45,6 @@ public: > > unsigned length() const; > SerializedScriptValue* state(); >- bool stateChanged() const; > void back(); > void forward(); > void go(int distance); >@@ -54,6 +53,9 @@ public: > void forward(ScriptExecutionContext*); > void go(ScriptExecutionContext*, int distance); > >+ bool stateChanged() const; >+ bool isSameAsCurrentState(SerializedScriptValue*) const; >+ > enum StateObjectType { > StateObjectPush, > StateObjectReplace >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index f214d17dc782ce3afc1e818b726ed3af3f104489..fa715bc12fdfc5be14c2708947fecc8bbef9f89c 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,17 @@ >+2012-02-10 Pablo Flouret <pablof@motorola.com> >+ >+ PopStateEvent.state should use the same object as history.state >+ https://bugs.webkit.org/show_bug.cgi?id=77493 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/loader/stateobjects/state-attribute-history-getter-expected.txt: Added. >+ * fast/loader/stateobjects/state-attribute-history-getter.html: Added. >+ * fast/loader/stateobjects/state-attribute-only-one-deserialization-expected.txt: >+ * fast/loader/stateobjects/state-attribute-only-one-deserialization.html: >+ * fast/loader/stateobjects/state-attribute-popstate-event-expected.txt: Added. >+ * fast/loader/stateobjects/state-attribute-popstate-event.html: Added. >+ > 2012-02-08 Julien Chaffraix <jchaffraix@webkit.org> > > Unreviewed gardening. >diff --git a/LayoutTests/fast/loader/stateobjects/state-attribute-history-getter-expected.txt b/LayoutTests/fast/loader/stateobjects/state-attribute-history-getter-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..04753a159d84e63d98f97b33cdf222b2b23c807a >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/state-attribute-history-getter-expected.txt >@@ -0,0 +1,4 @@ >+Check that setting a custom getter for history.state works correctly and that PopStateEvent.state still has a correct value. >+ >+PASS >+ >diff --git a/LayoutTests/fast/loader/stateobjects/state-attribute-history-getter.html b/LayoutTests/fast/loader/stateobjects/state-attribute-history-getter.html >new file mode 100644 >index 0000000000000000000000000000000000000000..c9a17b043cbb4d72fe4a3bc6f13c40dde77f37b7 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/state-attribute-history-getter.html >@@ -0,0 +1,50 @@ >+<!DOCTYPE html> >+<p>Check that setting a custom getter for history.state works correctly and that PopStateEvent.state still has a correct value.</p> >+<pre id=log></pre> >+<script> >+function log(msg) { >+ document.querySelector("#log").innerHTML += msg + "<br>"; >+} >+ >+if (window.layoutTestController) { >+ layoutTestController.clearBackForwardList(); >+ layoutTestController.dumpAsText(); >+ layoutTestController.waitUntilDone(); >+} >+ >+function test() { >+ if (!("state" in history)) { >+ log("FAIL: history.state is not defined"); >+ return; >+ } >+ >+ try { >+ Object.defineProperty(history, "state", { get: function () { return "oh hai" } }); >+ } catch (e) { >+ // history.state is not configurable in JSC. >+ log(e.name == "TypeError" ? "PASS" : ("FAIL: unexpected exception: " + e)); >+ layoutTestController.notifyDone(); >+ return; >+ } >+ >+ if (history.state !== "oh hai") { >+ log('FAIL: history.state != "oh hai"'); >+ } >+ >+ history.pushState(42, "", ""); >+ history.pushState(43, "", ""); >+ >+ window.onpopstate = function(e) { >+ if (e.state !== 42) >+ log("FAIL: e.state expected 42, was " + e.state + " (of type " + typeof e.state + ")"); >+ else >+ log("PASS"); >+ if (window.layoutTestController) >+ layoutTestController.notifyDone(); >+ } >+ >+ history.back(); >+} >+ >+test(); >+</script> >diff --git a/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization-expected.txt b/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization-expected.txt >index e3d0117f99dd8faba6bd5244fd745c74da69dfc0..159155e9bd4549ed65d6ac8acfa6860e9ad348bb 100644 >--- a/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization-expected.txt >+++ b/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization-expected.txt >@@ -12,7 +12,7 @@ Inside popstate event > > PASS history.state !== stateObject is true > PASS popStateEvent.state !== stateObject is true >-FAIL popStateEvent.state === history.state should be true. Was false. >+PASS popStateEvent.state === history.state is true > PASS successfullyParsed is true > > TEST COMPLETE >diff --git a/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization.html b/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization.html >index 083721d3834896002b6bf5b23591102b1c3feadc..95294957b32209ce31bc0f92c4be21aac4875272 100644 >--- a/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization.html >+++ b/LayoutTests/fast/loader/stateobjects/state-attribute-only-one-deserialization.html >@@ -45,7 +45,7 @@ > // 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("popStateEvent.state !== stateObject"); > // The event's state object and the current state object should match. >- shouldBeTrue("popStateEvent.state === history.state"); // This fails for now, needs to be fixed. >+ shouldBeTrue("popStateEvent.state === history.state"); > > var s = document.createElement("script"); > s.src = "../../js/resources/js-test-post.js"; >diff --git a/LayoutTests/fast/loader/stateobjects/state-attribute-popstate-event-expected.txt b/LayoutTests/fast/loader/stateobjects/state-attribute-popstate-event-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..5aabc3b041c9f790357a4f4dcdb6997fe96c7971 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/state-attribute-popstate-event-expected.txt >@@ -0,0 +1,19 @@ >+Check that PopStateEvent.state always has a correct value. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+ >+PASS history.state is defined. >+Push state 1 >+Push state 2 >+PASS history.state is 2 >+Go back >+PASS popStateEvent.state is 1 >+PASS history.state is 1 >+Push state 3 >+PASS popStateEvent.state is 1 >+PASS history.state is 3 >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/fast/loader/stateobjects/state-attribute-popstate-event.html b/LayoutTests/fast/loader/stateobjects/state-attribute-popstate-event.html >new file mode 100644 >index 0000000000000000000000000000000000000000..0d9bfb577e9b1adf686dc085d050403263432517 >--- /dev/null >+++ b/LayoutTests/fast/loader/stateobjects/state-attribute-popstate-event.html >@@ -0,0 +1,45 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <script src="../../js/resources/js-test-pre.js"></script> >+</head/> >+<body> >+<script> >+ description("Check that PopStateEvent.state always has a correct value."); >+ >+ window.jsTestIsAsync = true; >+ if (window.layoutTestController) { >+ layoutTestController.clearBackForwardList(); >+ layoutTestController.waitUntilDone(); >+ } >+ >+ shouldBeDefined("history.state"); >+ >+ debug("Push state 1"); >+ history.pushState(1, "", ""); >+ debug("Push state 2"); >+ history.pushState(2, "", ""); >+ shouldEvaluateTo("history.state", 2); >+ >+ var popStateEvent; >+ window.onpopstate = function(e) { >+ popStateEvent = e; >+ shouldEvaluateTo("popStateEvent.state", 1); >+ shouldEvaluateTo("history.state", 1); >+ >+ debug("Push state 3"); >+ history.pushState(3, "", ""); >+ shouldEvaluateTo("popStateEvent.state", 1); >+ shouldEvaluateTo("history.state", 3); >+ >+ var s = document.createElement("script"); >+ s.src = "../../js/resources/js-test-post.js"; >+ document.body.appendChild(s); >+ setTimeout(finishJSTest, 0); >+ } >+ >+ debug("Go back"); >+ 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 77493
:
126201
|
126594
|
127283
|
128324