Skip to content

Commit 1e32e91

Browse files
authored
Merge pull request #460 from ohanar/webidl_partial_mixins
webidl: add support for partial interfaces and mixins
2 parents d7a0512 + 80384d8 commit 1e32e91

File tree

10 files changed

+914
-465
lines changed

10 files changed

+914
-465
lines changed

crates/backend/src/ast.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub struct Program {
1010
pub enums: Vec<Enum>,
1111
pub structs: Vec<Struct>,
1212
pub type_aliases: Vec<TypeAlias>,
13+
pub consts: Vec<Const>,
1314
}
1415

1516
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
@@ -42,7 +43,6 @@ pub enum ImportKind {
4243
Static(ImportStatic),
4344
Type(ImportType),
4445
Enum(ImportEnum),
45-
Const(Const),
4646
}
4747

4848
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
@@ -179,7 +179,7 @@ pub struct TypeAlias {
179179
pub struct Const {
180180
pub vis: syn::Visibility,
181181
pub name: Ident,
182-
pub interface_name: Ident,
182+
pub class: Option<Ident>,
183183
pub ty: syn::Type,
184184
pub value: ConstValue,
185185
}
@@ -312,7 +312,6 @@ impl ImportKind {
312312
ImportKind::Static(_) => false,
313313
ImportKind::Type(_) => false,
314314
ImportKind::Enum(_) => false,
315-
ImportKind::Const(_) => false,
316315
}
317316
}
318317

@@ -322,7 +321,6 @@ impl ImportKind {
322321
ImportKind::Static(ref f) => shared::ImportKind::Static(f.shared()),
323322
ImportKind::Type(ref f) => shared::ImportKind::Type(f.shared()),
324323
ImportKind::Enum(ref f) => shared::ImportKind::Enum(f.shared()),
325-
ImportKind::Const(ref f) => shared::ImportKind::Const(f.shared()),
326324
}
327325
}
328326
}
@@ -425,9 +423,3 @@ impl StructField {
425423
}
426424
}
427425
}
428-
429-
impl Const {
430-
fn shared(&self) -> shared::Const {
431-
shared::Const {}
432-
}
433-
}

crates/backend/src/codegen.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ impl ToTokens for ast::Program {
6262
for a in self.type_aliases.iter() {
6363
a.to_tokens(tokens);
6464
}
65+
for c in self.consts.iter() {
66+
c.to_tokens(tokens);
67+
}
6568

6669
// Generate a static which will eventually be what lives in a custom section
6770
// of the wasm executable. For now it's just a plain old static, but we'll
@@ -502,7 +505,6 @@ impl ToTokens for ast::ImportKind {
502505
ast::ImportKind::Static(ref s) => s.to_tokens(tokens),
503506
ast::ImportKind::Type(ref t) => t.to_tokens(tokens),
504507
ast::ImportKind::Enum(ref e) => e.to_tokens(tokens),
505-
ast::ImportKind::Const(ref c) => c.to_tokens(tokens),
506508
}
507509
}
508510
}
@@ -845,7 +847,6 @@ impl<'a> ToTokens for DescribeImport<'a> {
845847
ast::ImportKind::Static(_) => return,
846848
ast::ImportKind::Type(_) => return,
847849
ast::ImportKind::Enum(_) => return,
848-
ast::ImportKind::Const(_) => return,
849850
};
850851
let describe_name = format!("__wbindgen_describe_{}", f.shim);
851852
let describe_name = Ident::new(&describe_name, Span::call_site());
@@ -969,7 +970,6 @@ impl ToTokens for ast::Const {
969970

970971
let vis = &self.vis;
971972
let name = &self.name;
972-
let interface_name = &self.interface_name;
973973
let ty = &self.ty;
974974

975975
let value: TokenStream = match self.value {
@@ -986,17 +986,24 @@ impl ToTokens for ast::Const {
986986
FloatLiteral(f) => {
987987
let f = Literal::f64_unsuffixed(f);
988988
quote!(#f)
989-
},
989+
}
990990
IntegerLiteral(i) => {
991991
let i = Literal::i64_unsuffixed(i);
992992
quote!(#i)
993-
},
993+
}
994994
Null => unimplemented!(),
995995
};
996-
(quote! {
997-
impl #interface_name {
998-
#vis const #name: #ty = #value;
999-
}
1000-
}).to_tokens(tokens);
996+
997+
let declaration = quote!(#vis const #name: #ty = #value;);
998+
999+
if let Some(class) = &self.class {
1000+
(quote! {
1001+
impl #class {
1002+
#declaration
1003+
}
1004+
}).to_tokens(tokens);
1005+
} else {
1006+
declaration.to_tokens(tokens);
1007+
}
10011008
}
10021009
}

