webidl: add support for partial interfaces and mixins

This is a major change to how webidl is processed. This adds
a two phase process, where the first phase records the names of
various types and indexes the mixins (and might do more in the
future). The actual program building happens in the second phase.

As part of this, this also makes it so that interface objects
are passed by reference, rather than by value. The spec isn't
exactly clear on this, but Mozilla's C++ reflection suggestions
seem to indicate that they should be passed by reference (see
https://developer.mozilla.org/en-US/docs/Mozilla/WebIDL_bindings).
This commit is contained in:
R. Andrew Ohana
2018-07-10 22:59:59 -07:00
parent 7a579be629
commit 5b952f2081
3 changed files with 744 additions and 412 deletions

View File

@@ -44,14 +44,14 @@ fn method() {
let pi = Foo::new(3.14159).unwrap();
let e = Foo::new(2.71828).unwrap();
// TODO: figure out why the following doesn't fail
// assert!(!pi.my_cmp(Foo::new(3.14159).unwrap()));
let tmp = pi.my_cmp(Foo::new(3.14159).unwrap());
// assert!(!pi.my_cmp(&pi));
let tmp = pi.my_cmp(&pi);
assert!(tmp);
let tmp =!pi.my_cmp(Foo::new(2.71828).unwrap());
let tmp =!pi.my_cmp(&e);
assert!(tmp);
let tmp = !e.my_cmp(Foo::new(3.14159).unwrap());
let tmp = !e.my_cmp(&pi);
assert!(tmp);
let tmp = e.my_cmp(Foo::new(2.71828).unwrap());
let tmp = e.my_cmp(&e);
assert!(tmp);
}
"#,
@@ -370,3 +370,130 @@ fn unforgeable_is_structural() {
)
.test();
}
#[test]
fn partial_interface() {
project()
.file(
"foo.webidl",
r#"
[Constructor]
interface Foo {
readonly attribute short un;
short deux();
};
partial interface Foo {
readonly attribute short trois;
short quatre();
};
"#,
)
.file(
"foo.js",
r#"
export class Foo {
get un() {
return 1;
}
deux() {
return 2;
}
get trois() {
return 3;
}
quatre() {
return 4;
}
}
"#,
)
.file(
"src/lib.rs",
r#"
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
pub mod foo;
#[wasm_bindgen]
pub fn test() {
let f = foo::Foo::new().unwrap();
assert_eq!(f.un(), 1);
assert_eq!(f.deux(), 2);
assert_eq!(f.trois(), 3);
assert_eq!(f.quatre(), 4);
}
"#,
)
.test();
}
#[test]
fn mixin() {
project()
.file(
"foo.webidl",
r#"
[Constructor(short bar)]
interface Foo {
static attribute short defaultBar;
};
interface mixin Bar {
readonly attribute short bar;
};
partial interface mixin Bar {
void addToBar(short other);
};
Foo includes Bar;
"#,
)
.file(
"foo.js",
r#"
export class Foo {
constructor(bar) {
this._bar = bar | Foo.defaultBar;
}
static get defaultBar() {
return Foo._defaultBar;
}
static set defaultBar(defaultBar) {
Foo._defaultBar = defaultBar;
}
get bar() {
return this._bar;
}
addToBar(other) {
this._bar += other;
}
}
"#,
)
.file(
"src/lib.rs",
r#"
#![feature(proc_macro, wasm_custom_section, wasm_import_module)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
pub mod foo;
use foo::Foo;
#[wasm_bindgen]
pub fn test() {
let f = Foo::new(1).unwrap();
assert_eq!(f.bar(), 1);
Foo::set_default_bar(7);
f.add_to_bar(Foo::default_bar());
assert_eq!(f.bar(), 8);
}
"#,
)
.test();
}