Merge pull request #214 from fitzgen/webidl

Add a WebIDL frontend
This commit is contained in:
Nick Fitzgerald 2018-05-30 11:52:16 -07:00 committed by GitHub
commit 4a54e6fd52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 235 additions and 1 deletions

View File

@ -37,6 +37,7 @@ wasm-bindgen-cli-support = { path = "crates/cli-support", version = '=0.2.11' }
[workspace]
members = [
"crates/cli",
"crates/webidl",
"examples/hello_world",
"examples/smorgasboard",
"examples/console_log",

18
crates/webidl/Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "wasm-bindgen-webidl"
version = "0.1.0"
authors = ["Nick Fitzgerald <fitzgen@gmail.com>"]
[[test]]
name = "webidl-all"
path = "tests/all/lib.rs"
[dev-dependencies]
wasm-bindgen-backend = { version = "=0.2.11", path = "../backend", features = ["extra-traits"] }
[dependencies]
failure = "0.1"
proc-macro2 = "0.4"
syn = { version = '0.14', features = ['full'] }
wasm-bindgen-backend = { version = "=0.2.11", path = "../backend" }
webidl = "0.6.0"

102
crates/webidl/src/lib.rs Executable file
View File

@ -0,0 +1,102 @@
/*!
# `wasm_bindgen_webidl`
Converts WebIDL into wasm-bindgen's internal AST form, so that bindings can be
emitted for the types and methods described in the WebIDL.
*/
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
extern crate failure;
extern crate proc_macro2;
extern crate syn;
extern crate wasm_bindgen_backend as backend;
extern crate webidl;
use failure::ResultExt;
use proc_macro2::Ident;
use std::fs;
use std::io::{self, Read};
use std::path::Path;
/// Either `Ok(t)` or `Err(failure::Error)`.
pub type Result<T> = ::std::result::Result<T, failure::Error>;
/// Parse the WebIDL at the given path into a wasm-bindgen AST.
pub fn parse_file(webidl_path: &Path) -> Result<backend::ast::Program> {
let file = fs::File::open(webidl_path).context("opening WebIDL file")?;
let mut file = io::BufReader::new(file);
let mut source = String::new();
file.read_to_string(&mut source)
.context("reading WebIDL file")?;
parse(&source)
}
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
pub fn parse(webidl_source: &str) -> Result<backend::ast::Program> {
let definitions = webidl::parse_string(webidl_source).context("parsing WebIDL source text")?;
let mut program = backend::ast::Program::default();
definitions.webidl_parse(&mut program)?;
Ok(program)
}
trait WebidlParse {
fn webidl_parse(&self, program: &mut backend::ast::Program) -> Result<()>;
}
impl WebidlParse for Vec<webidl::ast::Definition> {
fn webidl_parse(&self, program: &mut backend::ast::Program) -> Result<()> {
for def in self {
def.webidl_parse(program)?;
}
Ok(())
}
}
impl WebidlParse for webidl::ast::Definition {
fn webidl_parse(&self, program: &mut backend::ast::Program) -> Result<()> {
match *self {
webidl::ast::Definition::Interface(ref interface) => interface.webidl_parse(program),
// TODO
webidl::ast::Definition::Callback(..)
| webidl::ast::Definition::Dictionary(..)
| webidl::ast::Definition::Enum(..)
| webidl::ast::Definition::Implements(..)
| webidl::ast::Definition::Includes(..)
| webidl::ast::Definition::Mixin(..)
| webidl::ast::Definition::Namespace(..)
| webidl::ast::Definition::Typedef(..) => Ok(()),
}
}
}
impl WebidlParse for webidl::ast::Interface {
fn webidl_parse(&self, program: &mut backend::ast::Program) -> Result<()> {
match *self {
webidl::ast::Interface::NonPartial(ref interface) => interface.webidl_parse(program),
// TODO
webidl::ast::Interface::Callback(..) | webidl::ast::Interface::Partial(..) => Ok(()),
}
}
}
impl WebidlParse for webidl::ast::NonPartialInterface {
fn webidl_parse(&self, program: &mut backend::ast::Program) -> Result<()> {
program.imports.push(backend::ast::Import {
module: None,
version: None,
js_namespace: None,
kind: backend::ast::ImportKind::Type(backend::ast::ImportType {
vis: syn::Visibility::Public(syn::VisPublic {
pub_token: syn::token::Pub(proc_macro2::Span::call_site()),
}),
name: Ident::new(&self.name, proc_macro2::Span::call_site()),
}),
});
println!("{:#?}", self);
Ok(())
}
}

View File

@ -0,0 +1,59 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* http://www.w3.org/TR/2012/WD-dom-20120105/
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
[Constructor(DOMString type, optional EventInit eventInitDict),
Exposed=(Window,Worker,System), ProbablyShortLivingWrapper]
interface Event {
[Pure]
readonly attribute DOMString type;
[Pure]
readonly attribute EventTarget? target;
[Pure]
readonly attribute EventTarget? currentTarget;
sequence<EventTarget> composedPath();
const unsigned short NONE = 0;
const unsigned short CAPTURING_PHASE = 1;
const unsigned short AT_TARGET = 2;
const unsigned short BUBBLING_PHASE = 3;
[Pure]
readonly attribute unsigned short eventPhase;
void stopPropagation();
void stopImmediatePropagation();
[Pure]
readonly attribute boolean bubbles;
[Pure]
readonly attribute boolean cancelable;
[NeedsCallerType]
void preventDefault();
[Pure, NeedsCallerType]
readonly attribute boolean defaultPrevented;
[ChromeOnly, Pure]
readonly attribute boolean defaultPreventedByChrome;
[ChromeOnly, Pure]
readonly attribute boolean defaultPreventedByContent;
[Pure]
readonly attribute boolean composed;
[Unforgeable, Pure]
readonly attribute boolean isTrusted;
[Pure]
readonly attribute DOMHighResTimeStamp timeStamp;
void initEvent(DOMString type,
optional boolean bubbles = false,
optional boolean cancelable = false);
attribute boolean cancelBubble;
};

View File

@ -0,0 +1,24 @@
use super::backend;
use proc_macro2;
use syn;
assert_parse!(
event,
include_str!("./Event.webidl"),
backend::ast::Program {
exports: vec![],
imports: vec![backend::ast::Import {
module: None,
version: None,
js_namespace: None,
kind: backend::ast::ImportKind::Type(backend::ast::ImportType {
vis: syn::Visibility::Public(syn::VisPublic {
pub_token: syn::token::Pub(proc_macro2::Span::call_site()),
}),
name: syn::Ident::new("Event", proc_macro2::Span::call_site()),
}),
}],
enums: vec![],
structs: vec![],
}
);

View File

@ -0,0 +1,21 @@
extern crate proc_macro2;
extern crate syn;
extern crate wasm_bindgen_backend as backend;
extern crate wasm_bindgen_webidl as wb_webidl;
pub fn assert_parse(webidl: &str, expected: backend::ast::Program) {
let actual = wb_webidl::parse(webidl).expect("should parse the webidl source OK");
assert_eq!(expected, actual);
}
macro_rules! assert_parse {
($test_name:ident, $webidl_source:expr, $expected_ast:expr) => {
#[test]
fn $test_name() {
$crate::assert_parse($webidl_source, $expected_ast);
}
};
}
mod event;
mod simple;

View File

@ -0,0 +1,3 @@
use super::backend;
assert_parse!(empty, "", backend::ast::Program::default());

View File

@ -382,4 +382,5 @@ mod slice;
mod structural;
mod non_wasm;
mod u64;
mod char;
mod char;
mod webidl;

1
tests/all/webidl/mod.rs Normal file
View File

@ -0,0 +1 @@
mod simple;

View File

@ -0,0 +1,4 @@
#[test]
fn webidl() {
assert!(true);
}