crates/backend/src/defined.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ impl ImportedTypes for ast::Program {
7070
{
7171
self.imports.imported_types(f);
7272
self.type_aliases.imported_types(f);
73+
self.consts.imported_types(f);
7374
}
7475
}
7576

@@ -106,7 +107,6 @@ impl ImportedTypes for ast::ImportKind {
106107
ast::ImportKind::Function(fun) => fun.imported_types(f),
107108
ast::ImportKind::Type(ty) => ty.imported_types(f),
108109
ast::ImportKind::Enum(enm) => enm.imported_types(f),
109-
ast::ImportKind::Const(c) => c.imported_types(f),
110110
}
111111
}
112112
}
@@ -254,6 +254,7 @@ impl RemoveUndefinedImports for ast::Program {
254254
{
255255
self.imports.remove_undefined_imports(is_defined);
256256
self.type_aliases.remove_undefined_imports(is_defined);
257+
self.consts.remove_undefined_imports(is_defined);
257258
}
258259
}
259260

crates/cli-support/src/js/mod.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,7 +1758,6 @@ impl<'a, 'b> SubContext<'a, 'b> {
17581758
}
17591759
shared::ImportKind::Type(_) => {}
17601760
shared::ImportKind::Enum(_) => {}
1761-
shared::ImportKind::Const(_) => {}
17621761
}
17631762
Ok(())
17641763
}
@@ -1918,9 +1917,7 @@ impl<'a, 'b> SubContext<'a, 'b> {
19181917
"
19191918
const {}_target = {} {} ;
19201919
",
1921-
import.shim,
1922-
target,
1923-
fallback
1920+
import.shim, target, fallback
19241921
));
19251922
format!(
19261923
"{}_target{}",
@@ -2020,9 +2017,7 @@ fn format_doc_comments(comments: &Vec<String>, js_doc_comments: Option<String>)
20202017
.map(|c| format!("*{}\n", c.trim_matches('"')))
20212018
.collect();
20222019
let doc = if let Some(docs) = js_doc_comments {
2023-
docs.lines()
2024-
.map(|l| format!("* {} \n", l))
2025-
.collect()
2020+
docs.lines().map(|l| format!("* {} \n", l)).collect()
20262021
} else {
20272022
String::new()
20282023
};

crates/shared/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ pub enum ImportKind {
3434
Static(ImportStatic),
3535
Type(ImportType),
3636
Enum(ImportEnum),
37-
Const(Const)
3837
}
3938

4039
#[derive(Deserialize, Serialize)]
@@ -125,9 +124,6 @@ pub struct StructField {
125124
pub comments: Vec<String>,
126125
}
127126

128-
#[derive(Deserialize, Serialize)]
129-
pub struct Const {}
130-
131127
pub fn new_function(struct_name: &str) -> String {
132128
let mut name = format!("__wbg_");
133129
name.extend(struct_name.chars().flat_map(|s| s.to_lowercase()));

crates/webidl/src/first_pass.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
use std::{
2+
collections::{BTreeMap, BTreeSet}, mem,
3+
};
4+
5+
use webidl;
6+
7+
use super::Result;
8+
9+
#[derive(Default)]
10+
pub(crate) struct FirstPassRecord<'a> {
11+
pub(crate) interfaces: BTreeSet<String>,
12+
pub(crate) dictionaries: BTreeSet<String>,
13+
pub(crate) enums: BTreeSet<String>,
14+
pub(crate) mixins: BTreeMap<String, MixinData<'a>>,
15+
}
16+
17+
#[derive(Default)]
18+
pub(crate) struct MixinData<'a> {
19+
pub(crate) non_partial: Option<&'a webidl::ast::NonPartialMixin>,
20+
pub(crate) partials: Vec<&'a webidl::ast::PartialMixin>,
21+
}
22+
23+
pub(crate) trait FirstPass {
24+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()>;
25+
}
26+
27+
impl FirstPass for [webidl::ast::Definition] {
28+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
29+
for def in self {
30+
def.first_pass(record)?;
31+
}
32+
33+
Ok(())
34+
}
35+
}
36+
37+
impl FirstPass for webidl::ast::Definition {
38+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
39+
use webidl::ast::Definition::*;
40+
41+
match self {
42+
Dictionary(dictionary) => dictionary.first_pass(record),
43+
Enum(enum_) => enum_.first_pass(record),
44+
Interface(interface) => interface.first_pass(record),
45+
Mixin(mixin) => mixin.first_pass(record),
46+
_ => {
47+
// Other definitions aren't currently used in the first pass
48+
Ok(())
49+
}
50+
}
51+
}
52+
}
53+
54+
impl FirstPass for webidl::ast::Dictionary {
55+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
56+
use webidl::ast::Dictionary::*;
57+
58+
match self {
59+
NonPartial(dictionary) => dictionary.first_pass(record),
60+
_ => {
61+
// Other dictionaries aren't currently used in the first pass
62+
Ok(())
63+
}
64+
}
65+
}
66+
}
67+
68+
impl FirstPass for webidl::ast::NonPartialDictionary {
69+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
70+
if record.dictionaries.insert(self.name.clone()) {
71+
warn!("Encountered multiple declarations of {}", self.name);
72+
}
73+
74+
Ok(())
75+
}
76+
}
77+
78+
impl FirstPass for webidl::ast::Enum {
79+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
80+
if record.enums.insert(self.name.clone()) {
81+
warn!("Encountered multiple declarations of {}", self.name);
82+
}
83+
84+
Ok(())
85+
}
86+
}
87+
88+
impl FirstPass for webidl::ast::Interface {
89+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
90+
use webidl::ast::Interface::*;
91+
92+
match self {
93+
NonPartial(interface) => interface.first_pass(record),
94+
_ => {
95+
// Other interfaces aren't currently used in the first pass
96+
Ok(())
97+
}
98+
}
99+
}
100+
}
101+
102+
impl FirstPass for webidl::ast::NonPartialInterface {
103+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
104+
if record.interfaces.insert(self.name.clone()) {
105+
warn!("Encountered multiple declarations of {}", self.name);
106+
}
107+
108+
Ok(())
109+
}
110+
}
111+
112+
impl FirstPass for webidl::ast::Mixin {
113+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
114+
use webidl::ast::Mixin::*;
115+
116+
match self {
117+
NonPartial(mixin) => mixin.first_pass(record),
118+
Partial(mixin) => mixin.first_pass(record),
119+
}
120+
}
121+
}
122+
123+
impl FirstPass for webidl::ast::NonPartialMixin {
124+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
125+
let entry = record
126+
.mixins
127+
.entry(self.name.clone())
128+
.or_insert(Default::default());
129+
if mem::replace(&mut entry.non_partial, Some(self)).is_some() {
130+
warn!(
131+
"Encounterd multiple declarations of {}, using last encountered",
132+
self.name
133+
);
134+
}
135+
136+
Ok(())
137+
}
138+
}
139+
140+
impl FirstPass for webidl::ast::PartialMixin {
141+
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>) -> Result<()> {
142+
let entry = record
143+
.mixins
144+
.entry(self.name.clone())
145+
.or_insert(Default::default());
146+
entry.partials.push(self);
147+
148+
Ok(())
149+
}
150+
}

0 commit comments

Comments
 (0)