New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make document url mutable and implement location.replace() #13418
Merged
+117
−156
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
eca8f1d
Make 'Document.url' field mutable
stshine 9863149
Move fragment navigation into Document object
stshine fb6cc15
Implement Location.replace
stshine 91f3d4f
Remove redundant url clones
stshine 5287e70
Minor fixes and update test expectations
stshine File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.
Move fragment navigation into Document object
Move the `check_and_scroll_fragment()` method into Document, make the mothod set the fragment of url after navigation, and use the `perform_a_scroll()` method to scroll rather than an individual method. Also removes the broken `Window.fragment` fields.
- Loading branch information
commit 986314904341fafa7caa1d32ee9d992d7c45282e
| @@ -18,7 +18,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; | ||
| use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilter; | ||
| use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods; | ||
| use dom::bindings::codegen::Bindings::TouchBinding::TouchMethods; | ||
| use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; | ||
| use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, WindowMethods}; | ||
| use dom::bindings::codegen::UnionTypes::NodeOrString; | ||
| use dom::bindings::error::{Error, ErrorResult, Fallible}; | ||
| use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId}; | ||
| @@ -600,6 +600,45 @@ impl Document { | ||
| } | ||
| } | ||
|
|
||
| /// https://html.spec.whatwg.org/multipage/#scroll-to-the-fragment-identifier | ||
| pub fn check_and_scroll_fragment(&self, fragment: &str) { | ||
| let target = self.find_fragment_node(fragment); | ||
|
||
|
|
||
| // Step 1 | ||
| self.set_target_element(target.r()); | ||
|
|
||
| let point = if fragment.is_empty() || fragment.to_lowercase() == "top" { | ||
stshine
Author
Contributor
|
||
| // FIXME(stshine): this should be the origin of the stacking context space, | ||
| // which may differ under the influence of writing mode. | ||
| Some((0.0, 0.0)) | ||
| } else { | ||
| target.r().map(|element| { | ||
| // FIXME(#8275, pcwalton): This is pretty bogus when multiple layers | ||
| // are involved. Really what needs to happen is that this needs to go | ||
| // through layout to ask which layer the element belongs to, and have | ||
| // it send the scroll message to the compositor. | ||
| let rect = element.upcast::<Node>().bounding_content_box(); | ||
|
|
||
| // In order to align with element edges, we snap to unscaled pixel | ||
| // boundaries, since the paint thread currently does the same for | ||
| // drawing elements. This is important for pages that require pixel | ||
| // perfect scroll positioning for proper display (like Acid2). Since | ||
| // we don't have the device pixel ratio here, this might not be | ||
| // accurate, but should work as long as the ratio is a whole number. | ||
| // Once #8275 is fixed this should actually take into account the | ||
| // real device pixel ratio. | ||
| (rect.origin.x.to_nearest_px() as f32, | ||
| rect.origin.y.to_nearest_px() as f32) | ||
| }) | ||
| }; | ||
|
|
||
| if let Some((x, y)) = point { | ||
| // Step 3 | ||
| self.window.perform_a_scroll(x, y, ScrollBehavior::Instant, | ||
| target.r()); | ||
| } | ||
| } | ||
|
|
||
| fn get_anchor_by_name(&self, name: &str) -> Option<Root<Element>> { | ||
| let check_anchor = |node: &HTMLAnchorElement| { | ||
| let elem = node.upcast::<Element>(); | ||
| @@ -59,7 +59,6 @@ use euclid::Rect; | ||
| use euclid::point::Point2D; | ||
| use hyper::header::{ContentType, HttpDate, LastModified}; | ||
| use hyper::header::ReferrerPolicy as ReferrerPolicyHeader; | ||
| use hyper::method::Method; | ||
| use hyper::mime::{Mime, SubLevel, TopLevel}; | ||
| use hyper_serde::Serde; | ||
| use ipc_channel::ipc::{self, IpcSender}; | ||
| @@ -91,7 +90,6 @@ use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, | ||
| use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent}; | ||
| use script_traits::webdriver_msg::WebDriverScriptCommand; | ||
| use servo_url::ServoUrl; | ||
| use std::borrow::ToOwned; | ||
| use std::cell::Cell; | ||
| use std::collections::{hash_map, HashMap, HashSet}; | ||
| use std::option::Option; | ||
| @@ -1231,20 +1229,8 @@ impl ScriptThread { | ||
| self.dom_manipulation_task_source.queue(handler, doc.window().upcast()).unwrap(); | ||
|
|
||
| if let Some(fragment) = doc.url().fragment() { | ||
| self.check_and_scroll_fragment(fragment, pipeline, &doc); | ||
| } | ||
| } | ||
|
|
||
| fn check_and_scroll_fragment(&self, fragment: &str, pipeline_id: PipelineId, doc: &Document) { | ||
| match doc.find_fragment_node(fragment) { | ||
| Some(ref node) => { | ||
| doc.set_target_element(Some(&node)); | ||
| self.scroll_fragment_point(pipeline_id, &node); | ||
| } | ||
| None => { | ||
| doc.set_target_element(None); | ||
| } | ||
| } | ||
| doc.check_and_scroll_fragment(fragment); | ||
| }; | ||
stshine
Author
Contributor
|
||
| } | ||
|
|
||
| fn collect_reports(&self, reports_chan: ReportsChan) { | ||
| @@ -1826,26 +1812,6 @@ impl ScriptThread { | ||
| } | ||
| } | ||
|
|
||
| fn scroll_fragment_point(&self, pipeline_id: PipelineId, element: &Element) { | ||
| // FIXME(#8275, pcwalton): This is pretty bogus when multiple layers are involved. | ||
| // Really what needs to happen is that this needs to go through layout to ask which | ||
| // layer the element belongs to, and have it send the scroll message to the | ||
| // compositor. | ||
| let rect = element.upcast::<Node>().bounding_content_box(); | ||
|
|
||
| // In order to align with element edges, we snap to unscaled pixel boundaries, since the | ||
| // paint thread currently does the same for drawing elements. This is important for pages | ||
| // that require pixel perfect scroll positioning for proper display (like Acid2). Since we | ||
| // don't have the device pixel ratio here, this might not be accurate, but should work as | ||
| // long as the ratio is a whole number. Once #8275 is fixed this should actually take into | ||
| // account the real device pixel ratio. | ||
| let point = Point2D::new(rect.origin.x.to_nearest_px() as f32, | ||
| rect.origin.y.to_nearest_px() as f32); | ||
|
|
||
| let message = ConstellationMsg::ScrollFragmentPoint(pipeline_id, point, false); | ||
| self.constellation_chan.send(message).unwrap(); | ||
| } | ||
|
|
||
| /// Reflows non-incrementally, rebuilding the entire layout tree in the process. | ||
| fn rebuild_and_force_reflow(&self, document: &Document, reason: ReflowReason) { | ||
| let window = window_from_node(&*document); | ||
| @@ -1987,25 +1953,6 @@ impl ScriptThread { | ||
| frame_id: Option<FrameId>, | ||
| load_data: LoadData, | ||
| replace: bool) { | ||
| // Step 7. | ||
| { | ||
| let nurl = &load_data.url; | ||
| if let Some(fragment) = nurl.fragment() { | ||
| let document = match self.documents.borrow().find_document(parent_pipeline_id) { | ||
| Some(document) => document, | ||
| None => return warn!("Message sent to closed pipeline {}.", parent_pipeline_id), | ||
| }; | ||
| let nurl = nurl.as_url().unwrap(); | ||
| if let Some(url) = document.url().as_url() { | ||
| if &url[..Position::AfterQuery] == &nurl[..Position::AfterQuery] && | ||
| load_data.method == Method::Get { | ||
| self.check_and_scroll_fragment(fragment, parent_pipeline_id, &document); | ||
| return; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| match frame_id { | ||
| Some(frame_id) => { | ||
| if let Some(iframe) = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id) { | ||
| @@ -2032,13 +1979,6 @@ impl ScriptThread { | ||
| ReflowQueryType::NoQuery, | ||
| ReflowReason::WindowResize); | ||
|
|
||
| let fragment_node = window.steal_fragment_name() | ||
| .and_then(|name| document.find_fragment_node(&*name)); | ||
| match fragment_node { | ||
| Some(ref node) => self.scroll_fragment_point(pipeline_id, &node), | ||
| None => {} | ||
| } | ||
|
|
||
| // http://dev.w3.org/csswg/cssom-view/#resizing-viewports | ||
| if size_type == WindowSizeType::Resize { | ||
| let uievent = UIEvent::new(&window, | ||
| @@ -2118,8 +2058,6 @@ impl ScriptThread { | ||
|
|
||
| // https://html.spec.whatwg.org/multipage/#the-end steps 3-4. | ||
| document.process_deferred_scripts(); | ||
|
|
||
| window.set_fragment_name(final_url.fragment().map(str::to_owned)); | ||
| } | ||
|
|
||
| fn handle_css_error_reporting(&self, pipeline_id: PipelineId, filename: String, | ||
ProTip!
Use n and p to navigate between commits in a pull request.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Does .r() not work here?