Skip to content

Commit

Permalink
Derive DomObject with a proc macro
Browse files Browse the repository at this point in the history
  • Loading branch information
nox committed Feb 14, 2017
1 parent 1dfdd0b commit c84cea9
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 91 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions components/domobject_derive/Cargo.toml
@@ -0,0 +1,14 @@
[package]
name = "domobject_derive"
version = "0.0.1"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
publish = false

[lib]
path = "lib.rs"
proc-macro = true

[dependencies]
syn = "0.10"
quote = "0.3"
53 changes: 53 additions & 0 deletions components/domobject_derive/lib.rs
@@ -0,0 +1,53 @@
/* 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 proc_macro;
#[macro_use] extern crate quote;
extern crate syn;

#[proc_macro_derive(DomObject)]
pub fn expand_token_stream(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
expand_string(&input.to_string()).parse().unwrap()
}

fn expand_string(input: &str) -> String {
let type_ = syn::parse_macro_input(input).unwrap();

let first_field_name = if let syn::Body::Struct(syn::VariantData::Struct(ref fields)) = type_.body {
let first_field = fields.first().expect("#[derive(DomObject)] should not be applied on empty structs");
first_field.ident.as_ref().unwrap()
} else {
panic!("#[derive(DomObject)] should only be applied on proper structs")
};

let name = &type_.ident;
let (impl_generics, ty_generics, where_clause) = type_.generics.split_for_impl();

let tokens = quote! {
impl #impl_generics ::js::conversions::ToJSValConvertible for #name #ty_generics #where_clause {
#[allow(unsafe_code)]
unsafe fn to_jsval(&self,
cx: *mut ::js::jsapi::JSContext,
rval: ::js::jsapi::MutableHandleValue) {
let object = ::dom::bindings::reflector::DomObject::reflector(self).get_jsobject();
object.to_jsval(cx, rval)
}
}

impl #impl_generics ::dom::bindings::reflector::DomObject for #name #ty_generics #where_clause {
#[inline]
fn reflector(&self) -> &::dom::bindings::reflector::Reflector {
self.#first_field_name.reflector()
}
}

impl #impl_generics ::dom::bindings::reflector::MutDomObject for #name #ty_generics #where_clause {
fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
self.#first_field_name.init_reflector(obj);
}
}
};

tokens.to_string()
}
4 changes: 1 addition & 3 deletions components/plugins/jstraceable.rs
Expand Up @@ -15,9 +15,7 @@ pub fn expand_dom_struct(cx: &mut ExtCtxt, sp: Span, _: &MetaItem, anno: Annotat
item2.attrs.push(quote_attr!(cx, #[repr(C)]));
item2.attrs.push(quote_attr!(cx, #[derive(JSTraceable)]));
item2.attrs.push(quote_attr!(cx, #[derive(HeapSizeOf)]));

// The following attributes are only for internal usage
item2.attrs.push(quote_attr!(cx, #[_generate_reflector]));
item2.attrs.push(quote_attr!(cx, #[derive(DomObject)]));
// #[dom_struct] gets consumed, so this lets us keep around a residue
// Do NOT register a modifier/decorator on this attribute
item2.attrs.push(quote_attr!(cx, #[_dom_struct_marker]));
Expand Down
6 changes: 0 additions & 6 deletions components/plugins/lib.rs
Expand Up @@ -34,8 +34,6 @@ use syntax::symbol::Symbol;
/// Handles the auto-deriving for `#[derive(JSTraceable)]`
pub mod jstraceable;
pub mod lints;
/// Autogenerates implementations of DomObject on DOM structs
pub mod reflector;
/// Utilities for writing plugins
mod utils;

Expand All @@ -45,10 +43,6 @@ pub fn plugin_registrar(reg: &mut Registry) {
Symbol::intern("dom_struct"),
MultiModifier(box jstraceable::expand_dom_struct));

reg.register_syntax_extension(
Symbol::intern("_generate_reflector"),
MultiDecorator(box reflector::expand_reflector));

reg.register_late_lint_pass(box lints::unrooted_must_root::UnrootedPass::new());
reg.register_late_lint_pass(box lints::privatize::PrivatizePass);
reg.register_late_lint_pass(box lints::inheritance_integrity::InheritancePass);
Expand Down
82 changes: 0 additions & 82 deletions components/plugins/reflector.rs

This file was deleted.

1 change: 1 addition & 0 deletions components/script/Cargo.toml
Expand Up @@ -36,6 +36,7 @@ caseless = "0.1.0"
cookie = {version = "0.2.5", features = ["serialize-rustc"]}
cssparser = {version = "0.7", features = ["heap_size", "serde-serialization"]}
devtools_traits = {path = "../devtools_traits"}
domobject_derive = {path = "../domobject_derive"}
encoding = "0.2"
euclid = "0.10.1"
fnv = "1.0"
Expand Down
12 changes: 12 additions & 0 deletions components/script/dom/bindings/reflector.rs
Expand Up @@ -83,8 +83,20 @@ pub trait DomObject {
}
}

impl DomObject for Reflector {
fn reflector(&self) -> &Self {
self
}
}

/// A trait to initialize the `Reflector` for a DOM object.
pub trait MutDomObject: DomObject {
/// Initializes the Reflector
fn init_reflector(&mut self, obj: *mut JSObject);
}

impl MutDomObject for Reflector {
fn init_reflector(&mut self, obj: *mut JSObject) {
self.set_jsobject(obj)
}
}
2 changes: 2 additions & 0 deletions components/script/lib.rs
Expand Up @@ -39,6 +39,8 @@ extern crate core;
#[macro_use]
extern crate cssparser;
extern crate devtools_traits;
#[macro_use]
extern crate domobject_derive;
extern crate encoding;
extern crate euclid;
extern crate fnv;
Expand Down

0 comments on commit c84cea9

Please sign in to comment.