mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-20 08:16:31 +00:00
Migrate from the webidl
crate to weedle
This commit migrates the `wasm-bindgen-webidl` crate from the `webidl` parser to
`weedle`. The main rationale for doing this is that `webidl` depends on
`lalrpop`, which is quite a large dependency and takes a good deal of time to
compile. The `weedle` crate, however, depends on `nom` and is much faster to
compile.
Almost all translations were pretty straightforward. Some abstractions changed
and/or were introduced in this commit when moving to `weedle` like the
`ToSynType` trait, but otherwise the generated bindings should be the same. It's
been verified that the `weedle`-generated bindings are exactly the same as the
`webidl`-generated bindings, with the one exception of `weedle` generates one
more method, `WebGpuCommandEncoder::transition_buffer`. It's not clear currently
why `webidl` didn't generate this method, as its [idl] is pretty straightforward!
This commit is using a [fork] of `weedle` currently which has a number of fixes
for parsing our WebIDL, although all the fixes are quite minor!
Closes #620
[idl]: d66b834afd/crates/web-sys/webidls/enabled/WebGPU.webidl (L499)
[fork]: https://github.com/alexcrichton/weedle/tree/fix-for-web-sys
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
extern crate wasm_bindgen_webidl;
|
extern crate wasm_bindgen_webidl;
|
||||||
extern crate sourcefile;
|
extern crate sourcefile;
|
||||||
@ -8,9 +9,8 @@ use sourcefile::SourceFile;
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Write;
|
|
||||||
use std::path;
|
use std::path;
|
||||||
use std::process;
|
use std::process::{self, Command};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if let Err(e) = try_main() {
|
if let Err(e) = try_main() {
|
||||||
@ -32,12 +32,14 @@ fn try_main() -> Result<(), failure::Error> {
|
|||||||
let mut source = SourceFile::default();
|
let mut source = SourceFile::default();
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let entry = entry.context("getting webidls/enabled/*.webidl entry")?;
|
let entry = entry.context("getting webidls/enabled/*.webidl entry")?;
|
||||||
if entry.path().extension() == Some(OsStr::new("webidl")) {
|
let path = entry.path();
|
||||||
println!("cargo:rerun-if-changed={}", entry.path().display());
|
if path.extension() != Some(OsStr::new("webidl")) {
|
||||||
source = source.add_file(entry.path())
|
continue
|
||||||
.with_context(|_| format!("reading contents of file \"{}\"",
|
|
||||||
entry.path().display()))?;
|
|
||||||
}
|
}
|
||||||
|
println!("cargo:rerun-if-changed={}", path.display());
|
||||||
|
source = source.add_file(&path)
|
||||||
|
.with_context(|_| format!("reading contents of file \"{}\"",
|
||||||
|
path.display()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let bindings = match wasm_bindgen_webidl::compile(&source.contents) {
|
let bindings = match wasm_bindgen_webidl::compile(&source.contents) {
|
||||||
@ -60,17 +62,19 @@ fn try_main() -> Result<(), failure::Error> {
|
|||||||
|
|
||||||
let out_dir = env::var("OUT_DIR").context("reading OUT_DIR environment variable")?;
|
let out_dir = env::var("OUT_DIR").context("reading OUT_DIR environment variable")?;
|
||||||
let out_file_path = path::Path::new(&out_dir).join("bindings.rs");
|
let out_file_path = path::Path::new(&out_dir).join("bindings.rs");
|
||||||
let mut out_file = fs::File::create(&out_file_path)
|
fs::write(&out_file_path, bindings)
|
||||||
.context("creating output bindings file")?;
|
|
||||||
out_file
|
|
||||||
.write_all(bindings.as_bytes())
|
|
||||||
.context("writing bindings to output file")?;
|
.context("writing bindings to output file")?;
|
||||||
|
|
||||||
// run rustfmt on the generated file - really handy for debugging
|
// run rustfmt on the generated file - really handy for debugging
|
||||||
//if ! process::Command::new("rustfmt").arg(&out_file_path).status()
|
if env::var("WEBIDL_RUSTFMT_BINDINGS").is_ok() {
|
||||||
// .context("running rustfmt")?.success() {
|
let status = Command::new("rustfmt")
|
||||||
// return Err(format_err!("rustfmt failed to format {}", out_file_path.display()));
|
.arg(&out_file_path)
|
||||||
//}
|
.status()
|
||||||
|
.context("running rustfmt")?;
|
||||||
|
if !status.success() {
|
||||||
|
bail!("rustfmt failed: {}", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -20,4 +20,4 @@ proc-macro2 = "0.4.8"
|
|||||||
quote = '0.6'
|
quote = '0.6'
|
||||||
syn = { version = '0.14', features = ['full'] }
|
syn = { version = '0.14', features = ['full'] }
|
||||||
wasm-bindgen-backend = { version = "=0.2.15", path = "../backend" }
|
wasm-bindgen-backend = { version = "=0.2.15", path = "../backend" }
|
||||||
webidl = "0.7.0"
|
weedle = "0.6"
|
||||||
|
@ -7,66 +7,58 @@
|
|||||||
//! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can
|
//! Only `interface`s, `dictionary`s, `enum`s and `mixin`s can
|
||||||
//! be partial.
|
//! be partial.
|
||||||
|
|
||||||
use std::{
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
collections::{BTreeMap, BTreeSet}, mem,
|
|
||||||
};
|
|
||||||
|
|
||||||
use webidl;
|
use weedle::argument::Argument;
|
||||||
|
use weedle::attribute::ExtendedAttribute;
|
||||||
|
use weedle::interface::StringifierOrStatic;
|
||||||
|
use weedle::mixin::MixinMembers;
|
||||||
|
use weedle;
|
||||||
|
|
||||||
use super::Result;
|
use super::Result;
|
||||||
|
use util;
|
||||||
|
|
||||||
/// Collection of constructs that may use partial.
|
/// Collection of constructs that may use partial.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct FirstPassRecord<'a> {
|
pub(crate) struct FirstPassRecord<'src> {
|
||||||
pub(crate) interfaces: BTreeMap<String, InterfaceData>,
|
pub(crate) interfaces: BTreeMap<&'src str, InterfaceData<'src>>,
|
||||||
pub(crate) dictionaries: BTreeSet<String>,
|
pub(crate) dictionaries: BTreeSet<&'src str>,
|
||||||
pub(crate) enums: BTreeSet<String>,
|
pub(crate) enums: BTreeSet<&'src str>,
|
||||||
/// The mixins, mapping their name to the webidl ast node for the mixin.
|
/// The mixins, mapping their name to the webidl ast node for the mixin.
|
||||||
pub(crate) mixins: BTreeMap<String, MixinData<'a>>,
|
pub(crate) mixins: BTreeMap<&'src str, Vec<&'src MixinMembers<'src>>>,
|
||||||
pub(crate) typedefs: BTreeMap<String, webidl::ast::Type>,
|
pub(crate) typedefs: BTreeMap<&'src str, &'src weedle::types::Type<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We need to collect interface data during the first pass, to be used later.
|
/// We need to collect interface data during the first pass, to be used later.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct InterfaceData {
|
pub(crate) struct InterfaceData<'src> {
|
||||||
/// Whether only partial interfaces were encountered
|
/// Whether only partial interfaces were encountered
|
||||||
pub(crate) partial: bool,
|
pub(crate) partial: bool,
|
||||||
pub(crate) operations: BTreeMap<OperationId, OperationData>,
|
|
||||||
pub(crate) global: bool,
|
pub(crate) global: bool,
|
||||||
|
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub(crate) enum OperationId {
|
pub(crate) enum OperationId<'src> {
|
||||||
Constructor,
|
Constructor,
|
||||||
Operation(Option<String>)
|
Operation(Option<&'src str>)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct OperationData {
|
pub(crate) struct OperationData<'src> {
|
||||||
pub(crate) overloaded: bool,
|
pub(crate) overloaded: bool,
|
||||||
/// Map from argument names to whether they are the same for multiple overloads
|
/// Map from argument names to whether they are the same for multiple overloads
|
||||||
pub(crate) argument_names_same: BTreeMap<Vec<String>, bool>,
|
pub(crate) argument_names_same: BTreeMap<Vec<&'src str>, bool>,
|
||||||
}
|
|
||||||
|
|
||||||
/// We need to collect mixin data during the first pass, to be used later.
|
|
||||||
#[derive(Default)]
|
|
||||||
pub(crate) struct MixinData<'a> {
|
|
||||||
/// The non partial mixin, if present. If there is more than one, we are
|
|
||||||
/// parsing is a malformed WebIDL file, but the parser will recover by
|
|
||||||
/// using the last parsed mixin.
|
|
||||||
pub(crate) non_partial: Option<&'a webidl::ast::NonPartialMixin>,
|
|
||||||
/// 0 or more partial mixins.
|
|
||||||
pub(crate) partials: Vec<&'a webidl::ast::PartialMixin>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implemented on an AST node to populate the `FirstPassRecord` struct.
|
/// Implemented on an AST node to populate the `FirstPassRecord` struct.
|
||||||
pub(crate) trait FirstPass<Ctx> {
|
pub(crate) trait FirstPass<'src, Ctx> {
|
||||||
/// Populate `record` with any constructs in `self`.
|
/// Populate `record` with any constructs in `self`.
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, ctx: Ctx) -> Result<()>;
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, ctx: Ctx) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for [webidl::ast::Definition] {
|
impl<'src> FirstPass<'src, ()> for [weedle::Definition<'src>] {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
for def in self {
|
for def in self {
|
||||||
def.first_pass(record, ())?;
|
def.first_pass(record, ())?;
|
||||||
}
|
}
|
||||||
@ -75,15 +67,17 @@ impl FirstPass<()> for [webidl::ast::Definition] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::Definition {
|
impl<'src> FirstPass<'src, ()> for weedle::Definition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
use webidl::ast::Definition::*;
|
use weedle::Definition::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Dictionary(dictionary) => dictionary.first_pass(record, ()),
|
Dictionary(dictionary) => dictionary.first_pass(record, ()),
|
||||||
Enum(enum_) => enum_.first_pass(record, ()),
|
Enum(enum_) => enum_.first_pass(record, ()),
|
||||||
Interface(interface) => interface.first_pass(record, ()),
|
Interface(interface) => interface.first_pass(record, ()),
|
||||||
Mixin(mixin) => mixin.first_pass(record, ()),
|
PartialInterface(interface) => interface.first_pass(record, ()),
|
||||||
|
InterfaceMixin(mixin) => mixin.first_pass(record, ()),
|
||||||
|
PartialInterfaceMixin(mixin) => mixin.first_pass(record, ()),
|
||||||
Typedef(typedef) => typedef.first_pass(record, ()),
|
Typedef(typedef) => typedef.first_pass(record, ()),
|
||||||
_ => {
|
_ => {
|
||||||
// Other definitions aren't currently used in the first pass
|
// Other definitions aren't currently used in the first pass
|
||||||
@ -93,46 +87,38 @@ impl FirstPass<()> for webidl::ast::Definition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::Dictionary {
|
impl<'src> FirstPass<'src, ()> for weedle::DictionaryDefinition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
use webidl::ast::Dictionary::*;
|
if !record.dictionaries.insert(self.identifier.0) {
|
||||||
|
warn!("encountered multiple dictionary declarations of {}", self.identifier.0);
|
||||||
match self {
|
|
||||||
NonPartial(dictionary) => dictionary.first_pass(record, ()),
|
|
||||||
_ => {
|
|
||||||
// Other dictionaries aren't currently used in the first pass
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::NonPartialDictionary {
|
impl<'src> FirstPass<'src, ()> for weedle::EnumDefinition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
if record.dictionaries.insert(self.name.clone()) {
|
if !record.enums.insert(self.identifier.0) {
|
||||||
warn!("Encountered multiple declarations of {}", self.name);
|
warn!("Encountered multiple enum declarations of {}", self.identifier.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::Enum {
|
fn first_pass_operation<'src>(
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
record: &mut FirstPassRecord<'src>,
|
||||||
if record.enums.insert(self.name.clone()) {
|
self_name: &'src str,
|
||||||
warn!("Encountered multiple declarations of {}", self.name);
|
id: OperationId<'src>,
|
||||||
}
|
arguments: &[Argument<'src>],
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn first_pass_operation<'a>(
|
|
||||||
record: &mut FirstPassRecord<'a>,
|
|
||||||
self_name: &str,
|
|
||||||
id: OperationId,
|
|
||||||
arguments: &[webidl::ast::Argument],
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let mut names = Vec::with_capacity(arguments.len());
|
||||||
|
for argument in arguments {
|
||||||
|
match argument {
|
||||||
|
Argument::Single(arg) => names.push(arg.identifier.0),
|
||||||
|
Argument::Variadic(_) => return Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
record
|
record
|
||||||
.interfaces
|
.interfaces
|
||||||
.get_mut(self_name)
|
.get_mut(self_name)
|
||||||
@ -140,77 +126,48 @@ fn first_pass_operation<'a>(
|
|||||||
.operations
|
.operations
|
||||||
.entry(id)
|
.entry(id)
|
||||||
.and_modify(|operation_data| operation_data.overloaded = true)
|
.and_modify(|operation_data| operation_data.overloaded = true)
|
||||||
.or_insert_with(||
|
.or_insert_with(Default::default)
|
||||||
OperationData {
|
|
||||||
overloaded: false,
|
|
||||||
argument_names_same: Default::default(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.argument_names_same
|
.argument_names_same
|
||||||
.entry(arguments.iter().map(|argument| argument.name.clone()).collect())
|
.entry(names)
|
||||||
.and_modify(|same_argument_names| *same_argument_names = true)
|
.and_modify(|same_argument_names| *same_argument_names = true)
|
||||||
.or_insert(false);
|
.or_insert(false);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::Interface {
|
impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
use webidl::ast::Interface::*;
|
{
|
||||||
|
let interface = record
|
||||||
match self {
|
.interfaces
|
||||||
Partial(interface) => interface.first_pass(record, ()),
|
.entry(self.identifier.0)
|
||||||
NonPartial(interface) => interface.first_pass(record, ()),
|
.or_insert_with(Default::default);
|
||||||
// TODO
|
interface.partial = false;
|
||||||
Callback(..) => {
|
|
||||||
warn!("Unsupported WebIDL interface: {:?}", self);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::NonPartialInterface {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
|
||||||
record
|
|
||||||
.interfaces
|
|
||||||
.entry(self.name.clone())
|
|
||||||
.and_modify(|interface_data| {
|
|
||||||
if interface_data.partial {
|
|
||||||
interface_data.partial = false;
|
|
||||||
} else {
|
|
||||||
warn!("Encountered multiple declarations of {}", self.name);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.or_insert_with(||
|
|
||||||
InterfaceData {
|
|
||||||
partial: false,
|
|
||||||
operations: Default::default(),
|
|
||||||
global: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if ::util::is_chrome_only(&self.extended_attributes) {
|
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
for extended_attribute in &self.extended_attributes {
|
if let Some(attrs) = &self.attributes {
|
||||||
extended_attribute.first_pass(record, &self.name)?;
|
for attr in &attrs.body.list {
|
||||||
|
attr.first_pass(record, self.identifier.0)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for member in &self.members {
|
for member in &self.members.body {
|
||||||
member.first_pass(record, &self.name)?;
|
member.first_pass(record, self.identifier.0)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::PartialInterface {
|
impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
record
|
record
|
||||||
.interfaces
|
.interfaces
|
||||||
.entry(self.name.clone())
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(||
|
.or_insert_with(||
|
||||||
InterfaceData {
|
InterfaceData {
|
||||||
partial: true,
|
partial: true,
|
||||||
@ -219,168 +176,120 @@ impl FirstPass<()> for webidl::ast::PartialInterface {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if ::util::is_chrome_only(&self.extended_attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(())
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
for member in &self.members {
|
for member in &self.members.body {
|
||||||
member.first_pass(record, &self.name)?;
|
member.first_pass(record, self.identifier.0)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> FirstPass<&'b str> for webidl::ast::ExtendedAttribute {
|
impl<'src> FirstPass<'src, &'src str> for ExtendedAttribute<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
webidl::ast::ExtendedAttribute::ArgumentList(
|
ExtendedAttribute::ArgList(list) if list.identifier.0 == "Constructor" => {
|
||||||
webidl::ast::ArgumentListExtendedAttribute { arguments, name },
|
first_pass_operation(
|
||||||
)
|
record,
|
||||||
if name == "Constructor" =>
|
self_name,
|
||||||
{
|
OperationId::Constructor,
|
||||||
first_pass_operation(
|
&list.args.body.list,
|
||||||
record,
|
)
|
||||||
self_name,
|
}
|
||||||
OperationId::Constructor,
|
ExtendedAttribute::NoArgs(name) if (name.0).0 == "Constructor" => {
|
||||||
&arguments,
|
first_pass_operation(
|
||||||
)
|
record,
|
||||||
}
|
self_name,
|
||||||
webidl::ast::ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name))
|
OperationId::Constructor,
|
||||||
if name == "Constructor" =>
|
&[],
|
||||||
{
|
)
|
||||||
first_pass_operation(
|
}
|
||||||
record,
|
ExtendedAttribute::NamedArgList(list)
|
||||||
self_name,
|
if list.lhs_identifier.0 == "NamedConstructor" =>
|
||||||
OperationId::Constructor,
|
{
|
||||||
&[],
|
first_pass_operation(
|
||||||
)
|
record,
|
||||||
}
|
self_name,
|
||||||
webidl::ast::ExtendedAttribute::NamedArgumentList(
|
OperationId::Constructor,
|
||||||
webidl::ast::NamedArgumentListExtendedAttribute {
|
&list.args.body.list,
|
||||||
lhs_name,
|
)
|
||||||
rhs_arguments,
|
}
|
||||||
..
|
ExtendedAttribute::Ident(id) if id.lhs_identifier.0 == "Global" => {
|
||||||
},
|
record.interfaces.get_mut(self_name).unwrap().global = true;
|
||||||
)
|
Ok(())
|
||||||
if lhs_name == "NamedConstructor" =>
|
}
|
||||||
{
|
ExtendedAttribute::IdentList(id) if id.identifier.0 == "Global" => {
|
||||||
first_pass_operation(
|
record.interfaces.get_mut(self_name).unwrap().global = true;
|
||||||
record,
|
Ok(())
|
||||||
self_name,
|
}
|
||||||
OperationId::Constructor,
|
|
||||||
&rhs_arguments,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
webidl::ast::ExtendedAttribute::Identifier(
|
|
||||||
webidl::ast::IdentifierExtendedAttribute { lhs, .. }
|
|
||||||
)
|
|
||||||
| webidl::ast::ExtendedAttribute::IdentifierList(
|
|
||||||
webidl::ast::IdentifierListExtendedAttribute { lhs, .. }
|
|
||||||
)
|
|
||||||
if lhs == "Global" =>
|
|
||||||
{
|
|
||||||
record.interfaces.get_mut(self_name).unwrap().global = true;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Ok(())
|
_ => Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> FirstPass<&'b str> for webidl::ast::InterfaceMember {
|
impl<'src> FirstPass<'src, &'src str> for weedle::interface::InterfaceMember<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
webidl::ast::InterfaceMember::Operation(op) => op.first_pass(record, self_name),
|
weedle::interface::InterfaceMember::Operation(op) => {
|
||||||
|
op.first_pass(record, self_name)
|
||||||
|
}
|
||||||
_ => Ok(()),
|
_ => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> FirstPass<&'b str> for webidl::ast::Operation {
|
impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceMember<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
|
||||||
match self {
|
if self.specials.len() > 0 {
|
||||||
webidl::ast::Operation::Regular(op) => op.first_pass(record, self_name),
|
warn!("Unsupported webidl operation {:?}", self);
|
||||||
webidl::ast::Operation::Static(op) => op.first_pass(record, self_name),
|
return Ok(())
|
||||||
// TODO
|
}
|
||||||
webidl::ast::Operation::Special(_) | webidl::ast::Operation::Stringifier(_) => {
|
if let Some(StringifierOrStatic::Stringifier(_)) = self.modifier {
|
||||||
warn!("Unsupported WebIDL operation: {:?}", self);
|
warn!("Unsupported webidl operation {:?}", self);
|
||||||
Ok(())
|
return Ok(())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'b> FirstPass<&'b str> for webidl::ast::RegularOperation {
|
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
|
|
||||||
first_pass_operation(
|
first_pass_operation(
|
||||||
record,
|
record,
|
||||||
self_name,
|
self_name,
|
||||||
OperationId::Operation(self.name.clone()),
|
OperationId::Operation(self.identifier.map(|s| s.0)),
|
||||||
&self.arguments,
|
&self.args.body.list,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> FirstPass<&'b str> for webidl::ast::StaticOperation {
|
impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src>{
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, self_name: &'b str) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
first_pass_operation(
|
record
|
||||||
record,
|
|
||||||
self_name,
|
|
||||||
OperationId::Operation(self.name.clone()),
|
|
||||||
&self.arguments,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::Mixin {
|
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
|
||||||
use webidl::ast::Mixin::*;
|
|
||||||
|
|
||||||
match self {
|
|
||||||
NonPartial(mixin) => mixin.first_pass(record, ()),
|
|
||||||
Partial(mixin) => mixin.first_pass(record, ()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::NonPartialMixin {
|
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
|
||||||
let entry = record
|
|
||||||
.mixins
|
.mixins
|
||||||
.entry(self.name.clone())
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default)
|
||||||
if mem::replace(&mut entry.non_partial, Some(self)).is_some() {
|
.push(&self.members.body);
|
||||||
warn!(
|
|
||||||
"Encounterd multiple declarations of {}, using last encountered",
|
|
||||||
self.name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::PartialMixin {
|
impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceMixinDefinition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
let entry = record
|
record
|
||||||
.mixins
|
.mixins
|
||||||
.entry(self.name.clone())
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default)
|
||||||
entry.partials.push(self);
|
.push(&self.members.body);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FirstPass<()> for webidl::ast::Typedef {
|
impl<'src> FirstPass<'src, ()> for weedle::TypedefDefinition<'src> {
|
||||||
fn first_pass<'a>(&'a self, record: &mut FirstPassRecord<'a>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
if ::util::is_chrome_only(&self.extended_attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if record.typedefs.insert(self.name.clone(), *self.type_.clone()).is_some() {
|
if record.typedefs.insert(self.identifier.0, &self.type_.type_).is_some() {
|
||||||
warn!("Encountered multiple declarations of {}", self.name);
|
warn!("Encountered multiple declarations of {}", self.identifier.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -9,6 +9,7 @@ emitted for the types and methods described in the WebIDL.
|
|||||||
#![deny(missing_debug_implementations)]
|
#![deny(missing_debug_implementations)]
|
||||||
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-webidl/0.2")]
|
#![doc(html_root_url = "https://docs.rs/wasm-bindgen-webidl/0.2")]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
extern crate failure;
|
extern crate failure;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate failure_derive;
|
extern crate failure_derive;
|
||||||
@ -21,7 +22,7 @@ extern crate quote;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate syn;
|
extern crate syn;
|
||||||
extern crate wasm_bindgen_backend as backend;
|
extern crate wasm_bindgen_backend as backend;
|
||||||
extern crate webidl;
|
extern crate weedle;
|
||||||
|
|
||||||
mod first_pass;
|
mod first_pass;
|
||||||
mod util;
|
mod util;
|
||||||
@ -36,11 +37,14 @@ use std::path::Path;
|
|||||||
use backend::TryToTokens;
|
use backend::TryToTokens;
|
||||||
use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports};
|
use backend::defined::{ImportedTypeDefinitions, RemoveUndefinedImports};
|
||||||
use backend::util::{ident_ty, rust_ident, wrap_import_function};
|
use backend::util::{ident_ty, rust_ident, wrap_import_function};
|
||||||
use failure::{ResultExt, Fail};
|
use failure::ResultExt;
|
||||||
use heck::{ShoutySnakeCase};
|
use heck::{ShoutySnakeCase};
|
||||||
|
use weedle::argument::Argument;
|
||||||
|
use weedle::attribute::{ExtendedAttribute, ExtendedAttributeList};
|
||||||
|
|
||||||
use first_pass::{FirstPass, FirstPassRecord};
|
use first_pass::{FirstPass, FirstPassRecord};
|
||||||
use util::{ApplyTypedefs, public, webidl_const_ty_to_syn_ty, webidl_const_v_to_backend_const_v, camel_case_ident, mdn_doc};
|
use util::{public, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, mdn_doc};
|
||||||
|
use util::ToSynType;
|
||||||
|
|
||||||
pub use error::{Error, ErrorKind, Result};
|
pub use error::{Error, ErrorKind, Result};
|
||||||
|
|
||||||
@ -55,22 +59,31 @@ fn parse_file(webidl_path: &Path) -> Result<backend::ast::Program> {
|
|||||||
|
|
||||||
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
|
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
|
||||||
fn parse(webidl_source: &str) -> Result<backend::ast::Program> {
|
fn parse(webidl_source: &str) -> Result<backend::ast::Program> {
|
||||||
let definitions = match webidl::parse_string(webidl_source) {
|
let definitions = match weedle::parse(webidl_source) {
|
||||||
Ok(def) => def,
|
Ok(def) => def,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let kind = match &e {
|
return Err(match &e {
|
||||||
webidl::ParseError::InvalidToken { location } => {
|
weedle::Err::Incomplete(needed) => {
|
||||||
ErrorKind::ParsingWebIDLSourcePos(*location)
|
format_err!("needed {:?} more bytes", needed)
|
||||||
|
.context(ErrorKind::ParsingWebIDLSource).into()
|
||||||
}
|
}
|
||||||
webidl::ParseError::UnrecognizedToken { token: Some((start, ..)), .. } => {
|
weedle::Err::Error(cx) |
|
||||||
ErrorKind::ParsingWebIDLSourcePos(*start)
|
weedle::Err::Failure(cx) => {
|
||||||
|
let remaining = match cx {
|
||||||
|
weedle::Context::Code(remaining, _) => remaining,
|
||||||
|
};
|
||||||
|
let pos = webidl_source.len() - remaining.len();
|
||||||
|
format_err!("failed to parse WebIDL")
|
||||||
|
.context(ErrorKind::ParsingWebIDLSourcePos(pos)).into()
|
||||||
}
|
}
|
||||||
webidl::ParseError::ExtraToken { token: (start, ..) } => {
|
// webidl::ParseError::UnrecognizedToken { token: Some((start, ..)), .. } => {
|
||||||
ErrorKind::ParsingWebIDLSourcePos(*start)
|
// ErrorKind::ParsingWebIDLSourcePos(*start)
|
||||||
},
|
// }
|
||||||
_ => ErrorKind::ParsingWebIDLSource
|
// webidl::ParseError::ExtraToken { token: (start, ..) } => {
|
||||||
};
|
// ErrorKind::ParsingWebIDLSourcePos(*start)
|
||||||
return Err(e.context(kind).into());
|
// },
|
||||||
|
// _ => ErrorKind::ParsingWebIDLSource
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -119,21 +132,21 @@ fn compile_ast(mut ast: backend::ast::Program) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The main trait for parsing WebIDL AST into wasm-bindgen AST.
|
/// The main trait for parsing WebIDL AST into wasm-bindgen AST.
|
||||||
trait WebidlParse<Ctx> {
|
trait WebidlParse<'src, Ctx> {
|
||||||
/// Parse `self` into wasm-bindgen AST, and insert it into `program`.
|
/// Parse `self` into wasm-bindgen AST, and insert it into `program`.
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
context: Ctx,
|
context: Ctx,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebidlParse<()> for [webidl::ast::Definition] {
|
impl<'src> WebidlParse<'src, ()> for [weedle::Definition<'src>] {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
(): (),
|
(): (),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for def in self {
|
for def in self {
|
||||||
@ -143,104 +156,85 @@ impl WebidlParse<()> for [webidl::ast::Definition] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebidlParse<()> for webidl::ast::Definition {
|
impl<'src> WebidlParse<'src, ()> for weedle::Definition<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
(): (),
|
(): (),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
webidl::ast::Definition::Enum(enumeration) => {
|
weedle::Definition::Enum(enumeration) => {
|
||||||
enumeration.webidl_parse(program, first_pass, ())?
|
enumeration.webidl_parse(program, first_pass, ())?
|
||||||
}
|
}
|
||||||
webidl::ast::Definition::Includes(includes) => {
|
weedle::Definition::IncludesStatement(includes) => {
|
||||||
includes.webidl_parse(program, first_pass, ())?
|
includes.webidl_parse(program, first_pass, ())?
|
||||||
}
|
}
|
||||||
webidl::ast::Definition::Interface(interface) => {
|
weedle::Definition::Interface(interface) => {
|
||||||
interface.webidl_parse(program, first_pass, ())?
|
interface.webidl_parse(program, first_pass, ())?
|
||||||
}
|
}
|
||||||
// TODO
|
weedle::Definition::PartialInterface(interface) => {
|
||||||
webidl::ast::Definition::Callback(..)
|
interface.webidl_parse(program, first_pass, ())?
|
||||||
| webidl::ast::Definition::Dictionary(..)
|
|
||||||
| webidl::ast::Definition::Implements(..)
|
|
||||||
| webidl::ast::Definition::Namespace(..) => {
|
|
||||||
warn!("Unsupported WebIDL definition: {:?}", self)
|
|
||||||
}
|
}
|
||||||
webidl::ast::Definition::Mixin(_)
|
weedle::Definition::Typedef(_) |
|
||||||
| webidl::ast::Definition::Typedef(_) => {
|
weedle::Definition::InterfaceMixin(_) |
|
||||||
|
weedle::Definition::PartialInterfaceMixin(_) => {
|
||||||
// handled in the first pass
|
// handled in the first pass
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebidlParse<()> for webidl::ast::Includes {
|
|
||||||
fn webidl_parse(
|
|
||||||
&self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
first_pass: &FirstPassRecord<'_>,
|
|
||||||
(): (),
|
|
||||||
) -> Result<()> {
|
|
||||||
match first_pass.mixins.get(&self.includee) {
|
|
||||||
Some(mixin) => {
|
|
||||||
if let Some(non_partial) = mixin.non_partial {
|
|
||||||
for member in &non_partial.members {
|
|
||||||
member.webidl_parse(program, first_pass, &self.includer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for partial in &mixin.partials {
|
|
||||||
for member in &partial.members {
|
|
||||||
member.webidl_parse(program, first_pass, &self.includer)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => warn!("Tried to include missing mixin {}", self.includee),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebidlParse<()> for webidl::ast::Interface {
|
|
||||||
fn webidl_parse(
|
|
||||||
&self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
first_pass: &FirstPassRecord<'_>,
|
|
||||||
(): (),
|
|
||||||
) -> Result<()> {
|
|
||||||
match self {
|
|
||||||
webidl::ast::Interface::NonPartial(interface) => {
|
|
||||||
interface.webidl_parse(program, first_pass, ())
|
|
||||||
}
|
|
||||||
webidl::ast::Interface::Partial(interface) => {
|
|
||||||
interface.webidl_parse(program, first_pass, ())
|
|
||||||
}
|
|
||||||
// TODO
|
// TODO
|
||||||
webidl::ast::Interface::Callback(..) => {
|
weedle::Definition::Callback(..)
|
||||||
warn!("Unsupported WebIDL interface: {:?}", self);
|
| weedle::Definition::CallbackInterface(..)
|
||||||
Ok(())
|
| weedle::Definition::Dictionary(..)
|
||||||
|
| weedle::Definition::PartialDictionary(..)
|
||||||
|
| weedle::Definition::Implements(..)
|
||||||
|
| weedle::Definition::Namespace(..)
|
||||||
|
| weedle::Definition::PartialNamespace(..) => {
|
||||||
|
warn!("Unsupported WebIDL definition: {:?}", self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebidlParse<()> for webidl::ast::NonPartialInterface {
|
impl<'src> WebidlParse<'src, ()> for weedle::IncludesStatementDefinition<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
(): (),
|
(): (),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
match first_pass.mixins.get(self.rhs_identifier.0) {
|
||||||
|
Some(member_lists) => {
|
||||||
|
for member in member_lists.iter().flat_map(|list| list.iter()) {
|
||||||
|
member.webidl_parse(program, first_pass, self.lhs_identifier.0)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => warn!("Tried to include missing mixin {}", self.rhs_identifier.0),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> WebidlParse<'src, ()> for weedle::InterfaceDefinition<'src> {
|
||||||
|
fn webidl_parse(
|
||||||
|
&'src self,
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
first_pass: &FirstPassRecord<'src>,
|
||||||
|
(): (),
|
||||||
|
) -> Result<()> {
|
||||||
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if util::is_no_interface_object(&self.extended_attributes) {
|
if util::is_no_interface_object(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let doc_comment = Some(format!("The `{}` object\n\n{}", &self.name, mdn_doc(&self.name, None)));
|
let doc_comment = Some(format!(
|
||||||
|
"The `{}` object\n\n{}",
|
||||||
|
self.identifier.0,
|
||||||
|
mdn_doc(self.identifier.0, None),
|
||||||
|
));
|
||||||
|
|
||||||
program.imports.push(backend::ast::Import {
|
program.imports.push(backend::ast::Import {
|
||||||
module: None,
|
module: None,
|
||||||
@ -248,70 +242,67 @@ impl WebidlParse<()> for webidl::ast::NonPartialInterface {
|
|||||||
js_namespace: None,
|
js_namespace: None,
|
||||||
kind: backend::ast::ImportKind::Type(backend::ast::ImportType {
|
kind: backend::ast::ImportKind::Type(backend::ast::ImportType {
|
||||||
vis: public(),
|
vis: public(),
|
||||||
name: rust_ident(camel_case_ident(&self.name).as_str()),
|
name: rust_ident(camel_case_ident(self.identifier.0).as_str()),
|
||||||
attrs: Vec::new(),
|
attrs: Vec::new(),
|
||||||
doc_comment,
|
doc_comment,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
for extended_attribute in &self.extended_attributes {
|
if let Some(attrs) = &self.attributes {
|
||||||
extended_attribute.webidl_parse(program, first_pass, self)?;
|
for attr in &attrs.body.list {
|
||||||
|
attr.webidl_parse(program, first_pass, self)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for member in &self.members {
|
for member in &self.members.body {
|
||||||
member.webidl_parse(program, first_pass, &self.name)?;
|
member.webidl_parse(program, first_pass, self.identifier.0)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebidlParse<()> for webidl::ast::PartialInterface {
|
impl<'src> WebidlParse<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
(): (),
|
(): (),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !first_pass.interfaces.contains_key(&self.name) {
|
if !first_pass.interfaces.contains_key(self.identifier.0) {
|
||||||
warn!(
|
warn!(
|
||||||
"Partial interface {} missing non-partial interface",
|
"Partial interface {} missing non-partial interface",
|
||||||
self.name
|
self.identifier.0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for member in &self.members {
|
for member in &self.members.body {
|
||||||
member.webidl_parse(program, first_pass, &self.name)?;
|
member.webidl_parse(program, first_pass, self.identifier.0)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::ExtendedAttribute {
|
impl<'src> WebidlParse<'src, &'src weedle::InterfaceDefinition<'src>> for ExtendedAttribute<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
interface: &'a webidl::ast::NonPartialInterface,
|
interface: &'src weedle::InterfaceDefinition<'src>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut add_constructor = |arguments: &[webidl::ast::Argument], class: &str| {
|
let mut add_constructor = |arguments: &[Argument], class: &str| {
|
||||||
let arguments = &arguments
|
|
||||||
.iter()
|
|
||||||
.map(|argument| argument.apply_typedefs(first_pass))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let (overloaded, same_argument_names) = first_pass.get_operation_overloading(
|
let (overloaded, same_argument_names) = first_pass.get_operation_overloading(
|
||||||
arguments,
|
arguments,
|
||||||
::first_pass::OperationId::Constructor,
|
::first_pass::OperationId::Constructor,
|
||||||
&interface.name,
|
interface.identifier.0,
|
||||||
);
|
);
|
||||||
|
|
||||||
let self_ty = ident_ty(rust_ident(camel_case_ident(&interface.name).as_str()));
|
let self_ty = ident_ty(rust_ident(camel_case_ident(interface.identifier.0).as_str()));
|
||||||
|
|
||||||
let kind = backend::ast::ImportFunctionKind::Method {
|
let kind = backend::ast::ImportFunctionKind::Method {
|
||||||
class: class.to_string(),
|
class: class.to_string(),
|
||||||
@ -340,9 +331,7 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte
|
|||||||
"new",
|
"new",
|
||||||
overloaded,
|
overloaded,
|
||||||
same_argument_names,
|
same_argument_names,
|
||||||
arguments
|
arguments,
|
||||||
.iter()
|
|
||||||
.map(|arg| (&*arg.name, &*arg.type_, arg.variadic)),
|
|
||||||
Some(self_ty),
|
Some(self_ty),
|
||||||
kind,
|
kind,
|
||||||
structural,
|
structural,
|
||||||
@ -354,34 +343,24 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte
|
|||||||
};
|
};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
webidl::ast::ExtendedAttribute::ArgumentList(
|
ExtendedAttribute::ArgList(list)
|
||||||
webidl::ast::ArgumentListExtendedAttribute { arguments, name },
|
if list.identifier.0 == "Constructor" =>
|
||||||
)
|
|
||||||
if name == "Constructor" =>
|
|
||||||
{
|
{
|
||||||
add_constructor(arguments, &interface.name)
|
add_constructor(&list.args.body.list, interface.identifier.0)
|
||||||
}
|
}
|
||||||
webidl::ast::ExtendedAttribute::NoArguments(webidl::ast::Other::Identifier(name))
|
ExtendedAttribute::NoArgs(other) if (other.0).0 == "Constructor" => {
|
||||||
if name == "Constructor" =>
|
add_constructor(&[], interface.identifier.0)
|
||||||
|
}
|
||||||
|
ExtendedAttribute::NamedArgList(list)
|
||||||
|
if list.lhs_identifier.0 == "NamedConstructor" =>
|
||||||
{
|
{
|
||||||
add_constructor(&[], &interface.name)
|
add_constructor(&list.args.body.list, list.rhs_identifier.0)
|
||||||
}
|
}
|
||||||
webidl::ast::ExtendedAttribute::NamedArgumentList(
|
ExtendedAttribute::ArgList(_)
|
||||||
webidl::ast::NamedArgumentListExtendedAttribute {
|
| ExtendedAttribute::Ident(_)
|
||||||
lhs_name,
|
| ExtendedAttribute::IdentList(_)
|
||||||
rhs_arguments,
|
| ExtendedAttribute::NamedArgList(_)
|
||||||
rhs_name,
|
| ExtendedAttribute::NoArgs(_) => {
|
||||||
},
|
|
||||||
)
|
|
||||||
if lhs_name == "NamedConstructor" =>
|
|
||||||
{
|
|
||||||
add_constructor(rhs_arguments, rhs_name)
|
|
||||||
}
|
|
||||||
webidl::ast::ExtendedAttribute::ArgumentList(_)
|
|
||||||
| webidl::ast::ExtendedAttribute::Identifier(_)
|
|
||||||
| webidl::ast::ExtendedAttribute::IdentifierList(_)
|
|
||||||
| webidl::ast::ExtendedAttribute::NamedArgumentList(_)
|
|
||||||
| webidl::ast::ExtendedAttribute::NoArguments(_) => {
|
|
||||||
warn!("Unsupported WebIDL extended attribute: {:?}", self);
|
warn!("Unsupported WebIDL extended attribute: {:?}", self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,29 +369,32 @@ impl<'a> WebidlParse<&'a webidl::ast::NonPartialInterface> for webidl::ast::Exte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::InterfaceMember {
|
impl<'src> WebidlParse<'src, &'src str> for weedle::interface::InterfaceMember<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
self_name: &'a str,
|
self_name: &'src str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
use weedle::interface::InterfaceMember::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
webidl::ast::InterfaceMember::Attribute(attr) => {
|
Attribute(attr) => {
|
||||||
attr.webidl_parse(program, first_pass, self_name)
|
attr.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
webidl::ast::InterfaceMember::Operation(op) => {
|
Operation(op) => {
|
||||||
op.webidl_parse(program, first_pass, self_name)
|
op.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
webidl::ast::InterfaceMember::Const(cnst) => {
|
Const(cnst) => {
|
||||||
cnst.webidl_parse(program, first_pass, self_name)
|
cnst.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
webidl::ast::InterfaceMember::Iterable(iterable) => {
|
Iterable(iterable) => {
|
||||||
iterable.webidl_parse(program, first_pass, self_name)
|
iterable.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
// TODO
|
// TODO
|
||||||
| webidl::ast::InterfaceMember::Maplike(_)
|
| Maplike(_)
|
||||||
| webidl::ast::InterfaceMember::Setlike(_) => {
|
| Stringifier(_)
|
||||||
|
| Setlike(_) => {
|
||||||
warn!("Unsupported WebIDL interface member: {:?}", self);
|
warn!("Unsupported WebIDL interface member: {:?}", self);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -420,128 +402,236 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::InterfaceMember {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::MixinMember {
|
impl<'a, 'src> WebidlParse<'src, &'a str> for weedle::mixin::MixinMember<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
self_name: &'a str,
|
self_name: &'a str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
webidl::ast::MixinMember::Attribute(attr) => {
|
weedle::mixin::MixinMember::Attribute(attr) => {
|
||||||
attr.webidl_parse(program, first_pass, self_name)
|
attr.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
webidl::ast::MixinMember::Operation(op) => {
|
weedle::mixin::MixinMember::Operation(op) => {
|
||||||
op.webidl_parse(program, first_pass, self_name)
|
op.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
// TODO
|
// TODO
|
||||||
webidl::ast::MixinMember::Const(_) => {
|
weedle::mixin::MixinMember::Stringifier(_) |
|
||||||
warn!("Unsupported WebIDL interface member: {:?}", self);
|
weedle::mixin::MixinMember::Const(_) => {
|
||||||
Ok(())
|
warn!("Unsupported WebIDL mixin member: {:?}", self);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::Attribute {
|
|
||||||
fn webidl_parse(
|
|
||||||
&self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
first_pass: &FirstPassRecord<'_>,
|
|
||||||
self_name: &'a str,
|
|
||||||
) -> Result<()> {
|
|
||||||
match self {
|
|
||||||
webidl::ast::Attribute::Regular(attr) => {
|
|
||||||
attr.webidl_parse(program, first_pass, self_name)
|
|
||||||
}
|
|
||||||
webidl::ast::Attribute::Static(attr) => {
|
|
||||||
attr.webidl_parse(program, first_pass, self_name)
|
|
||||||
}
|
|
||||||
// TODO
|
|
||||||
webidl::ast::Attribute::Stringifier(_) => {
|
|
||||||
warn!("Unsupported WebIDL attribute: {:?}", self);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::Operation {
|
impl<'src> WebidlParse<'src, &'src str> for weedle::interface::AttributeInterfaceMember<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
self_name: &'a str,
|
self_name: &'src str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self {
|
member_attribute(
|
||||||
webidl::ast::Operation::Regular(op) => op.webidl_parse(program, first_pass, self_name),
|
program,
|
||||||
webidl::ast::Operation::Static(op) => op.webidl_parse(program, first_pass, self_name),
|
first_pass,
|
||||||
// TODO
|
self_name,
|
||||||
webidl::ast::Operation::Special(_) | webidl::ast::Operation::Stringifier(_) => {
|
&self.attributes,
|
||||||
warn!("Unsupported WebIDL operation: {:?}", self);
|
self.modifier,
|
||||||
Ok(())
|
self.readonly.is_some(),
|
||||||
}
|
&self.type_,
|
||||||
}
|
self.identifier.0,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::RegularAttribute {
|
impl<'src> WebidlParse<'src, &'src str> for weedle::mixin::AttributeMixinMember<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
first_pass: &FirstPassRecord<'src>,
|
||||||
self_name: &'a str,
|
self_name: &'src str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
member_attribute(
|
||||||
return Ok(());
|
program,
|
||||||
|
first_pass,
|
||||||
|
self_name,
|
||||||
|
&self.attributes,
|
||||||
|
if let Some(s) = self.stringifier {
|
||||||
|
Some(weedle::interface::StringifierOrInheritOrStatic::Stringifier(s))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
self.readonly.is_some(),
|
||||||
|
&self.type_,
|
||||||
|
self.identifier.0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn member_attribute<'src>(
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
first_pass: &FirstPassRecord<'src>,
|
||||||
|
self_name: &'src str,
|
||||||
|
attrs: &'src Option<ExtendedAttributeList>,
|
||||||
|
modifier: Option<weedle::interface::StringifierOrInheritOrStatic>,
|
||||||
|
readonly: bool,
|
||||||
|
type_: &'src weedle::types::AttributedType<'src>,
|
||||||
|
identifier: &'src str,
|
||||||
|
) -> Result<()> {
|
||||||
|
use weedle::interface::StringifierOrInheritOrStatic::*;
|
||||||
|
|
||||||
|
if util::is_chrome_only(attrs) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let statik = match modifier {
|
||||||
|
Some(Stringifier(_)) => {
|
||||||
|
warn!("Unsupported stringifier on type {:?}", (self_name, identifier));
|
||||||
|
return Ok(())
|
||||||
}
|
}
|
||||||
|
Some(Inherit(_)) => false,
|
||||||
|
Some(Static(_)) => true,
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
|
||||||
let is_structural = util::is_structural(&self.extended_attributes);
|
if type_.attributes.is_some() {
|
||||||
let throws = util::throws(&self.extended_attributes);
|
warn!("Unsupported attributes on type {:?}", (self_name, identifier));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_structural = util::is_structural(attrs);
|
||||||
|
let throws = util::throws(attrs);
|
||||||
|
|
||||||
|
first_pass
|
||||||
|
.create_getter(
|
||||||
|
identifier,
|
||||||
|
&type_.type_,
|
||||||
|
self_name,
|
||||||
|
statik,
|
||||||
|
is_structural,
|
||||||
|
throws,
|
||||||
|
)
|
||||||
|
.map(wrap_import_function)
|
||||||
|
.map(|import| program.imports.push(import));
|
||||||
|
|
||||||
|
if !readonly {
|
||||||
first_pass
|
first_pass
|
||||||
.create_getter(
|
.create_setter(
|
||||||
&self.name,
|
identifier,
|
||||||
&self.type_.apply_typedefs(first_pass),
|
type_.type_.clone(),
|
||||||
self_name,
|
self_name,
|
||||||
false,
|
statik,
|
||||||
is_structural,
|
is_structural,
|
||||||
throws,
|
throws,
|
||||||
)
|
)
|
||||||
.map(wrap_import_function)
|
.map(wrap_import_function)
|
||||||
.map(|import| program.imports.push(import));
|
.map(|import| program.imports.push(import));
|
||||||
|
}
|
||||||
|
|
||||||
if !self.read_only {
|
Ok(())
|
||||||
first_pass
|
}
|
||||||
.create_setter(
|
|
||||||
&self.name,
|
|
||||||
&self.type_.apply_typedefs(first_pass),
|
|
||||||
self_name,
|
|
||||||
false,
|
|
||||||
is_structural,
|
|
||||||
throws,
|
|
||||||
)
|
|
||||||
.map(wrap_import_function)
|
|
||||||
.map(|import| program.imports.push(import));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
impl<'src> WebidlParse<'src, &'src str> for weedle::interface::OperationInterfaceMember<'src> {
|
||||||
|
fn webidl_parse(
|
||||||
|
&self,
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
first_pass: &FirstPassRecord<'src>,
|
||||||
|
self_name: &'src str,
|
||||||
|
) -> Result<()> {
|
||||||
|
member_operation(
|
||||||
|
program,
|
||||||
|
first_pass,
|
||||||
|
self_name,
|
||||||
|
&self.attributes,
|
||||||
|
self.modifier,
|
||||||
|
&self.specials,
|
||||||
|
&self.return_type,
|
||||||
|
&self.args.body.list,
|
||||||
|
&self.identifier,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::Iterable {
|
impl<'src> WebidlParse<'src, &'src str> for weedle::mixin::OperationMixinMember<'src> {
|
||||||
|
fn webidl_parse(
|
||||||
|
&self,
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
first_pass: &FirstPassRecord<'src>,
|
||||||
|
self_name: &'src str,
|
||||||
|
) -> Result<()> {
|
||||||
|
member_operation(
|
||||||
|
program,
|
||||||
|
first_pass,
|
||||||
|
self_name,
|
||||||
|
&self.attributes,
|
||||||
|
None,
|
||||||
|
&[],
|
||||||
|
&self.return_type,
|
||||||
|
&self.args.body.list,
|
||||||
|
&self.identifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn member_operation<'src>(
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
first_pass: &FirstPassRecord<'src>,
|
||||||
|
self_name: &'src str,
|
||||||
|
attrs: &'src Option<ExtendedAttributeList>,
|
||||||
|
modifier: Option<weedle::interface::StringifierOrStatic>,
|
||||||
|
specials: &[weedle::interface::Special],
|
||||||
|
return_type: &'src weedle::types::ReturnType<'src>,
|
||||||
|
args: &'src [Argument],
|
||||||
|
identifier: &Option<weedle::common::Identifier<'src>>,
|
||||||
|
) -> Result<()> {
|
||||||
|
use weedle::interface::StringifierOrStatic::*;
|
||||||
|
|
||||||
|
if util::is_chrome_only(attrs) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let statik = match modifier {
|
||||||
|
Some(Stringifier(_)) => {
|
||||||
|
warn!("Unsupported stringifier on type {:?}", (self_name, identifier));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
Some(Static(_)) => true,
|
||||||
|
None => false,
|
||||||
|
};
|
||||||
|
if specials.len() > 0 {
|
||||||
|
warn!("Unsupported specials on type {:?}", (self_name, identifier));
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
first_pass
|
||||||
|
.create_basic_method(
|
||||||
|
args,
|
||||||
|
identifier.map(|s| s.0),
|
||||||
|
return_type,
|
||||||
|
self_name,
|
||||||
|
statik,
|
||||||
|
util::throws(attrs),
|
||||||
|
)
|
||||||
|
.map(wrap_import_function)
|
||||||
|
.map(|import| program.imports.push(import));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> WebidlParse<'src, &'src str> for weedle::interface::IterableInterfaceMember<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&self,
|
||||||
_program: &mut backend::ast::Program,
|
_program: &mut backend::ast::Program,
|
||||||
_first_pass: &FirstPassRecord<'_>,
|
_first_pass: &FirstPassRecord<'src>,
|
||||||
_self_name: &'a str,
|
_self_name: &'src str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
// if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
// return Ok(());
|
||||||
}
|
// }
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
let throws = util::throws(&self.extended_attributes);
|
let throws = util::throws(&self.extended_attributes);
|
||||||
let return_value = webidl::ast::ReturnType::NonVoid(self.value_type.clone());
|
let return_value = weedle::ReturnType::NonVoid(self.value_type.clone());
|
||||||
let args = [];
|
let args = [];
|
||||||
first_pass
|
first_pass
|
||||||
.create_basic_method(
|
.create_basic_method(
|
||||||
@ -572,142 +662,32 @@ impl<'a> WebidlParse<&'a str> for webidl::ast::Iterable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::StaticAttribute {
|
impl<'src> WebidlParse<'src, ()> for weedle::EnumDefinition<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
_: &FirstPassRecord<'src>,
|
||||||
self_name: &'a str,
|
|
||||||
) -> Result<()> {
|
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let is_structural = util::is_structural(&self.extended_attributes);
|
|
||||||
let throws = util::throws(&self.extended_attributes);
|
|
||||||
|
|
||||||
first_pass
|
|
||||||
.create_getter(
|
|
||||||
&self.name,
|
|
||||||
&self.type_.apply_typedefs(first_pass),
|
|
||||||
self_name,
|
|
||||||
true,
|
|
||||||
is_structural,
|
|
||||||
throws,
|
|
||||||
)
|
|
||||||
.map(wrap_import_function)
|
|
||||||
.map(|import| program.imports.push(import));
|
|
||||||
|
|
||||||
if !self.read_only {
|
|
||||||
first_pass
|
|
||||||
.create_setter(
|
|
||||||
&self.name,
|
|
||||||
&self.type_.apply_typedefs(first_pass),
|
|
||||||
self_name,
|
|
||||||
true,
|
|
||||||
is_structural,
|
|
||||||
throws,
|
|
||||||
)
|
|
||||||
.map(wrap_import_function)
|
|
||||||
.map(|import| program.imports.push(import));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::RegularOperation {
|
|
||||||
fn webidl_parse(
|
|
||||||
&self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
first_pass: &FirstPassRecord<'_>,
|
|
||||||
self_name: &'a str,
|
|
||||||
) -> Result<()> {
|
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let throws = util::throws(&self.extended_attributes);
|
|
||||||
|
|
||||||
first_pass
|
|
||||||
.create_basic_method(
|
|
||||||
&self
|
|
||||||
.arguments
|
|
||||||
.iter()
|
|
||||||
.map(|argument| argument.apply_typedefs(first_pass))
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
self.name.as_ref(),
|
|
||||||
&self.return_type.apply_typedefs(first_pass),
|
|
||||||
self_name,
|
|
||||||
false,
|
|
||||||
throws,
|
|
||||||
)
|
|
||||||
.map(wrap_import_function)
|
|
||||||
.map(|import| program.imports.push(import));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::StaticOperation {
|
|
||||||
fn webidl_parse(
|
|
||||||
&self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
first_pass: &FirstPassRecord<'_>,
|
|
||||||
self_name: &'a str,
|
|
||||||
) -> Result<()> {
|
|
||||||
if util::is_chrome_only(&self.extended_attributes) {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let throws = util::throws(&self.extended_attributes);
|
|
||||||
|
|
||||||
first_pass
|
|
||||||
.create_basic_method(
|
|
||||||
&self
|
|
||||||
.arguments
|
|
||||||
.iter()
|
|
||||||
.map(|argument| argument.apply_typedefs(first_pass))
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
self.name.as_ref(),
|
|
||||||
&self.return_type.apply_typedefs(first_pass),
|
|
||||||
self_name,
|
|
||||||
true,
|
|
||||||
throws,
|
|
||||||
)
|
|
||||||
.map(wrap_import_function)
|
|
||||||
.map(|import| program.imports.push(import));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> WebidlParse<()> for webidl::ast::Enum {
|
|
||||||
fn webidl_parse(
|
|
||||||
&self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
_: &FirstPassRecord<'_>,
|
|
||||||
(): (),
|
(): (),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let variants = &self.values.body.list;
|
||||||
program.imports.push(backend::ast::Import {
|
program.imports.push(backend::ast::Import {
|
||||||
module: None,
|
module: None,
|
||||||
version: None,
|
version: None,
|
||||||
js_namespace: None,
|
js_namespace: None,
|
||||||
kind: backend::ast::ImportKind::Enum(backend::ast::ImportEnum {
|
kind: backend::ast::ImportKind::Enum(backend::ast::ImportEnum {
|
||||||
vis: public(),
|
vis: public(),
|
||||||
name: rust_ident(camel_case_ident(&self.name).as_str()),
|
name: rust_ident(camel_case_ident(self.identifier.0).as_str()),
|
||||||
variants: self
|
variants: variants
|
||||||
.variants
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v|
|
.map(|v| {
|
||||||
if !v.is_empty() {
|
if !v.0.is_empty() {
|
||||||
rust_ident(camel_case_ident(&v).as_str())
|
rust_ident(camel_case_ident(&v.0).as_str())
|
||||||
} else {
|
} else {
|
||||||
rust_ident("None")
|
rust_ident("None")
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
variant_values: self.variants.clone(),
|
variant_values: variants.iter().map(|v| v.0.to_string()).collect(),
|
||||||
rust_attrs: vec![parse_quote!(#[derive(Copy, Clone, PartialEq, Debug)])],
|
rust_attrs: vec![parse_quote!(#[derive(Copy, Clone, PartialEq, Debug)])],
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@ -716,21 +696,24 @@ impl<'a> WebidlParse<()> for webidl::ast::Enum {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WebidlParse<&'a str> for webidl::ast::Const {
|
impl<'src> WebidlParse<'src, &'src str> for weedle::interface::ConstMember<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&self,
|
&'src self,
|
||||||
program: &mut backend::ast::Program,
|
program: &mut backend::ast::Program,
|
||||||
first_pass: &FirstPassRecord<'_>,
|
record: &FirstPassRecord<'src>,
|
||||||
self_name: &'a str,
|
self_name: &'src str,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ty = webidl_const_ty_to_syn_ty(&self.type_.apply_typedefs(first_pass));
|
let ty = match self.const_type.to_syn_type(record, TypePosition::Return) {
|
||||||
|
Some(s) => s,
|
||||||
|
None => return Ok(()),
|
||||||
|
};
|
||||||
|
|
||||||
program.consts.push(backend::ast::Const {
|
program.consts.push(backend::ast::Const {
|
||||||
vis: public(),
|
vis: public(),
|
||||||
name: rust_ident(self.name.to_shouty_snake_case().as_str()),
|
name: rust_ident(self.identifier.0.to_shouty_snake_case().as_str()),
|
||||||
class: Some(rust_ident(camel_case_ident(&self_name).as_str())),
|
class: Some(rust_ident(camel_case_ident(&self_name).as_str())),
|
||||||
ty,
|
ty,
|
||||||
value: webidl_const_v_to_backend_const_v(&self.value),
|
value: webidl_const_v_to_backend_const_v(&self.const_value),
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user