aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--components/canvas/lib.rs1
-rw-r--r--components/compositing/lib.rs1
-rw-r--r--components/gfx/lib.rs1
-rw-r--r--components/layout/context.rs1
-rw-r--r--components/servo/Cargo.lock31
-rw-r--r--components/servo/Cargo.toml6
-rw-r--r--components/style/traversal.rs45
-rw-r--r--ports/cef/Cargo.lock19
-rw-r--r--ports/cef/Cargo.toml2
-rw-r--r--ports/geckolib/bindings.rs85
-rw-r--r--ports/geckolib/data.rs75
-rw-r--r--ports/geckolib/glue.rs144
-rw-r--r--ports/geckolib/lib.rs2
-rw-r--r--ports/geckolib/traversal.rs82
-rw-r--r--ports/geckolib/wrapper.rs36
-rw-r--r--ports/gonk/Cargo.lock4
-rw-r--r--python/servo/testing_commands.py64
-rw-r--r--python/tidy.py2
-rw-r--r--tests/compiletest/helper/Cargo.toml12
-rw-r--r--tests/compiletest/helper/lib.rs29
-rw-r--r--tests/compiletest/plugin/Cargo.toml15
-rw-r--r--tests/compiletest/plugin/compile-fail/ban.rs18
-rw-r--r--tests/compiletest/plugin/compile-fail/privatize.rs16
-rw-r--r--tests/compiletest/plugin/compile-fail/str_to_string.rs16
-rw-r--r--tests/compiletest/plugin/compile-fail/transmute_type.rs19
-rw-r--r--tests/compiletest/plugin/compile-fail/unrooted_must_root.rs27
-rw-r--r--tests/compiletest/plugin/lib.rs10
28 files changed, 621 insertions, 143 deletions
diff --git a/.travis.yml b/.travis.yml
index 5c810b5064b..63fc4ddddcc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,7 @@ matrix:
script:
- ./mach build -d --verbose
- ./mach test-unit
+ - ./mach test-compiletest
- bash etc/ci/lockfile_changed.sh
- bash etc/ci/manifest_changed.sh
cache:
diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs
index 5a0b1a9e596..7377e0385c7 100644
--- a/components/canvas/lib.rs
+++ b/components/canvas/lib.rs
@@ -2,7 +2,6 @@
* 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/. */
-#![feature(clone_from_slice)]
#![feature(nonzero)]
#![feature(plugin)]
#![plugin(plugins)]
diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs
index bf192bd044a..6434c3a8939 100644
--- a/components/compositing/lib.rs
+++ b/components/compositing/lib.rs
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![feature(box_syntax)]
-#![feature(clone_from_slice)]
#![feature(custom_derive)]
#![feature(plugin)]
#![feature(mpsc_select)]
diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs
index c0868ade6f8..8bc6f8c8b4a 100644
--- a/components/gfx/lib.rs
+++ b/components/gfx/lib.rs
@@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// For simd (currently x86_64/aarch64)
-#![cfg_attr(any(target_arch = "x86_64", target_arch = "aarch64"), feature(convert))]
#![cfg_attr(any(target_os = "linux", target_os = "android", target_os = "windows"), feature(heap_api))]
#![feature(alloc)]
diff --git a/components/layout/context.rs b/components/layout/context.rs
index ca4ef0851dd..134a6f03b2b 100644
--- a/components/layout/context.rs
+++ b/components/layout/context.rs
@@ -50,6 +50,7 @@ pub fn heap_size_of_local_context() -> usize {
})
}
+// Keep this implementation in sync with the one in ports/geckolib/traversal.rs.
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext)
-> Rc<LocalLayoutContext> {
LOCAL_CONTEXT_KEY.with(|r| {
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 344250b75b1..f78d15b3b1b 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -6,6 +6,7 @@ dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"canvas 0.0.1",
"canvas_traits 0.0.1",
+ "compiletest_helper 0.0.1",
"compositing 0.0.1",
"devtools 0.0.1",
"devtools_traits 0.0.1",
@@ -28,6 +29,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_compiletest 0.0.1",
"plugin_tests 0.0.1",
"profile 0.0.1",
"profile_traits 0.0.1",
@@ -241,6 +243,21 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "compiletest_helper"
+version = "0.0.1"
+dependencies = [
+ "compiletest_rs 0.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "compiletest_rs"
+version = "0.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "compositing"
version = "0.0.1"
dependencies = [
@@ -736,7 +753,7 @@ dependencies = [
"net_traits 0.0.1",
"script_traits 0.0.1",
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1403,6 +1420,14 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "plugin_compiletest"
+version = "0.0.1"
+dependencies = [
+ "compiletest_helper 0.0.1",
+ "plugins 0.0.1",
+]
+
+[[package]]
name = "plugin_tests"
version = "0.0.1"
dependencies = [
@@ -1704,7 +1729,7 @@ dependencies = [
[[package]]
name = "servo-glutin"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1746,7 +1771,7 @@ dependencies = [
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml
index b12bbb2312d..1b0a92ff94e 100644
--- a/components/servo/Cargo.toml
+++ b/components/servo/Cargo.toml
@@ -41,6 +41,12 @@ path = "../../tests/unit/style"
[dev-dependencies.util_tests]
path = "../../tests/unit/util"
+[dev-dependencies.compiletest_helper]
+path = "../../tests/compiletest/helper"
+
+[dev-dependencies.plugin_compiletest]
+path = "../../tests/compiletest/plugin"
+
[[test]]
name = "reftest"
path = "../../tests/reftest.rs"
diff --git a/components/style/traversal.rs b/components/style/traversal.rs
index d39da40f03e..781c99f619e 100644
--- a/components/style/traversal.rs
+++ b/components/style/traversal.rs
@@ -2,13 +2,11 @@
* 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 context::{LocalStyleContext, SharedStyleContext, StyleContext};
+use context::{SharedStyleContext, StyleContext};
use dom::{OpaqueNode, TNode, TRestyleDamage, UnsafeNode};
use matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
use selectors::bloom::BloomFilter;
use std::cell::RefCell;
-use std::mem;
-use std::rc::Rc;
use util::opts;
use util::tid::tid;
@@ -115,47 +113,6 @@ pub trait DomTraversalContext<'ln, N: TNode<'ln>> {
fn process_postorder(&self, node: N);
}
-pub struct StandaloneStyleContext<'a> {
- pub shared: &'a SharedStyleContext,
- cached_local_style_context: Rc<LocalStyleContext>,
-}
-
-impl<'a> StandaloneStyleContext<'a> {
- pub fn new(_: &'a SharedStyleContext) -> Self { panic!("Not implemented") }
-}
-
-impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
- fn shared_context(&self) -> &'a SharedStyleContext {
- &self.shared
- }
-
- fn local_context(&self) -> &LocalStyleContext {
- &self.cached_local_style_context
- }
-}
-
-pub struct RecalcStyleOnly<'lc> {
- context: StandaloneStyleContext<'lc>,
- root: OpaqueNode,
-}
-
-impl<'lc, 'ln, N: TNode<'ln>> DomTraversalContext<'ln, N> for RecalcStyleOnly<'lc> {
- type SharedContext = SharedStyleContext;
- #[allow(unsafe_code)]
- fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self {
- // See the comment in RecalcStyleAndConstructFlows::new for an explanation of why this is
- // necessary.
- let shared_lc: &'lc SharedStyleContext = unsafe { mem::transmute(shared) };
- RecalcStyleOnly {
- context: StandaloneStyleContext::new(shared_lc),
- root: root,
- }
- }
-
- fn process_preorder(&self, node: N) { recalc_style_at(&self.context, self.root, node); }
- fn process_postorder(&self, _: N) {}
-}
-
/// The recalc-style-for-node traversal, which styles each node and must run before
/// layout computation. This computes the styles applied to each node.
#[inline]
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index 92ab7641c4e..796fcb6d639 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -4,7 +4,7 @@ version = "0.0.1"
dependencies = [
"azure 0.4.0 (git+https://github.com/servo/rust-azure)",
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "cocoa 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cocoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"compositing 0.0.1",
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -216,17 +216,6 @@ dependencies = [
[[package]]
name = "cocoa"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "objc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "cocoa"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
@@ -695,7 +684,7 @@ dependencies = [
"net_traits 0.0.1",
"script_traits 0.0.1",
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"url 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1654,7 +1643,7 @@ dependencies = [
[[package]]
name = "servo-glutin"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1696,7 +1685,7 @@ dependencies = [
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/ports/cef/Cargo.toml b/ports/cef/Cargo.toml
index 029f51b1a9c..a47bfe10e21 100644
--- a/ports/cef/Cargo.toml
+++ b/ports/cef/Cargo.toml
@@ -66,7 +66,7 @@ features = ["plugins"]
[target.x86_64-apple-darwin.dependencies]
objc = "0.1"
-cocoa = "0.1"
+cocoa = "0.2"
core-foundation = "0.2"
core-graphics = "0.2"
core-text = "1.0"
diff --git a/ports/geckolib/bindings.rs b/ports/geckolib/bindings.rs
index 96a5cb40705..845cca32e13 100644
--- a/ports/geckolib/bindings.rs
+++ b/ports/geckolib/bindings.rs
@@ -28,19 +28,22 @@ pub type intptr_t = int64_t;
pub type uintptr_t = uint64_t;
pub type intmax_t = ::libc::c_long;
pub type uintmax_t = ::libc::c_ulong;
-pub type Enum_NodeType = ::libc::c_uint;
-pub const ELEMENT_NODE: ::libc::c_uint = 1;
-pub const ATTRIBUTE_NODE: ::libc::c_uint = 2;
-pub const TEXT_NODE: ::libc::c_uint = 3;
-pub const CDATA_SECTION_NODE: ::libc::c_uint = 4;
-pub const ENTITY_REFERENCE_NODE: ::libc::c_uint = 5;
-pub const ENTITY_NODE: ::libc::c_uint = 6;
-pub const PROCESSING_INSTRUCTION_NODE: ::libc::c_uint = 7;
-pub const COMMENT_NODE: ::libc::c_uint = 8;
-pub const DOCUMENT_NODE: ::libc::c_uint = 9;
-pub const DOCUMENT_TYPE_NODE: ::libc::c_uint = 10;
-pub const DOCUMENT_FRAGMENT_NODE: ::libc::c_uint = 11;
-pub const NOTATION_NODE: ::libc::c_uint = 12;
+#[derive(Clone, Copy)]
+#[repr(u32)]
+pub enum Enum_NodeType {
+ ELEMENT_NODE = 1,
+ ATTRIBUTE_NODE = 2,
+ TEXT_NODE = 3,
+ CDATA_SECTION_NODE = 4,
+ ENTITY_REFERENCE_NODE = 5,
+ ENTITY_NODE = 6,
+ PROCESSING_INSTRUCTION_NODE = 7,
+ COMMENT_NODE = 8,
+ DOCUMENT_NODE = 9,
+ DOCUMENT_TYPE_NODE = 10,
+ DOCUMENT_FRAGMENT_NODE = 11,
+ NOTATION_NODE = 12,
+}
pub enum Struct_RawGeckoNode { }
pub type RawGeckoNode = Struct_RawGeckoNode;
pub enum Struct_RawGeckoElement { }
@@ -49,10 +52,15 @@ pub enum Struct_RawGeckoDocument { }
pub type RawGeckoDocument = Struct_RawGeckoDocument;
pub enum Struct_ServoNodeData { }
pub type ServoNodeData = Struct_ServoNodeData;
+pub enum Struct_ServoArcStyleSheet { }
+pub type ServoArcStyleSheet = Struct_ServoArcStyleSheet;
+pub enum Struct_ServoStyleSetData { }
+pub type ServoStyleSetData = Struct_ServoStyleSetData;
extern "C" {
pub fn Gecko_ElementState(element: *mut RawGeckoElement) -> uint8_t;
- pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement, ns: *const uint8_t,
- name: *const uint8_t, length: *mut uint32_t)
+ pub fn Gecko_GetAttrAsUTF8(element: *mut RawGeckoElement,
+ ns: *const uint8_t, name: *const uint8_t,
+ length: *mut uint32_t)
-> *const ::libc::c_char;
pub fn Gecko_ChildrenCount(node: *mut RawGeckoNode) -> uint32_t;
pub fn Gecko_GetDocumentElement(document: *mut RawGeckoDocument)
@@ -61,21 +69,50 @@ extern "C" {
pub fn Gecko_GetLastChild(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
pub fn Gecko_GetPrevSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
pub fn Gecko_GetNextSibling(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
+ pub fn Gecko_GetParentElement(element: *mut RawGeckoElement)
+ -> *mut RawGeckoElement;
+ pub fn Gecko_GetFirstChildElement(element: *mut RawGeckoElement)
+ -> *mut RawGeckoElement;
+ pub fn Gecko_GetLastChildElement(element: *mut RawGeckoElement)
+ -> *mut RawGeckoElement;
+ pub fn Gecko_GetPrevSiblingElement(element: *mut RawGeckoElement)
+ -> *mut RawGeckoElement;
+ pub fn Gecko_GetNextSiblingElement(element: *mut RawGeckoElement)
+ -> *mut RawGeckoElement;
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
pub fn Gecko_GetParentNode(node: *mut RawGeckoNode) -> *mut RawGeckoNode;
- pub fn Gecko_LocalName(element: *mut RawGeckoElement, length: *mut uint32_t)
- -> *const uint16_t;
+ pub fn Gecko_LocalName(element: *mut RawGeckoElement,
+ length: *mut uint32_t) -> *const uint16_t;
pub fn Gecko_IsHTMLElementInHTMLDocument(element: *mut RawGeckoElement)
-> ::libc::c_int;
pub fn Gecko_IsLink(element: *mut RawGeckoElement) -> ::libc::c_int;
pub fn Gecko_IsTextNode(node: *mut RawGeckoNode) -> ::libc::c_int;
- pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement) -> ::libc::c_int;
- pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement) -> ::libc::c_int;
- pub fn Gecko_Namespace(element: *mut RawGeckoElement, length: *mut uint32_t)
- -> *const uint16_t;
+ pub fn Gecko_IsVisitedLink(element: *mut RawGeckoElement)
+ -> ::libc::c_int;
+ pub fn Gecko_IsUnvisitedLink(element: *mut RawGeckoElement)
+ -> ::libc::c_int;
+ pub fn Gecko_IsRootElement(element: *mut RawGeckoElement)
+ -> ::libc::c_int;
+ pub fn Gecko_Namespace(element: *mut RawGeckoElement,
+ length: *mut uint32_t) -> *const uint16_t;
pub fn Gecko_NodeIsElement(node: *mut RawGeckoNode) -> ::libc::c_int;
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
- data: *mut ServoNodeData) -> ();
- pub fn Servo_RestyleDocument(aDoc: *mut RawGeckoDocument) -> ();
- pub fn Servo_DropNodeData(data: *mut ServoNodeData) -> ();
+ data: *mut ServoNodeData);
+ pub fn Servo_RestyleDocument(doc: *mut RawGeckoDocument,
+ data: *mut ServoStyleSetData);
+ pub fn Servo_DropNodeData(data: *mut ServoNodeData);
+ pub fn Servo_StylesheetFromUTF8Bytes(bytes: *const uint8_t,
+ length: uint32_t)
+ -> *mut ServoArcStyleSheet;
+ pub fn Servo_AppendStyleSheet(sheet: *mut ServoArcStyleSheet,
+ data: *mut ServoStyleSetData);
+ pub fn Servo_PrependStyleSheet(sheet: *mut ServoArcStyleSheet,
+ data: *mut ServoStyleSetData);
+ pub fn Servo_RemoveStyleSheet(sheet: *mut ServoArcStyleSheet,
+ data: *mut ServoStyleSetData);
+ pub fn Servo_StyleSheetHasRules(sheet: *mut ServoArcStyleSheet)
+ -> ::libc::c_int;
+ pub fn Servo_DropStylesheet(sheet: *mut ServoArcStyleSheet);
+ pub fn Servo_InitStyleSetData() -> *mut ServoStyleSetData;
+ pub fn Servo_DropStyleSetData(data: *mut ServoStyleSetData);
}
diff --git a/ports/geckolib/data.rs b/ports/geckolib/data.rs
new file mode 100644
index 00000000000..3e78c6c87ae
--- /dev/null
+++ b/ports/geckolib/data.rs
@@ -0,0 +1,75 @@
+/* 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 bindings::ServoStyleSetData;
+use euclid::Size2D;
+use euclid::size::TypedSize2D;
+use num_cpus;
+use std::cmp;
+use std::collections::HashMap;
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::{Arc, RwLock};
+use style::animation::Animation;
+use style::context::SharedStyleContext;
+use style::dom::OpaqueNode;
+use style::media_queries::{Device, MediaType};
+use style::parallel::WorkQueueData;
+use style::selector_matching::Stylist;
+use style::stylesheets::Stylesheet;
+use util::geometry::ViewportPx;
+use util::thread_state;
+use util::workqueue::WorkQueue;
+
+pub struct PerDocumentStyleData {
+
+ /// Rule processor.
+ pub stylist: Stylist,
+
+ /// List of stylesheets, mirrored from Gecko.
+ pub stylesheets: Vec<Arc<Stylesheet>>,
+
+ /// Whether the stylesheets list above has changed since the last restyle.
+ pub stylesheets_changed: bool,
+
+ // FIXME(bholley): Hook these up to something.
+ pub new_animations_sender: Sender<Animation>,
+ pub new_animations_receiver: Receiver<Animation>,
+ pub running_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
+ pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
+
+ // FIXME(bholley): This shouldn't be per-document.
+ pub work_queue: WorkQueue<SharedStyleContext, WorkQueueData>,
+}
+
+impl PerDocumentStyleData {
+ pub fn new() -> PerDocumentStyleData {
+ // FIXME(bholley): Real window size.
+ let window_size: TypedSize2D<ViewportPx, f32> = Size2D::typed(800.0, 600.0);
+ let device = Device::new(MediaType::Screen, window_size);
+
+ let (new_anims_sender, new_anims_receiver) = channel();
+ let num_threads = cmp::max(num_cpus::get() * 3 / 4, 1);
+
+ PerDocumentStyleData {
+ stylist: Stylist::new(device),
+ stylesheets: Vec::new(),
+ stylesheets_changed: true,
+ new_animations_sender: new_anims_sender,
+ new_animations_receiver: new_anims_receiver,
+ running_animations: Arc::new(RwLock::new(HashMap::new())),
+ expired_animations: Arc::new(RwLock::new(HashMap::new())),
+ work_queue: WorkQueue::new("StyleWorker", thread_state::LAYOUT, num_threads),
+ }
+ }
+
+ pub fn borrow_mut_from_raw<'a>(data: *mut ServoStyleSetData) -> &'a mut Self {
+ unsafe { &mut *(data as *mut PerDocumentStyleData) }
+ }
+}
+
+impl Drop for PerDocumentStyleData {
+ fn drop(&mut self) {
+ self.work_queue.shutdown();
+ }
+}
diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs
index bb1d6bcae3e..9ad4c99577a 100644
--- a/ports/geckolib/glue.rs
+++ b/ports/geckolib/glue.rs
@@ -6,27 +6,22 @@
use app_units::Au;
use bindings::RawGeckoDocument;
-use bindings::ServoNodeData;
+use bindings::{ServoArcStyleSheet, ServoNodeData, ServoStyleSetData, uint8_t, uint32_t};
+use data::PerDocumentStyleData;
use euclid::Size2D;
-use euclid::size::TypedSize2D;
-use num_cpus;
-use std::cmp;
-use std::collections::HashMap;
-use std::sync::mpsc::{channel, Sender};
-use std::sync::{Arc, Mutex, RwLock};
-use style::animation::Animation;
+use std::mem::{forget, transmute};
+use std::slice;
+use std::str::from_utf8_unchecked;
+use std::sync::{Arc, Mutex};
use style::context::{ReflowGoal, SharedStyleContext, StylistWrapper};
use style::dom::{TDocument, TNode};
use style::error_reporting::StdoutErrorReporter;
-use style::media_queries::{Device, MediaType};
-use style::parallel::{self, WorkQueueData};
-use style::selector_matching::Stylist;
-use style::stylesheets::Stylesheet;
-use style::traversal::RecalcStyleOnly;
-use util::geometry::ViewportPx;
+use style::parallel;
+use style::stylesheets::{Origin, Stylesheet};
+use traversal::RecalcStyleOnly;
+use url::Url;
+use util::arc_ptr_eq;
use util::resource_files::set_resources_path;
-use util::thread_state;
-use util::workqueue::WorkQueue;
use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData};
/*
@@ -38,50 +33,36 @@ use wrapper::{GeckoDocument, GeckoNode, NonOpaqueStyleData};
*/
#[no_mangle]
-pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument) -> () {
+pub extern "C" fn Servo_RestyleDocument(doc: *mut RawGeckoDocument, raw_data: *mut ServoStyleSetData) -> () {
let document = unsafe { GeckoDocument::from_raw(doc) };
let node = match document.root_node() {
Some(x) => x,
None => return,
};
+ let data = unsafe { &mut *(raw_data as *mut PerDocumentStyleData) };
// FIXME(bholley): Don't hardcode resources path. We may want to use Gecko's UA stylesheets
// anyway.
set_resources_path(Some("/files/mozilla/stylo/servo/resources/".to_owned()));
- // FIXME(bholley): Real window size.
- let window_size: TypedSize2D<ViewportPx, f32> = Size2D::typed(800.0, 600.0);
- let device = Device::new(MediaType::Screen, window_size);
-
- // FIXME(bholley): Real stylist and stylesheets.
- let stylesheets: Vec<Arc<Stylesheet>> = Vec::new();
- let mut stylist = Box::new(Stylist::new(device));
- let _needs_dirtying = stylist.update(&stylesheets, false);
-
- // FIXME(bholley): Hook this up to something.
- let new_animations_sender: Sender<Animation> = channel().0;
+ let _needs_dirtying = data.stylist.update(&data.stylesheets, data.stylesheets_changed);
+ data.stylesheets_changed = false;
let shared_style_context = SharedStyleContext {
viewport_size: Size2D::new(Au(0), Au(0)),
screen_size_changed: false,
generation: 0,
goal: ReflowGoal::ForScriptQuery,
- stylist: StylistWrapper(&*stylist),
- new_animations_sender: Mutex::new(new_animations_sender),
- running_animations: Arc::new(RwLock::new(HashMap::new())),
- expired_animations: Arc::new(RwLock::new(HashMap::new())),
+ stylist: StylistWrapper(&data.stylist),
+ new_animations_sender: Mutex::new(data.new_animations_sender.clone()),
+ running_animations: data.running_animations.clone(),
+ expired_animations: data.expired_animations.clone(),
error_reporter: Box::new(StdoutErrorReporter),
};
- let num_threads = cmp::max(num_cpus::get() * 3 / 4, 1);
- let mut parallel_traversal: WorkQueue<SharedStyleContext, WorkQueueData> =
- WorkQueue::new("StyleWorker", thread_state::LAYOUT, num_threads);
-
if node.is_dirty() || node.has_dirty_descendants() {
- parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context, &mut parallel_traversal);
+ parallel::traverse_dom::<GeckoNode, RecalcStyleOnly>(node, &shared_style_context, &mut data.work_queue);
}
-
- parallel_traversal.shutdown();
}
#[no_mangle]
@@ -90,3 +71,88 @@ pub extern "C" fn Servo_DropNodeData(data: *mut ServoNodeData) -> () {
let _ = Box::<NonOpaqueStyleData>::from_raw(data as *mut NonOpaqueStyleData);
}
}
+
+#[no_mangle]
+pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const uint8_t,
+ length: uint32_t) -> *mut ServoArcStyleSheet {
+
+ let input = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
+
+ // FIXME(heycam): Pass in the real base URL and sheet origin to use.
+ let url = Url::parse("about:none").unwrap();
+ let sheet = Arc::new(Stylesheet::from_str(input, url, Origin::Author, Box::new(StdoutErrorReporter)));
+ unsafe {
+ transmute(sheet)
+ }
+}
+
+fn with_arc_stylesheet<F, Output>(raw: *mut ServoArcStyleSheet, cb: F) -> Output
+ where F: FnOnce(&Arc<Stylesheet>) -> Output {
+ let owned = unsafe { consume_arc_stylesheet(raw) };
+ let result = cb(&owned);
+ forget(owned);
+ result
+}
+
+unsafe fn consume_arc_stylesheet(raw: *mut ServoArcStyleSheet) -> Arc<Stylesheet> {
+ transmute(raw)
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: *mut ServoArcStyleSheet,
+ raw_data: *mut ServoStyleSetData) {
+ let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
+ with_arc_stylesheet(raw_sheet, |sheet| {
+ data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
+ data.stylesheets.push(sheet.clone());
+ data.stylesheets_changed = true;
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_PrependStyleSheet(raw_sheet: *mut ServoArcStyleSheet,
+ raw_data: *mut ServoStyleSetData) {
+ let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
+ with_arc_stylesheet(raw_sheet, |sheet| {
+ data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
+ data.stylesheets.insert(0, sheet.clone());
+ data.stylesheets_changed = true;
+ })
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_RemoveStyleSheet(raw_sheet: *mut ServoArcStyleSheet,
+ raw_data: *mut ServoStyleSetData) {
+ let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
+ with_arc_stylesheet(raw_sheet, |sheet| {
+ data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
+ data.stylesheets_changed = true;
+ });
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_StyleSheetHasRules(raw_sheet: *mut ServoArcStyleSheet) -> ::libc::c_int {
+ with_arc_stylesheet(raw_sheet, |sheet| if sheet.rules.is_empty() { 0 } else { 1 })
+}
+
+
+#[no_mangle]
+pub extern "C" fn Servo_DropStylesheet(sheet: *mut ServoArcStyleSheet) -> () {
+ unsafe {
+ let _ = consume_arc_stylesheet(sheet);
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_InitStyleSetData() -> *mut ServoStyleSetData {
+ let data = Box::new(PerDocumentStyleData::new());
+ Box::into_raw(data) as *mut ServoStyleSetData
+}
+
+
+#[no_mangle]
+pub extern "C" fn Servo_DropStyleSetData(data: *mut ServoStyleSetData) -> () {
+ unsafe {
+ let _ = Box::<PerDocumentStyleData>::from_raw(data as *mut PerDocumentStyleData);
+ }
+}
diff --git a/ports/geckolib/lib.rs b/ports/geckolib/lib.rs
index d1548b7fd94..e47d757b127 100644
--- a/ports/geckolib/lib.rs
+++ b/ports/geckolib/lib.rs
@@ -23,6 +23,8 @@ extern crate util;
#[allow(dead_code, non_camel_case_types)]
mod bindings;
+mod data;
#[allow(non_snake_case)]
pub mod glue;
+mod traversal;
mod wrapper;
diff --git a/ports/geckolib/traversal.rs b/ports/geckolib/traversal.rs
new file mode 100644
index 00000000000..217035f5a52
--- /dev/null
+++ b/ports/geckolib/traversal.rs
@@ -0,0 +1,82 @@
+/* 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::cell::RefCell;
+use std::mem;
+use std::rc::Rc;
+use style::context::{LocalStyleContext, SharedStyleContext, StyleContext};
+use style::dom::{OpaqueNode, TNode};
+use style::matching::{ApplicableDeclarationsCache, StyleSharingCandidateCache};
+use style::traversal::{DomTraversalContext, recalc_style_at};
+
+thread_local!(static LOCAL_CONTEXT_KEY: RefCell<Option<Rc<LocalStyleContext>>> = RefCell::new(None));
+
+// Keep this implementation in sync with the one in components/layout/context.rs.
+fn create_or_get_local_context(shared: &SharedStyleContext)
+ -> Rc<LocalStyleContext> {
+ LOCAL_CONTEXT_KEY.with(|r| {
+ let mut r = r.borrow_mut();
+ if let Some(context) = r.clone() {
+ if shared.screen_size_changed {
+ context.applicable_declarations_cache.borrow_mut().evict_all();
+ }
+ context
+ } else {
+ let context = Rc::new(LocalStyleContext {
+ applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()),
+ style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()),
+ });
+ *r = Some(context.clone());
+ context
+ }
+ })
+}
+
+pub struct StandaloneStyleContext<'a> {
+ pub shared: &'a SharedStyleContext,
+ cached_local_context: Rc<LocalStyleContext>,
+}
+
+impl<'a> StandaloneStyleContext<'a> {
+ pub fn new(shared: &'a SharedStyleContext) -> Self {
+ let local_context = create_or_get_local_context(shared);
+ StandaloneStyleContext {
+ shared: shared,
+ cached_local_context: local_context,
+ }
+ }
+}
+
+impl<'a> StyleContext<'a> for StandaloneStyleContext<'a> {
+ fn shared_context(&self) -> &'a SharedStyleContext {
+ &self.shared
+ }
+
+ fn local_context(&self) -> &LocalStyleContext {
+ &self.cached_local_context
+ }
+}
+
+pub struct RecalcStyleOnly<'lc> {
+ context: StandaloneStyleContext<'lc>,
+ root: OpaqueNode,
+}
+
+impl<'lc, 'ln, N: TNode<'ln>> DomTraversalContext<'ln, N> for RecalcStyleOnly<'lc> {
+ type SharedContext = SharedStyleContext;
+ #[allow(unsafe_code)]
+ fn new<'a>(shared: &'a Self::SharedContext, root: OpaqueNode) -> Self {
+ // See the comment in RecalcStyleAndConstructFlows::new for an explanation of why this is
+ // necessary.
+ let shared_lc: &'lc SharedStyleContext = unsafe { mem::transmute(shared) };
+ RecalcStyleOnly {
+ context: StandaloneStyleContext::new(shared_lc),
+ root: root,
+ }
+ }
+
+ fn process_preorder(&self, node: N) { recalc_style_at(&self.context, self.root, node); }
+ fn process_postorder(&self, _: N) {}
+}
+
diff --git a/ports/geckolib/wrapper.rs b/ports/geckolib/wrapper.rs
index 41b2b3ab1bc..03c436f7d28 100644
--- a/ports/geckolib/wrapper.rs
+++ b/ports/geckolib/wrapper.rs
@@ -6,9 +6,13 @@
use bindings::{Gecko_ChildrenCount};
use bindings::{Gecko_ElementState, Gecko_GetAttrAsUTF8, Gecko_GetDocumentElement};
-use bindings::{Gecko_GetFirstChild, Gecko_GetLastChild, Gecko_GetNodeData};
-use bindings::{Gecko_GetParentNode, Gecko_GetPrevSibling, Gecko_GetNextSibling};
-use bindings::{Gecko_IsHTMLElementInHTMLDocument, Gecko_IsLink, Gecko_IsTextNode};
+use bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement};
+use bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement};
+use bindings::{Gecko_GetNextSibling, Gecko_GetNextSiblingElement};
+use bindings::{Gecko_GetNodeData};
+use bindings::{Gecko_GetParentElement, Gecko_GetParentNode};
+use bindings::{Gecko_GetPrevSibling, Gecko_GetPrevSiblingElement};
+use bindings::{Gecko_IsHTMLElementInHTMLDocument, Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNode};
use bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
#[allow(unused_imports)] // Used in commented-out code.
use bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
@@ -334,7 +338,7 @@ impl<'le> TElement<'le> for GeckoElement<'le> {
fn synthesize_presentational_hints_for_legacy_attributes<V>(&self, _hints: &mut V)
where V: VecLike<DeclarationBlock<Vec<PropertyDeclaration>>>
{
- unimplemented!()
+ // FIXME(bholley) - Need to implement this.
}
#[inline]
@@ -356,27 +360,39 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
type Impl = ServoSelectorImpl;
fn parent_element(&self) -> Option<Self> {
- unimplemented!()
+ unsafe {
+ Gecko_GetParentElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
+ }
}
fn first_child_element(&self) -> Option<Self> {
- unimplemented!()
+ unsafe {
+ Gecko_GetFirstChildElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
+ }
}
fn last_child_element(&self) -> Option<Self> {
- unimplemented!()
+ unsafe {
+ Gecko_GetLastChildElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
+ }
}
fn prev_sibling_element(&self) -> Option<Self> {
- unimplemented!()
+ unsafe {
+ Gecko_GetPrevSiblingElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
+ }
}
fn next_sibling_element(&self) -> Option<Self> {
- unimplemented!()
+ unsafe {
+ Gecko_GetNextSiblingElement(self.element).as_ref().map(|el| GeckoElement::from_ref(el))
+ }
}
fn is_root(&self) -> bool {
- unimplemented!()
+ unsafe {
+ Gecko_IsRootElement(self.element) != 0
+ }
}
fn is_empty(&self) -> bool {
diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock
index d48c1c92f57..09893b87e30 100644
--- a/ports/gonk/Cargo.lock
+++ b/ports/gonk/Cargo.lock
@@ -1623,7 +1623,7 @@ dependencies = [
[[package]]
name = "servo-glutin"
-version = "0.4.8"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_glue 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1665,7 +1665,7 @@ dependencies = [
"servo-egl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-fontconfig 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"servo-freetype-sys 2.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "servo-glutin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "servo-glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"x11 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py
index 142a59e766f..d9d26366d20 100644
--- a/python/servo/testing_commands.py
+++ b/python/servo/testing_commands.py
@@ -109,7 +109,10 @@ class MachCommands(CommandBase):
"include_arg": "include"}),
("unit", {"kwargs": {},
"paths": [path.abspath(path.join("tests", "unit"))],
- "include_arg": "test_name"})
+ "include_arg": "test_name"}),
+ ("compiletest", {"kwargs": {"release": release},
+ "paths": [path.abspath(path.join("tests", "compiletest"))],
+ "include_arg": "test_name"})
])
suites_by_prefix = {path: k for k, v in suites.iteritems() if "paths" in v for path in v["paths"]}
@@ -207,6 +210,65 @@ class MachCommands(CommandBase):
if result != 0:
return result
+ @Command('test-compiletest',
+ description='Run compiletests',
+ category='testing')
+ @CommandArgument('--package', '-p', default=None, help="Specific package to test")
+ @CommandArgument('test_name', nargs=argparse.REMAINDER,
+ help="Only run tests that match this pattern or file path")
+ @CommandArgument('--release', default=False, action="store_true",
+ help="Run with a release build of servo")
+ def test_compiletest(self, test_name=None, package=None, release=False):
+ if test_name is None:
+ test_name = []
+
+ self.ensure_bootstrapped()
+
+ if package:
+ packages = {package}
+ else:
+ packages = set()
+
+ test_patterns = []
+ for test in test_name:
+ # add package if 'tests/compiletest/<package>'
+ match = re.search("tests/compiletest/(\\w+)/?$", test)
+ if match:
+ packages.add(match.group(1))
+ # add package & test if '<package>/<test>', 'tests/compiletest/<package>/<test>.rs', or similar
+ elif re.search("\\w/\\w", test):
+ tokens = test.split("/")
+ packages.add(tokens[-2])
+ test_prefix = tokens[-1]
+ if test_prefix.endswith(".rs"):
+ test_prefix = test_prefix[:-3]
+ test_prefix += "::"
+ test_patterns.append(test_prefix)
+ # add test as-is otherwise
+ else:
+ test_patterns.append(test)
+
+ if not packages:
+ packages = set(os.listdir(path.join(self.context.topdir, "tests", "compiletest")))
+
+ packages.remove("helper")
+
+ args = ["cargo", "test"]
+ for crate in packages:
+ args += ["-p", "%s_compiletest" % crate]
+ args += test_patterns
+
+ env = self.build_env()
+ if release:
+ env["BUILD_MODE"] = "release"
+ args += ["--release"]
+ else:
+ env["BUILD_MODE"] = "debug"
+
+ result = call(args, env=env, cwd=self.servo_crate())
+ if result != 0:
+ return result
+
@Command('test-ref',
description='Run the reference tests',
category='testing')
diff --git a/python/tidy.py b/python/tidy.py
index c474c601954..2e160a5703a 100644
--- a/python/tidy.py
+++ b/python/tidy.py
@@ -168,7 +168,7 @@ def check_lock(file_name, contents):
raise StopIteration
# package names to be neglected (as named by cargo)
- exceptions = ["cocoa"]
+ exceptions = []
import toml
content = toml.loads(contents)
diff --git a/tests/compiletest/helper/Cargo.toml b/tests/compiletest/helper/Cargo.toml
new file mode 100644
index 00000000000..a5c3028d53c
--- /dev/null
+++ b/tests/compiletest/helper/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "compiletest_helper"
+version = "0.0.1"
+authors = ["The Servo Project Developers"]
+
+[lib]
+name = "compiletest_helper"
+path = "lib.rs"
+doctest = false
+
+[dependencies.compiletest_rs]
+compiletest_rs = "0.11"
diff --git a/tests/compiletest/helper/lib.rs b/tests/compiletest/helper/lib.rs
new file mode 100644
index 00000000000..2ec43d3f522
--- /dev/null
+++ b/tests/compiletest/helper/lib.rs
@@ -0,0 +1,29 @@
+/* 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/. */
+
+extern crate compiletest_rs as compiletest;
+
+use std::env;
+use std::path::PathBuf;
+
+pub fn run_mode(mode: &'static str) {
+
+ let mut config = compiletest::default_config();
+ let cfg_mode = mode.parse().ok().expect("Invalid mode");
+
+ config.mode = cfg_mode;
+ config.src_base = PathBuf::from(format!("{}", mode));
+
+ let mut base_path = env::current_dir().expect("Current directory is invalid");
+ base_path.pop();
+ base_path.pop();
+ base_path.pop();
+
+ let mode = env::var("BUILD_MODE").expect("BUILD_MODE environment variable must be set");
+ let debug_path = base_path.join(PathBuf::from(format!("target/{}", mode)));
+ let deps_path = base_path.join(PathBuf::from(format!("target/{}/deps", mode)));
+
+ config.target_rustcflags = Some(format!("-L {} -L {}", debug_path.display(), deps_path.display()));
+ compiletest::run_tests(&config);
+}
diff --git a/tests/compiletest/plugin/Cargo.toml b/tests/compiletest/plugin/Cargo.toml
new file mode 100644
index 00000000000..6ba2a22f198
--- /dev/null
+++ b/tests/compiletest/plugin/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "plugin_compiletest"
+version = "0.0.1"
+authors = ["The Servo Project Developers"]
+
+[lib]
+name = "plugin_compiletest"
+path = "lib.rs"
+doctest = false
+
+[dependencies.compiletest_helper]
+path = "../helper"
+
+[dependencies.plugins]
+path = "../../../components/plugins"
diff --git a/tests/compiletest/plugin/compile-fail/ban.rs b/tests/compiletest/plugin/compile-fail/ban.rs
new file mode 100644
index 00000000000..b789597d59d
--- /dev/null
+++ b/tests/compiletest/plugin/compile-fail/ban.rs
@@ -0,0 +1,18 @@
+/* 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/. */
+
+#![feature(plugin)]
+#![plugin(plugins)]
+
+extern crate js;
+
+use js::jsval::JSVal;
+use std::cell::Cell;
+
+struct Foo {
+ bar: Cell<JSVal>
+ //~^ ERROR Banned type Cell<JSVal> detected. Use MutHeap<JSVal> instead,
+}
+
+fn main() {}
diff --git a/tests/compiletest/plugin/compile-fail/privatize.rs b/tests/compiletest/plugin/compile-fail/privatize.rs
new file mode 100644
index 00000000000..a6f2ffdbe62
--- /dev/null
+++ b/tests/compiletest/plugin/compile-fail/privatize.rs
@@ -0,0 +1,16 @@
+/* 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/. */
+
+#![feature(plugin, custom_attribute)]
+#![plugin(plugins)]
+#![allow(dead_code)]
+
+#[privatize]
+struct Foo {
+ pub v1: i32,
+ //~^ ERROR Field v1 is public where only private fields are allowed
+ v2: i32
+}
+
+fn main() {}
diff --git a/tests/compiletest/plugin/compile-fail/str_to_string.rs b/tests/compiletest/plugin/compile-fail/str_to_string.rs
new file mode 100644
index 00000000000..ee45ee39b96
--- /dev/null
+++ b/tests/compiletest/plugin/compile-fail/str_to_string.rs
@@ -0,0 +1,16 @@
+/* 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/. */
+
+#![feature(plugin)]
+#![plugin(plugins)]
+
+
+fn main() {
+ let x = "foo".to_string();
+ //~^ ERROR str.to_owned() is more efficient than str.to_string()
+
+ let x = &x[..];
+ x.to_string();
+ //~^ ERROR str.to_owned() is more efficient than str.to_string()
+}
diff --git a/tests/compiletest/plugin/compile-fail/transmute_type.rs b/tests/compiletest/plugin/compile-fail/transmute_type.rs
new file mode 100644
index 00000000000..42bdd8c8c0f
--- /dev/null
+++ b/tests/compiletest/plugin/compile-fail/transmute_type.rs
@@ -0,0 +1,19 @@
+/* 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/. */
+
+#![feature(plugin)]
+#![plugin(plugins)]
+#![allow(dead_code)]
+#![deny(transmute_type_lint)]
+
+use std::mem::{self, transmute};
+
+
+fn main() {
+ let _: &[u8] = unsafe { transmute("Rust") };
+ //~^ ERROR Transmute to &[u8] from &'static str detected
+
+ let _: &[u8] = unsafe { mem::transmute("Rust") };
+ //~^ ERROR Transmute to &[u8] from &'static str detected
+}
diff --git a/tests/compiletest/plugin/compile-fail/unrooted_must_root.rs b/tests/compiletest/plugin/compile-fail/unrooted_must_root.rs
new file mode 100644
index 00000000000..f9b6d29dbee
--- /dev/null
+++ b/tests/compiletest/plugin/compile-fail/unrooted_must_root.rs
@@ -0,0 +1,27 @@
+/* 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/. */
+
+#![feature(plugin)]
+#![plugin(plugins)]
+#![allow(dead_code)]
+
+#[must_root]
+struct Foo {
+ v: i32
+}
+
+struct Bar {
+ f: Foo
+ //~^ ERROR Type must be rooted, use #[must_root] on the struct definition to propagate
+}
+
+fn foo1(_: Foo) {} //~ ERROR Type must be rooted
+
+
+fn foo2() -> Foo { //~ ERROR Type must be rooted
+ Foo { v: 10 }
+}
+
+
+fn main() {}
diff --git a/tests/compiletest/plugin/lib.rs b/tests/compiletest/plugin/lib.rs
new file mode 100644
index 00000000000..d3466c57b9b
--- /dev/null
+++ b/tests/compiletest/plugin/lib.rs
@@ -0,0 +1,10 @@
+/* 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/. */
+
+extern crate compiletest_helper;
+
+#[test]
+fn compile_test() {
+ compiletest_helper::run_mode("compile-fail");
+}