mirror of
https://github.com/servo/servo.git
synced 2025-08-02 12:10:29 +01:00
Auto merge of #9887 - schuster:HTMLHyperlinkElementUtils, r=jdm
Implement HTMLHyperlinkElementUtils for HTMLAnchorElement Fixes #7857 Origin is omitted since it's still not available in rust-url, but since the previous PR also left it out, I'm assuming that's okay. Please let me know if there are any style issues. There might be more concise ways to do the pattern matching that I don't know about, I guessed at the indentation style in one or two places. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9887) <!-- Reviewable:end -->
This commit is contained in:
commit
9a8d62286c
26 changed files with 369 additions and 1606 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
use dom::activation::Activatable;
|
||||
use dom::attr::AttrValue;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||
use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding::HTMLAnchorElementMethods;
|
||||
|
@ -12,6 +13,7 @@ use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
|||
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||
use dom::bindings::inheritance::Castable;
|
||||
use dom::bindings::js::{JS, MutNullableHeap, Root};
|
||||
use dom::bindings::str::USVString;
|
||||
use dom::document::Document;
|
||||
use dom::domtokenlist::DOMTokenList;
|
||||
use dom::element::Element;
|
||||
|
@ -21,16 +23,19 @@ use dom::htmlelement::HTMLElement;
|
|||
use dom::htmlimageelement::HTMLImageElement;
|
||||
use dom::mouseevent::MouseEvent;
|
||||
use dom::node::{Node, document_from_node, window_from_node};
|
||||
use dom::urlhelper::UrlHelper;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use num::ToPrimitive;
|
||||
use std::default::Default;
|
||||
use string_cache::Atom;
|
||||
use url::{Url, UrlParser};
|
||||
use util::str::DOMString;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct HTMLAnchorElement {
|
||||
htmlelement: HTMLElement,
|
||||
rel_list: MutNullableHeap<JS<DOMTokenList>>,
|
||||
url: DOMRefCell<Option<Url>>,
|
||||
}
|
||||
|
||||
impl HTMLAnchorElement {
|
||||
|
@ -41,6 +46,7 @@ impl HTMLAnchorElement {
|
|||
htmlelement:
|
||||
HTMLElement::new_inherited(localName, prefix, document),
|
||||
rel_list: Default::default(),
|
||||
url: DOMRefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +57,37 @@ impl HTMLAnchorElement {
|
|||
let element = HTMLAnchorElement::new_inherited(localName, prefix, document);
|
||||
Node::reflect_node(box element, document, HTMLAnchorElementBinding::Wrap)
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#concept-hyperlink-url-set
|
||||
fn set_url(&self) {
|
||||
let attribute = self.upcast::<Element>().get_attribute(&ns!(), &atom!("href"));
|
||||
*self.url.borrow_mut() = attribute.and_then(|attribute| {
|
||||
let document = document_from_node(self);
|
||||
let mut parser = UrlParser::new();
|
||||
parser.base_url(document.url());
|
||||
parser.parse(&attribute.value()).ok()
|
||||
});
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#reinitialise-url
|
||||
fn reinitialize_url(&self) {
|
||||
// Step 1.
|
||||
match *self.url.borrow() {
|
||||
None => return,
|
||||
Some(ref url) if url.scheme == "blob" &&
|
||||
url.non_relative_scheme_data().is_some() => return,
|
||||
_ => (),
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
self.set_url();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#update-href
|
||||
fn update_href(&self) {
|
||||
self.upcast::<Element>().set_string_attribute(&atom!("href"),
|
||||
self.url.borrow().as_ref().unwrap().serialize().into());
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMethods for HTMLAnchorElement {
|
||||
|
@ -107,6 +144,312 @@ impl HTMLAnchorElementMethods for HTMLAnchorElement {
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-a-shape
|
||||
make_setter!(SetShape, "shape");
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hash
|
||||
fn Hash(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 3.
|
||||
None => USVString(String::new()),
|
||||
Some(ref url) => {
|
||||
// Steps 3-4.
|
||||
UrlHelper::Hash(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hash
|
||||
fn SetHash(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.scheme == "javascript" { return; }
|
||||
// Steps 4-5.
|
||||
UrlHelper::SetHash(url, value);
|
||||
// Step 6.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-host
|
||||
fn Host(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 3.
|
||||
None => USVString(String::new()),
|
||||
Some(ref url) => {
|
||||
if url.host().is_none() {
|
||||
USVString(String::new())
|
||||
} else {
|
||||
// Steps 4-5.
|
||||
UrlHelper::Host(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-host
|
||||
fn SetHost(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.non_relative_scheme_data().is_some() {
|
||||
return;
|
||||
}
|
||||
// Step 4.
|
||||
UrlHelper::SetHost(url, value);
|
||||
// Step 5.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hostname
|
||||
fn Hostname(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 3.
|
||||
None => USVString(String::new()),
|
||||
Some(ref url) => {
|
||||
// Step 4.
|
||||
UrlHelper::Hostname(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-hostname
|
||||
fn SetHostname(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.non_relative_scheme_data().is_some() {
|
||||
return;
|
||||
}
|
||||
// Step 4.
|
||||
UrlHelper::SetHostname(url, value);
|
||||
// Step 5.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-href
|
||||
fn Href(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
USVString(match *self.url.borrow() {
|
||||
None => {
|
||||
match self.upcast::<Element>().get_attribute(&ns!(), &atom!("href")) {
|
||||
// Step 3.
|
||||
None => String::new(),
|
||||
// Step 4.
|
||||
Some(attribute) => (**attribute.value()).to_owned(),
|
||||
}
|
||||
},
|
||||
// Step 5.
|
||||
Some(ref url) => url.serialize(),
|
||||
})
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-href
|
||||
fn SetHref(&self, value: USVString) {
|
||||
self.upcast::<Element>().set_string_attribute(&atom!("href"),
|
||||
DOMString::from_string(value.0));
|
||||
self.set_url();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-password
|
||||
fn Password(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 3.
|
||||
None => USVString(String::new()),
|
||||
// Steps 3-4.
|
||||
Some(ref url) => UrlHelper::Password(url)
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-password
|
||||
fn SetPassword(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.host().is_none() || url.non_relative_scheme_data().is_some() {
|
||||
return;
|
||||
}
|
||||
// Step 4.
|
||||
UrlHelper::SetPassword(url, value);
|
||||
// Step 5.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-pathname
|
||||
fn Pathname(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 3.
|
||||
None => USVString(String::new()),
|
||||
// Steps 4-5.
|
||||
Some(ref url) => UrlHelper::Pathname(url)
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-pathname
|
||||
fn SetPathname(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.non_relative_scheme_data().is_some() { return; }
|
||||
// Step 5.
|
||||
UrlHelper::SetPathname(url, value);
|
||||
// Step 6.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-port
|
||||
fn Port(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 3.
|
||||
None => USVString(String::new()),
|
||||
// Step 4.
|
||||
Some(ref url) => UrlHelper::Port(url)
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-port
|
||||
fn SetPort(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.host().is_none() ||
|
||||
url.non_relative_scheme_data().is_some() ||
|
||||
url.scheme == "file" {
|
||||
return;
|
||||
}
|
||||
// Step 4.
|
||||
UrlHelper::SetPort(url, value);
|
||||
// Step 5.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-protocol
|
||||
fn Protocol(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 2.
|
||||
None => USVString(":".to_owned()),
|
||||
// Step 3.
|
||||
Some(ref url) => UrlHelper::Protocol(url)
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-protocol
|
||||
fn SetProtocol(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 2.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
// Step 3.
|
||||
UrlHelper::SetProtocol(url, value);
|
||||
// Step 4.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-search
|
||||
fn Search(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 2.
|
||||
None => USVString(String::new()),
|
||||
// Step 3.
|
||||
Some(ref url) => UrlHelper::Search(url)
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-search
|
||||
fn SetSearch(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
// Steps 4-5.
|
||||
// TODO add this element's node document character encoding as
|
||||
// encoding override (as described in the spec)
|
||||
UrlHelper::SetSearch(url, value);
|
||||
// Step 6.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-username
|
||||
fn Username(&self) -> USVString {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
match *self.url.borrow() {
|
||||
// Step 2.
|
||||
None => USVString(String::new()),
|
||||
// Step 3.
|
||||
Some(ref url) => UrlHelper::Username(url)
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-username
|
||||
fn SetUsername(&self, value: USVString) {
|
||||
// Step 1.
|
||||
self.reinitialize_url();
|
||||
|
||||
// Step 3.
|
||||
if let Some(url) = self.url.borrow_mut().as_mut() {
|
||||
if url.host().is_none() || url.non_relative_scheme_data().is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
UrlHelper::SetUsername(url, value);
|
||||
// Step 5.
|
||||
self.update_href();
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-hyperlink-href
|
||||
fn Stringifier(&self) -> DOMString {
|
||||
DOMString::from(self.Href().0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Activatable for HTMLAnchorElement {
|
||||
|
|
|
@ -21,6 +21,7 @@ impl UrlHelper {
|
|||
}
|
||||
|
||||
pub fn SetHash(url: &mut Url, value: USVString) {
|
||||
url.fragment = Some(String::new());
|
||||
let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
|
||||
let _ = wrapper.set_fragment(&value.0);
|
||||
}
|
||||
|
@ -101,6 +102,9 @@ impl UrlHelper {
|
|||
}
|
||||
|
||||
pub fn SetPathname(url: &mut Url, value: USVString) {
|
||||
if let Some(path) = url.path_mut() {
|
||||
path.clear();
|
||||
}
|
||||
let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
|
||||
let _ = wrapper.set_path(&value.0);
|
||||
}
|
||||
|
@ -149,6 +153,7 @@ impl UrlHelper {
|
|||
}
|
||||
|
||||
pub fn SetSearch(url: &mut Url, value: USVString) {
|
||||
url.query = Some(String::new());
|
||||
let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() };
|
||||
let _ = wrapper.set_query(&value.0);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ interface HTMLAnchorElement : HTMLElement {
|
|||
|
||||
// also has obsolete members
|
||||
};
|
||||
//HTMLAnchorElement implements HTMLHyperlinkElementUtils;
|
||||
HTMLAnchorElement implements HTMLHyperlinkElementUtils;
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#HTMLAnchorElement-partial
|
||||
partial interface HTMLAnchorElement {
|
||||
|
|
|
@ -4,17 +4,23 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#htmlhyperlinkelementutils
|
||||
//[NoInterfaceObject/*, Exposed=Window*/]
|
||||
//interface HTMLHyperlinkElementUtils {
|
||||
[NoInterfaceObject/*, Exposed=Window*/]
|
||||
interface HTMLHyperlinkElementUtils {
|
||||
// stringifier attribute USVString href;
|
||||
attribute USVString href;
|
||||
// attribute USVString origin;
|
||||
// attribute USVString protocol;
|
||||
// attribute USVString username;
|
||||
// attribute USVString password;
|
||||
// attribute USVString host;
|
||||
// attribute USVString hostname;
|
||||
// attribute USVString port;
|
||||
// attribute USVString pathname;
|
||||
// attribute USVString search;
|
||||
// attribute USVString hash;
|
||||
//};
|
||||
attribute USVString protocol;
|
||||
attribute USVString username;
|
||||
attribute USVString password;
|
||||
attribute USVString host;
|
||||
attribute USVString hostname;
|
||||
attribute USVString port;
|
||||
attribute USVString pathname;
|
||||
attribute USVString search;
|
||||
attribute USVString hash;
|
||||
|
||||
// Adding a separate stringifier method until
|
||||
// https://github.com/servo/servo/issues/7590 adds attribute stringifier
|
||||
// support.
|
||||
stringifier;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue