diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2015-11-21 21:10:52 +0530 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2015-11-21 21:10:52 +0530 |
commit | ea690a2dff64d1cb4eb668473d62f1bbcb19f7c8 (patch) | |
tree | cf5804f921ef3b249cc41610b7a99d11663ebfbe /components | |
parent | ec3437f4e30547884f9faaf153201fad6ab1173f (diff) | |
parent | f34da4120d475f7fd78a647fc246e5731e7de941 (diff) | |
download | servo-ea690a2dff64d1cb4eb668473d62f1bbcb19f7c8.tar.gz servo-ea690a2dff64d1cb4eb668473d62f1bbcb19f7c8.zip |
Auto merge of #8622 - frewsxcv:url-plugin, r=SimonSapin
Implement 'url!(..)' macro
https://github.com/servo/rust-url/issues/136
https://github.com/servo/rust-url/pull/137
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8622)
<!-- Reviewable:end -->
Diffstat (limited to 'components')
-rw-r--r-- | components/compositing/constellation.rs | 2 | ||||
-rw-r--r-- | components/plugins/Cargo.toml | 3 | ||||
-rw-r--r-- | components/plugins/lib.rs | 4 | ||||
-rw-r--r-- | components/plugins/url_plugin.rs | 141 | ||||
-rw-r--r-- | components/script/dom/document.rs | 2 | ||||
-rw-r--r-- | components/script/dom/htmliframeelement.rs | 2 | ||||
-rw-r--r-- | components/script/script_task.rs | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 12 | ||||
-rw-r--r-- | components/servo/Cargo.toml | 3 | ||||
-rw-r--r-- | components/style/font_face.rs | 2 | ||||
-rw-r--r-- | components/style/parser.rs | 2 | ||||
-rw-r--r-- | components/style/selector_matching.rs | 2 | ||||
-rw-r--r-- | components/util/opts.rs | 2 |
13 files changed, 171 insertions, 8 deletions
diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 2084ace9701..1055aabaa26 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -701,7 +701,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { parent_info, window_size, None, - LoadData::new(Url::parse("about:failure").unwrap())); + LoadData::new(url!("about:failure"))); self.push_pending_frame(new_pipeline_id, Some(pipeline_id)); } diff --git a/components/plugins/Cargo.toml b/components/plugins/Cargo.toml index 9e317316984..f697fe45cf7 100644 --- a/components/plugins/Cargo.toml +++ b/components/plugins/Cargo.toml @@ -16,5 +16,8 @@ git = "https://github.com/Manishearth/rust-clippy" branch = "servo" optional = true +[dependencies.url] +version = "0.2.36" + [features] default = [] diff --git a/components/plugins/lib.rs b/components/plugins/lib.rs index bb328c9441a..d52ad866879 100644 --- a/components/plugins/lib.rs +++ b/components/plugins/lib.rs @@ -26,6 +26,8 @@ extern crate tenacious; #[cfg(feature = "clippy")] extern crate clippy; +extern crate url; + use rustc::plugin::Registry; use syntax::ext::base::*; use syntax::feature_gate::AttributeType::Whitelisted; @@ -41,6 +43,7 @@ pub mod lints; pub mod reflector; /// Utilities for writing plugins pub mod casing; +mod url_plugin; pub mod utils; #[plugin_registrar] @@ -51,6 +54,7 @@ pub fn plugin_registrar(reg: &mut Registry) { reg.register_syntax_extension(intern("derive_HeapSizeOf"), MultiDecorator(box heap_size::expand_heap_size)); reg.register_macro("to_lower", casing::expand_lower); reg.register_macro("to_upper", casing::expand_upper); + reg.register_macro("url", url_plugin::expand_url); reg.register_late_lint_pass(box lints::transmute_type::TransmutePass); reg.register_late_lint_pass(box lints::unrooted_must_root::UnrootedPass::new()); reg.register_late_lint_pass(box lints::privatize::PrivatizePass); diff --git a/components/plugins/url_plugin.rs b/components/plugins/url_plugin.rs new file mode 100644 index 00000000000..8ae06624c4b --- /dev/null +++ b/components/plugins/url_plugin.rs @@ -0,0 +1,141 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::error::Error; +use syntax; +use syntax::ast::{TokenTree, ExprLit, LitStr, Expr}; +use syntax::codemap::Span; +use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult}; +use syntax::ext::build::AstBuilder; +use syntax::fold::Folder; +use syntax::parse; +use syntax::parse::token::InternedString; +use url::{Url, Host, RelativeSchemeData, SchemeData}; + +pub fn expand_url(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) + -> Box<MacResult + 'static> { + let mut parser = parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), tts.to_vec()); + let query_expr = cx.expander().fold_expr(parser.parse_expr()); + + // Ensure a str literal was passed to the macro + let query = match parse_str_lit(&query_expr) { + Some(query) => query, + None => { + cx.span_err(query_expr.span, "'url!' expected string literal"); + return DummyResult::any(sp) + }, + }; + + // Parse the str literal + let Url { scheme, scheme_data, query, fragment } = match Url::parse(&query) { + Ok(url) => url, + Err(error) => { + cx.span_err(query_expr.span, error.description()); + return DummyResult::any(sp) + } + }; + + let scheme_data_expr = cx.expr_scheme_data(sp, scheme_data); + let query_expr = cx.expr_option_string(sp, query); + let fragment_expr = cx.expr_option_string(sp, fragment); + + let url_expr = quote_expr!(cx, { + ::url::Url { + scheme: $scheme.to_owned(), + scheme_data: $scheme_data_expr, + query: $query_expr, + fragment: $fragment_expr, + } + }); + + MacEager::expr(url_expr) +} + +fn parse_str_lit(e: &Expr) -> Option<InternedString> { + if let ExprLit(ref lit) = e.node { + if let LitStr(ref s, _) = lit.node { + return Some(s.clone()); + } + } + None +} + +trait ExtCtxtHelpers { + fn expr_scheme_data(&self, sp: Span, scheme_data: SchemeData) -> syntax::ptr::P<Expr>; + fn expr_option_string(&self, sp: Span, string: Option<String>) -> syntax::ptr::P<Expr>; + fn expr_option_u16(&self, sp: Span, unsigned: Option<u16>) -> syntax::ptr::P<Expr>; + fn expr_host(&self, sp: Span, host: Host) -> syntax::ptr::P<Expr>; + fn expr_slice_u16(&self, sp: Span, unsigned: &[u16]) -> syntax::ptr::P<Expr>; + fn expr_vec_string(&self, sp: Span, strings: Vec<String>) -> syntax::ptr::P<Expr>; +} + +impl<'a> ExtCtxtHelpers for ExtCtxt<'a> { + fn expr_scheme_data(&self, sp: Span, scheme_data: SchemeData) -> syntax::ptr::P<Expr> { + match scheme_data { + SchemeData::Relative( + RelativeSchemeData { username, password, host, port, default_port, path }) => + { + let password_expr = self.expr_option_string(sp, password); + let host_expr = self.expr_host(sp, host); + let port_expr = self.expr_option_u16(sp, port); + let default_port_expr = self.expr_option_u16(sp, default_port); + let path_expr = self.expr_vec_string(sp, path); + + quote_expr!(self, + ::url::SchemeData::Relative( + ::url::RelativeSchemeData { + username: $username.to_owned(), + password: $password_expr, + host: $host_expr, + port: $port_expr, + default_port: $default_port_expr, + path: $path_expr.to_owned(), + } + )) + }, + SchemeData::NonRelative(ref scheme_data) => { + quote_expr!(self, ::url::SchemeData::NonRelative($scheme_data.to_owned())) + }, + } + } + + fn expr_option_string(&self, sp: Span, string: Option<String>) -> syntax::ptr::P<Expr> { + match string { + Some(string) => quote_expr!(self, Some($string.to_owned())), + None => self.expr_none(sp), + } + } + + fn expr_option_u16(&self, sp: Span, unsigned: Option<u16>) -> syntax::ptr::P<Expr> { + match unsigned { + Some(unsigned) => quote_expr!(self, Some($unsigned)), + None => self.expr_none(sp), + } + } + + fn expr_host(&self, sp: Span, host: Host) -> syntax::ptr::P<Expr> { + match host { + Host::Domain(domain) => quote_expr!(self, ::url::Host::Domain(String::from($domain))), + Host::Ipv6(address) => { + let pieces_expr = self.expr_slice_u16(sp, &address.pieces); + quote_expr!(self, + ::url::Host::Ipv6( + ::url::Ipv6Address { + pieces: $pieces_expr.to_owned() + } + )) + }, + } + } + + fn expr_slice_u16(&self, sp: Span, unsigned: &[u16]) -> syntax::ptr::P<Expr> { + let unsigned = unsigned.iter().map(|p| quote_expr!(self, $p)).collect(); + self.expr_vec_slice(sp, unsigned) + } + + fn expr_vec_string(&self, sp: Span, strings: Vec<String>) -> syntax::ptr::P<Expr> { + let strings = strings.iter().map(|p| quote_expr!(self, $p.to_owned())).collect(); + self.expr_vec(sp, strings) + } +} diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 585b93f1912..34a7846b543 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -1388,7 +1388,7 @@ impl Document { source: DocumentSource, doc_loader: DocumentLoader) -> Document { - let url = url.unwrap_or_else(|| Url::parse("about:blank").unwrap()); + let url = url.unwrap_or_else(|| url!("about:blank")); let (ready_state, domcontentloaded_dispatched) = if source == DocumentSource::FromParser { (DocumentReadyState::Loading, false) diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index b3e62ef434b..7d14dfe916d 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -124,7 +124,7 @@ impl HTMLIFrameElement { pub fn process_the_iframe_attributes(&self) { let url = match self.get_url() { Some(url) => url.clone(), - None => Url::parse("about:blank").unwrap(), + None => url!("about:blank"), }; self.navigate_child_browsing_context(url); diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 1f407ab940a..95e1c7f356f 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -1969,7 +1969,7 @@ impl ScriptTask { }; if load_data.url.scheme == "javascript" { - load_data.url = Url::parse("about:blank").unwrap(); + load_data.url = url!("about:blank"); } resource_task.send(ControlMsg::Load(NetLoadData { diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 92b083fdf50..b95310c217a 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -28,6 +28,7 @@ dependencies = [ "net_traits 0.0.1", "net_traits_tests 0.0.1", "offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", + "plugin_tests 0.0.1", "profile 0.0.1", "profile_traits 0.0.1", "script 0.0.1", @@ -1223,6 +1224,7 @@ dependencies = [ "msg 0.0.1", "net 0.0.1", "net_traits 0.0.1", + "plugins 0.0.1", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", @@ -1389,10 +1391,19 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "plugin_tests" +version = "0.0.1" +dependencies = [ + "plugins 0.0.1", + "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "plugins" version = "0.0.1" dependencies = [ "tenacious 0.0.11 (git+https://github.com/Manishearth/rust-tenacious)", + "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1770,6 +1781,7 @@ dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "plugins 0.0.1", "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml index b17a137a16c..5d2222b8aa1 100644 --- a/components/servo/Cargo.toml +++ b/components/servo/Cargo.toml @@ -29,6 +29,9 @@ path = "../../tests/unit/net" [dev-dependencies.net_traits_tests] path = "../../tests/unit/net_traits" +[dev-dependencies.plugin_tests] +path = "../../tests/unit/plugin" + [dev-dependencies.script_tests] path = "../../tests/unit/script" diff --git a/components/style/font_face.rs b/components/style/font_face.rs index ff4f2993d81..52abb82c3cf 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -112,7 +112,7 @@ fn parse_one_src(context: &ParserContext, input: &mut Parser) -> Result<Source, } let url = try!(input.expect_url()); let url = UrlParser::new().base_url(context.base_url).parse(&url).unwrap_or_else( - |_error| Url::parse("about:invalid").unwrap()); + |_error| url!("about:invalid")); // Parsing optional format() let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() { diff --git a/components/style/parser.rs b/components/style/parser.rs index f189c7c5d93..67f35fa0976 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -31,7 +31,7 @@ impl<'a> ParserContext<'a> { impl<'a> ParserContext<'a> { pub fn parse_url(&self, input: &str) -> Url { UrlParser::new().base_url(self.base_url).parse(input) - .unwrap_or_else(|_| Url::parse("about:invalid").unwrap()) + .unwrap_or_else(|_| url!("about:invalid")) } } diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index e8887163b61..f4b2168fc26 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -61,7 +61,7 @@ lazy_static! { Ok(res) => { Stylesheet::from_bytes( &res, - Url::parse("chrome:///quirks-mode.css").unwrap(), + url!("chrome:///quirks-mode.css"), None, None, Origin::UserAgent) diff --git a/components/util/opts.rs b/components/util/opts.rs index 761568de42d..1b74e142408 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -440,7 +440,7 @@ const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop; pub fn default_opts() -> Opts { Opts { is_running_problem_test: false, - url: Some(Url::parse("about:blank").unwrap()), + url: Some(url!("about:blank")), paint_threads: 1, gpu_painting: false, tile_size: 512, |