mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-25 14:12:13 +00:00
Add support for unions in arguments and for optional arguments
This commit is contained in:
parent
f85fd0e2ad
commit
703b1ab91d
@ -7,7 +7,7 @@ use Diagnostic;
|
|||||||
/// An abstract syntax tree representing a rust program. Contains
|
/// An abstract syntax tree representing a rust program. Contains
|
||||||
/// extra information for joining up this rust code with javascript.
|
/// extra information for joining up this rust code with javascript.
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||||
#[derive(Default)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Program {
|
pub struct Program {
|
||||||
/// rust -> js interfaces
|
/// rust -> js interfaces
|
||||||
pub exports: Vec<Export>,
|
pub exports: Vec<Export>,
|
||||||
@ -24,6 +24,7 @@ pub struct Program {
|
|||||||
/// A rust to js interface. Allows interaction with rust objects/functions
|
/// A rust to js interface. Allows interaction with rust objects/functions
|
||||||
/// from javascript.
|
/// from javascript.
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Export {
|
pub struct Export {
|
||||||
/// The javascript class name.
|
/// The javascript class name.
|
||||||
pub class: Option<Ident>,
|
pub class: Option<Ident>,
|
||||||
@ -44,6 +45,7 @@ pub struct Export {
|
|||||||
|
|
||||||
/// The 3 types variations of `self`.
|
/// The 3 types variations of `self`.
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum MethodSelf {
|
pub enum MethodSelf {
|
||||||
/// `self`
|
/// `self`
|
||||||
ByValue,
|
ByValue,
|
||||||
@ -54,6 +56,7 @@ pub enum MethodSelf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Import {
|
pub struct Import {
|
||||||
pub module: Option<String>,
|
pub module: Option<String>,
|
||||||
pub js_namespace: Option<Ident>,
|
pub js_namespace: Option<Ident>,
|
||||||
@ -61,6 +64,7 @@ pub struct Import {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum ImportKind {
|
pub enum ImportKind {
|
||||||
Function(ImportFunction),
|
Function(ImportFunction),
|
||||||
Static(ImportStatic),
|
Static(ImportStatic),
|
||||||
@ -69,6 +73,7 @@ pub enum ImportKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ImportFunction {
|
pub struct ImportFunction {
|
||||||
pub function: Function,
|
pub function: Function,
|
||||||
pub rust_name: Ident,
|
pub rust_name: Ident,
|
||||||
@ -81,6 +86,7 @@ pub struct ImportFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum ImportFunctionKind {
|
pub enum ImportFunctionKind {
|
||||||
Method {
|
Method {
|
||||||
class: String,
|
class: String,
|
||||||
@ -91,18 +97,21 @@ pub enum ImportFunctionKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum MethodKind {
|
pub enum MethodKind {
|
||||||
Constructor,
|
Constructor,
|
||||||
Operation(Operation),
|
Operation(Operation),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Operation {
|
pub struct Operation {
|
||||||
pub is_static: bool,
|
pub is_static: bool,
|
||||||
pub kind: OperationKind,
|
pub kind: OperationKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum OperationKind {
|
pub enum OperationKind {
|
||||||
Regular,
|
Regular,
|
||||||
Getter(Option<Ident>),
|
Getter(Option<Ident>),
|
||||||
@ -113,6 +122,7 @@ pub enum OperationKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ImportStatic {
|
pub struct ImportStatic {
|
||||||
pub vis: syn::Visibility,
|
pub vis: syn::Visibility,
|
||||||
pub ty: syn::Type,
|
pub ty: syn::Type,
|
||||||
@ -122,6 +132,7 @@ pub struct ImportStatic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ImportType {
|
pub struct ImportType {
|
||||||
pub vis: syn::Visibility,
|
pub vis: syn::Visibility,
|
||||||
pub rust_name: Ident,
|
pub rust_name: Ident,
|
||||||
@ -133,6 +144,7 @@ pub struct ImportType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ImportEnum {
|
pub struct ImportEnum {
|
||||||
/// The Rust enum's visibility
|
/// The Rust enum's visibility
|
||||||
pub vis: syn::Visibility,
|
pub vis: syn::Visibility,
|
||||||
@ -147,6 +159,7 @@ pub struct ImportEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub arguments: Vec<syn::ArgCaptured>,
|
pub arguments: Vec<syn::ArgCaptured>,
|
||||||
@ -156,6 +169,7 @@ pub struct Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Struct {
|
pub struct Struct {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub fields: Vec<StructField>,
|
pub fields: Vec<StructField>,
|
||||||
@ -163,6 +177,7 @@ pub struct Struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub struct_name: Ident,
|
pub struct_name: Ident,
|
||||||
@ -174,6 +189,7 @@ pub struct StructField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Enum {
|
pub struct Enum {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub variants: Vec<Variant>,
|
pub variants: Vec<Variant>,
|
||||||
@ -181,6 +197,7 @@ pub struct Enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Variant {
|
pub struct Variant {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub value: u32,
|
pub value: u32,
|
||||||
@ -202,6 +219,7 @@ pub enum TypeLocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Const {
|
pub struct Const {
|
||||||
pub vis: syn::Visibility,
|
pub vis: syn::Visibility,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
@ -211,6 +229,7 @@ pub struct Const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||||
|
#[derive(Clone)]
|
||||||
/// same as webidl::ast::ConstValue
|
/// same as webidl::ast::ConstValue
|
||||||
pub enum ConstValue {
|
pub enum ConstValue {
|
||||||
BooleanLiteral(bool),
|
BooleanLiteral(bool),
|
||||||
|
@ -31,8 +31,7 @@ interface WebGL2RenderingContext
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
interface mixin WebGL2RenderingContextBase
|
||||||
interface WebGL2RenderingContextBase
|
|
||||||
{
|
{
|
||||||
const GLenum READ_BUFFER = 0x0C02;
|
const GLenum READ_BUFFER = 0x0C02;
|
||||||
const GLenum UNPACK_ROW_LENGTH = 0x0CF2;
|
const GLenum UNPACK_ROW_LENGTH = 0x0CF2;
|
||||||
@ -694,8 +693,8 @@ interface WebGL2RenderingContextBase
|
|||||||
void bindVertexArray(WebGLVertexArrayObject? array);
|
void bindVertexArray(WebGLVertexArrayObject? array);
|
||||||
};
|
};
|
||||||
|
|
||||||
WebGL2RenderingContextBase implements WebGLRenderingContextBase;
|
WebGL2RenderingContextBase includes WebGLRenderingContextBase;
|
||||||
WebGL2RenderingContext implements WebGL2RenderingContextBase;
|
WebGL2RenderingContext includes WebGL2RenderingContextBase;
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface EXT_color_buffer_float {
|
interface EXT_color_buffer_float {
|
||||||
|
@ -111,8 +111,7 @@ typedef (Int32Array or sequence<GLint>) Int32List;
|
|||||||
// WebGL2RenderingContext have in common. This doesn't have all the things they
|
// WebGL2RenderingContext have in common. This doesn't have all the things they
|
||||||
// have in common, because we don't support splitting multiple overloads of the
|
// have in common, because we don't support splitting multiple overloads of the
|
||||||
// same method across separate interfaces and pulling them in with "implements".
|
// same method across separate interfaces and pulling them in with "implements".
|
||||||
[Exposed=(Window, Worker), NoInterfaceObject]
|
interface mixin WebGLRenderingContextBase {
|
||||||
interface WebGLRenderingContextBase {
|
|
||||||
/* ClearBufferMask */
|
/* ClearBufferMask */
|
||||||
const GLenum DEPTH_BUFFER_BIT = 0x00000100;
|
const GLenum DEPTH_BUFFER_BIT = 0x00000100;
|
||||||
const GLenum STENCIL_BUFFER_BIT = 0x00000400;
|
const GLenum STENCIL_BUFFER_BIT = 0x00000400;
|
||||||
@ -802,7 +801,7 @@ interface WebGLRenderingContext {
|
|||||||
void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32List data);
|
void uniformMatrix4fv(WebGLUniformLocation? location, GLboolean transpose, Float32List data);
|
||||||
};
|
};
|
||||||
|
|
||||||
WebGLRenderingContext implements WebGLRenderingContextBase;
|
WebGLRenderingContext includes WebGLRenderingContextBase;
|
||||||
|
|
||||||
// For OffscreenCanvas
|
// For OffscreenCanvas
|
||||||
// Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
|
// Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
|
||||||
|
@ -26,8 +26,9 @@ pub(crate) struct FirstPassRecord<'src> {
|
|||||||
pub(crate) dictionaries: BTreeSet<&'src str>,
|
pub(crate) dictionaries: BTreeSet<&'src str>,
|
||||||
pub(crate) enums: BTreeSet<&'src str>,
|
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<&'src str, Vec<&'src MixinMembers<'src>>>,
|
pub(crate) mixins: BTreeMap<&'src str, MixinData<'src>>,
|
||||||
pub(crate) typedefs: BTreeMap<&'src str, &'src weedle::types::Type<'src>>,
|
pub(crate) typedefs: BTreeMap<&'src str, &'src weedle::types::Type<'src>>,
|
||||||
|
pub(crate) includes: BTreeMap<&'src str, BTreeSet<&'src str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
@ -40,7 +41,16 @@ pub(crate) struct InterfaceData<'src> {
|
|||||||
pub(crate) superclass: Option<&'src str>,
|
pub(crate) superclass: Option<&'src str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
/// We need to collect mixin data during the first pass, to be used later.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub(crate) struct MixinData<'src> {
|
||||||
|
/// Whether only partial mixins were encountered
|
||||||
|
pub(crate) partial: bool,
|
||||||
|
pub(crate) members: Vec<&'src MixinMembers<'src>>,
|
||||||
|
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
pub(crate) enum OperationId<'src> {
|
pub(crate) enum OperationId<'src> {
|
||||||
Constructor,
|
Constructor,
|
||||||
Operation(Option<&'src str>),
|
Operation(Option<&'src str>),
|
||||||
@ -79,6 +89,7 @@ impl<'src> FirstPass<'src, ()> for weedle::Definition<'src> {
|
|||||||
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, ()),
|
||||||
|
IncludesStatement(includes) => includes.first_pass(record, ()),
|
||||||
Interface(interface) => interface.first_pass(record, ()),
|
Interface(interface) => interface.first_pass(record, ()),
|
||||||
PartialInterface(interface) => interface.first_pass(record, ()),
|
PartialInterface(interface) => interface.first_pass(record, ()),
|
||||||
InterfaceMixin(mixin) => mixin.first_pass(record, ()),
|
InterfaceMixin(mixin) => mixin.first_pass(record, ()),
|
||||||
@ -111,24 +122,44 @@ impl<'src> FirstPass<'src, ()> for weedle::EnumDefinition<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> FirstPass<'src, ()> for weedle::IncludesStatementDefinition<'src> {
|
||||||
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
|
record
|
||||||
|
.includes
|
||||||
|
.entry(self.lhs_identifier.0)
|
||||||
|
.or_insert_with(Default::default)
|
||||||
|
.insert(self.rhs_identifier.0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn first_pass_operation<'src>(
|
fn first_pass_operation<'src>(
|
||||||
record: &mut FirstPassRecord<'src>,
|
record: &mut FirstPassRecord<'src>,
|
||||||
|
mixin: bool,
|
||||||
self_name: &'src str,
|
self_name: &'src str,
|
||||||
id: OperationId<'src>,
|
id: OperationId<'src>,
|
||||||
arguments: &[Argument<'src>],
|
arguments: &[Argument<'src>],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut names = Vec::with_capacity(arguments.len());
|
let mut names = Vec::with_capacity(arguments.len());
|
||||||
for argument in arguments {
|
for argument in arguments {
|
||||||
match argument {
|
match argument {
|
||||||
Argument::Single(arg) => names.push(arg.identifier.0),
|
Argument::Single(single) => names.push(single.identifier.0),
|
||||||
Argument::Variadic(_) => return Ok(()),
|
Argument::Variadic(variadic) => names.push(variadic.identifier.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
record
|
if mixin {
|
||||||
.interfaces
|
&mut record
|
||||||
.get_mut(self_name)
|
.mixins
|
||||||
.unwrap()
|
.get_mut(self_name)
|
||||||
.operations
|
.unwrap()
|
||||||
|
.operations
|
||||||
|
} else {
|
||||||
|
&mut record
|
||||||
|
.interfaces
|
||||||
|
.get_mut(self_name)
|
||||||
|
.unwrap()
|
||||||
|
.operations
|
||||||
|
}
|
||||||
.entry(id)
|
.entry(id)
|
||||||
.and_modify(|operation_data| operation_data.overloaded = true)
|
.and_modify(|operation_data| operation_data.overloaded = true)
|
||||||
.or_insert_with(Default::default)
|
.or_insert_with(Default::default)
|
||||||
@ -143,12 +174,12 @@ fn first_pass_operation<'src>(
|
|||||||
impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
{
|
{
|
||||||
let interface = record
|
let interface_data = record
|
||||||
.interfaces
|
.interfaces
|
||||||
.entry(self.identifier.0)
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(Default::default);
|
.or_insert_with(Default::default);
|
||||||
interface.partial = false;
|
interface_data.partial = false;
|
||||||
interface.superclass = self.inheritance.map(|s| s.identifier.0);
|
interface_data.superclass = self.inheritance.map(|s| s.identifier.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
@ -177,8 +208,8 @@ impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
|
|||||||
.or_insert_with(||
|
.or_insert_with(||
|
||||||
InterfaceData {
|
InterfaceData {
|
||||||
partial: true,
|
partial: true,
|
||||||
operations: Default::default(),
|
|
||||||
global: false,
|
global: false,
|
||||||
|
operations: Default::default(),
|
||||||
superclass: None,
|
superclass: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -201,6 +232,7 @@ impl<'src> FirstPass<'src, &'src str> for ExtendedAttribute<'src> {
|
|||||||
ExtendedAttribute::ArgList(list) if list.identifier.0 == "Constructor" => {
|
ExtendedAttribute::ArgList(list) if list.identifier.0 == "Constructor" => {
|
||||||
first_pass_operation(
|
first_pass_operation(
|
||||||
record,
|
record,
|
||||||
|
false,
|
||||||
self_name,
|
self_name,
|
||||||
OperationId::Constructor,
|
OperationId::Constructor,
|
||||||
&list.args.body.list,
|
&list.args.body.list,
|
||||||
@ -209,6 +241,7 @@ impl<'src> FirstPass<'src, &'src str> for ExtendedAttribute<'src> {
|
|||||||
ExtendedAttribute::NoArgs(name) if (name.0).0 == "Constructor" => {
|
ExtendedAttribute::NoArgs(name) if (name.0).0 == "Constructor" => {
|
||||||
first_pass_operation(
|
first_pass_operation(
|
||||||
record,
|
record,
|
||||||
|
false,
|
||||||
self_name,
|
self_name,
|
||||||
OperationId::Constructor,
|
OperationId::Constructor,
|
||||||
&[],
|
&[],
|
||||||
@ -219,6 +252,7 @@ impl<'src> FirstPass<'src, &'src str> for ExtendedAttribute<'src> {
|
|||||||
{
|
{
|
||||||
first_pass_operation(
|
first_pass_operation(
|
||||||
record,
|
record,
|
||||||
|
false,
|
||||||
self_name,
|
self_name,
|
||||||
OperationId::Constructor,
|
OperationId::Constructor,
|
||||||
&list.args.body.list,
|
&list.args.body.list,
|
||||||
@ -260,6 +294,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceM
|
|||||||
}
|
}
|
||||||
first_pass_operation(
|
first_pass_operation(
|
||||||
record,
|
record,
|
||||||
|
false,
|
||||||
self_name,
|
self_name,
|
||||||
match self.identifier.map(|s| s.0) {
|
match self.identifier.map(|s| s.0) {
|
||||||
None => match self.specials.get(0) {
|
None => match self.specials.get(0) {
|
||||||
@ -278,11 +313,23 @@ impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceM
|
|||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src>{
|
impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src>{
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
record
|
{
|
||||||
.mixins
|
let mixin_data = record
|
||||||
.entry(self.identifier.0)
|
.mixins
|
||||||
.or_insert_with(Default::default)
|
.entry(self.identifier.0)
|
||||||
.push(&self.members.body);
|
.or_insert_with(Default::default);
|
||||||
|
mixin_data.partial = false;
|
||||||
|
mixin_data.members.push(&self.members.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if util::is_chrome_only(&self.attributes) {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
for member in &self.members.body {
|
||||||
|
member.first_pass(record, self.identifier.0)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,12 +339,55 @@ impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceMixinDefinition<'src>
|
|||||||
record
|
record
|
||||||
.mixins
|
.mixins
|
||||||
.entry(self.identifier.0)
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(Default::default)
|
.or_insert_with(||
|
||||||
|
MixinData {
|
||||||
|
partial: true,
|
||||||
|
members: Default::default(),
|
||||||
|
operations: Default::default(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.members
|
||||||
.push(&self.members.body);
|
.push(&self.members.body);
|
||||||
|
|
||||||
|
if util::is_chrome_only(&self.attributes) {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
for member in &self.members.body {
|
||||||
|
member.first_pass(record, self.identifier.0)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> FirstPass<'src, &'src str> for weedle::mixin::MixinMember<'src> {
|
||||||
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
|
||||||
|
match self {
|
||||||
|
weedle::mixin::MixinMember::Operation(op) => {
|
||||||
|
op.first_pass(record, self_name)
|
||||||
|
}
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> FirstPass<'src, &'src str> for weedle::mixin::OperationMixinMember<'src> {
|
||||||
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, self_name: &'src str) -> Result<()> {
|
||||||
|
if self.stringifier.is_some() {
|
||||||
|
warn!("Unsupported webidl operation {:?}", self);
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
first_pass_operation(
|
||||||
|
record,
|
||||||
|
true,
|
||||||
|
self_name,
|
||||||
|
OperationId::Operation(self.identifier.map(|s| s.0.clone())),
|
||||||
|
&self.args.body.list,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::TypedefDefinition<'src> {
|
impl<'src> FirstPass<'src, ()> for weedle::TypedefDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
|
@ -168,9 +168,6 @@ impl<'src> WebidlParse<'src, ()> for weedle::Definition<'src> {
|
|||||||
weedle::Definition::Enum(enumeration) => {
|
weedle::Definition::Enum(enumeration) => {
|
||||||
enumeration.webidl_parse(program, first_pass, ())?
|
enumeration.webidl_parse(program, first_pass, ())?
|
||||||
}
|
}
|
||||||
weedle::Definition::IncludesStatement(includes) => {
|
|
||||||
includes.webidl_parse(program, first_pass, ())?
|
|
||||||
}
|
|
||||||
weedle::Definition::Interface(interface) => {
|
weedle::Definition::Interface(interface) => {
|
||||||
interface.webidl_parse(program, first_pass, ())?
|
interface.webidl_parse(program, first_pass, ())?
|
||||||
}
|
}
|
||||||
@ -182,6 +179,9 @@ impl<'src> WebidlParse<'src, ()> for weedle::Definition<'src> {
|
|||||||
weedle::Definition::PartialInterfaceMixin(_) => {
|
weedle::Definition::PartialInterfaceMixin(_) => {
|
||||||
// handled in the first pass
|
// handled in the first pass
|
||||||
}
|
}
|
||||||
|
weedle::Definition::IncludesStatement(..) => {
|
||||||
|
// handled in the first pass
|
||||||
|
}
|
||||||
weedle::Definition::Implements(..) => {
|
weedle::Definition::Implements(..) => {
|
||||||
// nothing to do for this, ignore it
|
// nothing to do for this, ignore it
|
||||||
}
|
}
|
||||||
@ -199,25 +199,6 @@ impl<'src> WebidlParse<'src, ()> for weedle::Definition<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> WebidlParse<'src, ()> for weedle::IncludesStatementDefinition<'src> {
|
|
||||||
fn webidl_parse(
|
|
||||||
&'src self,
|
|
||||||
program: &mut backend::ast::Program,
|
|
||||||
first_pass: &FirstPassRecord<'src>,
|
|
||||||
(): (),
|
|
||||||
) -> Result<()> {
|
|
||||||
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> {
|
impl<'src> WebidlParse<'src, ()> for weedle::InterfaceDefinition<'src> {
|
||||||
fn webidl_parse(
|
fn webidl_parse(
|
||||||
&'src self,
|
&'src self,
|
||||||
@ -261,10 +242,33 @@ impl<'src> WebidlParse<'src, ()> for weedle::InterfaceDefinition<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse<'src>(
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
first_pass: &FirstPassRecord<'src>,
|
||||||
|
self_name: &str,
|
||||||
|
mixin_name: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
if let Some(mixin_data) = first_pass.mixins.get(mixin_name) {
|
||||||
|
for members in &mixin_data.members {
|
||||||
|
for member in *members {
|
||||||
|
member.webidl_parse(program, first_pass, self_name)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mixin_names) = first_pass.includes.get(mixin_name) {
|
||||||
|
for mixin_name in mixin_names {
|
||||||
|
parse(program, first_pass, self_name, mixin_name)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
for member in &self.members.body {
|
for member in &self.members.body {
|
||||||
member.webidl_parse(program, first_pass, self.identifier.0)?;
|
member.webidl_parse(program, first_pass, self.identifier.0)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parse(program, first_pass, self.identifier.0, self.identifier.0)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +284,11 @@ impl<'src> WebidlParse<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !first_pass.interfaces.contains_key(self.identifier.0) {
|
if first_pass
|
||||||
|
.interfaces
|
||||||
|
.get(self.identifier.0)
|
||||||
|
.map(|interface_data| !interface_data.partial)
|
||||||
|
.unwrap_or(true) {
|
||||||
warn!(
|
warn!(
|
||||||
"Partial interface {} missing non-partial interface",
|
"Partial interface {} missing non-partial interface",
|
||||||
self.identifier.0
|
self.identifier.0
|
||||||
@ -345,8 +353,11 @@ impl<'src> WebidlParse<'src, &'src weedle::InterfaceDefinition<'src>> for Extend
|
|||||||
throws,
|
throws,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.map(wrap_import_function)
|
.map(|import_functions|
|
||||||
.map(|import| program.imports.push(import));
|
for import_function in import_functions {
|
||||||
|
program.imports.push(wrap_import_function(import_function));
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
@ -436,8 +447,8 @@ impl<'src> WebidlParse<'src, &'src str> for weedle::interface::InterfaceMember<'
|
|||||||
Operation(op) => {
|
Operation(op) => {
|
||||||
op.webidl_parse(program, first_pass, self_name)
|
op.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
Const(cnst) => {
|
Const(const_) => {
|
||||||
cnst.webidl_parse(program, first_pass, self_name)
|
const_.webidl_parse(program, first_pass, self_name)
|
||||||
}
|
}
|
||||||
Iterable(iterable) => {
|
Iterable(iterable) => {
|
||||||
iterable.webidl_parse(program, first_pass, self_name)
|
iterable.webidl_parse(program, first_pass, self_name)
|
||||||
@ -537,7 +548,7 @@ fn member_attribute<'src>(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let statik = match modifier {
|
let is_static = match modifier {
|
||||||
Some(Stringifier(_)) => {
|
Some(Stringifier(_)) => {
|
||||||
warn!("Unsupported stringifier on type {:?}", (self_name, identifier));
|
warn!("Unsupported stringifier on type {:?}", (self_name, identifier));
|
||||||
return Ok(())
|
return Ok(())
|
||||||
@ -560,12 +571,15 @@ fn member_attribute<'src>(
|
|||||||
identifier,
|
identifier,
|
||||||
&type_.type_,
|
&type_.type_,
|
||||||
self_name,
|
self_name,
|
||||||
statik,
|
is_static,
|
||||||
is_structural,
|
is_structural,
|
||||||
throws,
|
throws,
|
||||||
)
|
)
|
||||||
.map(wrap_import_function)
|
.map(|import_functions|
|
||||||
.map(|import| program.imports.push(import));
|
for import_function in import_functions {
|
||||||
|
program.imports.push(wrap_import_function(import_function));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if !readonly {
|
if !readonly {
|
||||||
first_pass
|
first_pass
|
||||||
@ -573,12 +587,15 @@ fn member_attribute<'src>(
|
|||||||
identifier,
|
identifier,
|
||||||
type_.type_.clone(),
|
type_.type_.clone(),
|
||||||
self_name,
|
self_name,
|
||||||
statik,
|
is_static,
|
||||||
is_structural,
|
is_structural,
|
||||||
throws,
|
throws,
|
||||||
)
|
)
|
||||||
.map(wrap_import_function)
|
.map(|import_functions|
|
||||||
.map(|import| program.imports.push(import));
|
for import_function in import_functions {
|
||||||
|
program.imports.push(wrap_import_function(import_function));
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -642,7 +659,7 @@ fn member_operation<'src>(
|
|||||||
if util::is_chrome_only(attrs) {
|
if util::is_chrome_only(attrs) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let statik = match modifier {
|
let is_static = match modifier {
|
||||||
Some(Stringifier(_)) => {
|
Some(Stringifier(_)) => {
|
||||||
warn!("Unsupported stringifier on type {:?}", (self_name, identifier));
|
warn!("Unsupported stringifier on type {:?}", (self_name, identifier));
|
||||||
return Ok(())
|
return Ok(())
|
||||||
@ -670,7 +687,7 @@ fn member_operation<'src>(
|
|||||||
},
|
},
|
||||||
return_type,
|
return_type,
|
||||||
self_name,
|
self_name,
|
||||||
statik,
|
is_static,
|
||||||
specials.len() == 1 || first_pass
|
specials.len() == 1 || first_pass
|
||||||
.interfaces
|
.interfaces
|
||||||
.get(self_name)
|
.get(self_name)
|
||||||
@ -678,8 +695,11 @@ fn member_operation<'src>(
|
|||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
util::throws(attrs),
|
util::throws(attrs),
|
||||||
)
|
)
|
||||||
.map(wrap_import_function)
|
.map(|import_functions|
|
||||||
.map(|import| program.imports.push(import));
|
for import_function in import_functions {
|
||||||
|
program.imports.push(wrap_import_function(import_function));
|
||||||
|
}
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use backend;
|
use backend;
|
||||||
use backend::util::{ident_ty, leading_colon_path_ty, raw_ident, rust_ident};
|
use backend::util::{ident_ty, leading_colon_path_ty, raw_ident, rust_ident};
|
||||||
@ -315,64 +316,75 @@ impl<'src> ToSynType<'src> for weedle::term::Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> ToSynType<'src> for weedle::types::Type<'src> {
|
impl<'src> ToSynType<'src> for NonAnyType<'src> {
|
||||||
fn to_syn_type(&self, record: &FirstPassRecord<'src>, pos: TypePosition)
|
fn to_syn_type(&self, record: &FirstPassRecord<'src>, pos: TypePosition)
|
||||||
-> Option<syn::Type>
|
-> Option<syn::Type>
|
||||||
{
|
{
|
||||||
use weedle::types::NonAnyType::*;
|
match self {
|
||||||
let single = match self {
|
NonAnyType::Boolean(s) => s.to_syn_type(record, pos),
|
||||||
Type::Single(s) => s,
|
NonAnyType::Octet(s) => s.to_syn_type(record, pos),
|
||||||
Type::Union(_) => return None,
|
NonAnyType::Byte(s) => s.to_syn_type(record, pos),
|
||||||
};
|
NonAnyType::Identifier(s) => s.to_syn_type(record, pos),
|
||||||
|
NonAnyType::Integer(s) => s.to_syn_type(record, pos),
|
||||||
|
NonAnyType::FloatingPoint(s) => s.to_syn_type(record, pos),
|
||||||
|
|
||||||
let ty = match single {
|
NonAnyType::Float32Array(s) => s.to_syn_type(record, pos),
|
||||||
// `any` becomes `::wasm_bindgen::JsValue`.
|
NonAnyType::Float64Array(s) => s.to_syn_type(record, pos),
|
||||||
SingleType::Any(_) => {
|
NonAnyType::Int8Array(s) => s.to_syn_type(record, pos),
|
||||||
let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")];
|
NonAnyType::Int16Array(s) => s.to_syn_type(record, pos),
|
||||||
return Some(leading_colon_path_ty(path))
|
NonAnyType::Int32Array(s) => s.to_syn_type(record, pos),
|
||||||
}
|
NonAnyType::Uint8Array(s) => s.to_syn_type(record, pos),
|
||||||
SingleType::NonAny(other) => other,
|
NonAnyType::Uint8ClampedArray(s) => s.to_syn_type(record, pos),
|
||||||
};
|
NonAnyType::Uint16Array(s) => s.to_syn_type(record, pos),
|
||||||
|
NonAnyType::Uint32Array(s) => s.to_syn_type(record, pos),
|
||||||
|
|
||||||
match ty {
|
NonAnyType::DOMString(s) => s.to_syn_type(record, pos),
|
||||||
Boolean(s) => s.to_syn_type(record, pos),
|
NonAnyType::ByteString(s) => s.to_syn_type(record, pos),
|
||||||
Octet(s) => s.to_syn_type(record, pos),
|
NonAnyType::USVString(s) => s.to_syn_type(record, pos),
|
||||||
Byte(s) => s.to_syn_type(record, pos),
|
NonAnyType::ArrayBuffer(b) => b.to_syn_type(record, pos),
|
||||||
Identifier(s) => s.to_syn_type(record, pos),
|
NonAnyType::Object(o) => o.to_syn_type(record, pos),
|
||||||
Integer(s) => s.to_syn_type(record, pos),
|
|
||||||
FloatingPoint(s) => s.to_syn_type(record, pos),
|
|
||||||
|
|
||||||
Float32Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Float64Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Int8Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Int16Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Int32Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Uint8Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Uint8ClampedArray(s) => s.to_syn_type(record, pos),
|
|
||||||
Uint16Array(s) => s.to_syn_type(record, pos),
|
|
||||||
Uint32Array(s) => s.to_syn_type(record, pos),
|
|
||||||
|
|
||||||
DOMString(s) => s.to_syn_type(record, pos),
|
|
||||||
ByteString(s) => s.to_syn_type(record, pos),
|
|
||||||
USVString(s) => s.to_syn_type(record, pos),
|
|
||||||
ArrayBuffer(b) => b.to_syn_type(record, pos),
|
|
||||||
Object(o) => o.to_syn_type(record, pos),
|
|
||||||
|
|
||||||
// Support for these types is not yet implemented, so skip
|
// Support for these types is not yet implemented, so skip
|
||||||
// generating any bindings for this function.
|
// generating any bindings for this function.
|
||||||
| DataView(_)
|
| NonAnyType::DataView(_)
|
||||||
| Error(_)
|
| NonAnyType::Error(_)
|
||||||
| FrozenArrayType(_)
|
| NonAnyType::FrozenArrayType(_)
|
||||||
| Promise(_)
|
| NonAnyType::Promise(_)
|
||||||
| RecordType(..)
|
| NonAnyType::RecordType(..)
|
||||||
| Sequence(_)
|
| NonAnyType::Sequence(_)
|
||||||
| Symbol(_) => {
|
| NonAnyType::Symbol(_) => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> ToSynType<'src> for SingleType<'src> {
|
||||||
|
fn to_syn_type(&self, record: &FirstPassRecord<'src>, pos: TypePosition)
|
||||||
|
-> Option<syn::Type>
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
// `any` becomes `::wasm_bindgen::JsValue`.
|
||||||
|
SingleType::Any(_) => {
|
||||||
|
let path = vec![rust_ident("wasm_bindgen"), rust_ident("JsValue")];
|
||||||
|
Some(leading_colon_path_ty(path))
|
||||||
|
}
|
||||||
|
SingleType::NonAny(non_any) => non_any.to_syn_type(record, pos),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> ToSynType<'src> for Type<'src> {
|
||||||
|
fn to_syn_type(&self, record: &FirstPassRecord<'src>, pos: TypePosition)
|
||||||
|
-> Option<syn::Type>
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Type::Single(single) => single.to_syn_type(record, pos),
|
||||||
|
Type::Union(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Map a webidl const value to the correct wasm-bindgen const value
|
/// Map a webidl const value to the correct wasm-bindgen const value
|
||||||
pub fn webidl_const_v_to_backend_const_v(v: &ConstValue) -> backend::ast::ConstValue {
|
pub fn webidl_const_v_to_backend_const_v(v: &ConstValue) -> backend::ast::ConstValue {
|
||||||
@ -519,31 +531,153 @@ pub enum TypePosition {
|
|||||||
Return,
|
Return,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implemented on an AST type node to generate a snake case name.
|
trait GetArgumentPossibilities<'src> {
|
||||||
trait TypeToString {
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>>;
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: TypeToString> TypeToString for MayBeNull<T> {
|
impl<'src, T: GetArgumentPossibilities<'src>> GetArgumentPossibilities<'src> for MayBeNull<T> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
if self.q_mark.is_some() {
|
Some(
|
||||||
dst.push_str("opt_");
|
self
|
||||||
}
|
.type_
|
||||||
self.type_.type_to_string(record, dst);
|
.get_argument_possibilities(record)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|(ty, type_name)|
|
||||||
|
if self.q_mark.is_some() {
|
||||||
|
(option_ty(ty), "opt_".to_string() + &type_name)
|
||||||
|
} else {
|
||||||
|
(ty, type_name)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> TypeToString for weedle::types::ReturnType<'src> {
|
impl<'src> GetArgumentPossibilities<'src> for weedle::common::Identifier<'src> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
|
if let Some(other) = record.typedefs.get(&self.0) {
|
||||||
|
other.get_argument_possibilities(record)
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
self.to_syn_type(record, TypePosition::Argument)?,
|
||||||
|
self.get_type_name(record),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> GetArgumentPossibilities<'src> for NonAnyType<'src> {
|
||||||
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
|
if let NonAnyType::Identifier(identifier) = self {
|
||||||
|
identifier.get_argument_possibilities(record)
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
self.to_syn_type(record, TypePosition::Argument)?,
|
||||||
|
self.get_type_name(record),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> GetArgumentPossibilities<'src> for SingleType<'src> {
|
||||||
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
|
if let SingleType::NonAny(non_any) = self {
|
||||||
|
non_any.get_argument_possibilities(record)
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
vec![
|
||||||
|
(
|
||||||
|
self.to_syn_type(record, TypePosition::Argument)?,
|
||||||
|
self.get_type_name(record),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> GetArgumentPossibilities<'src> for UnionMemberType<'src> {
|
||||||
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
match self {
|
match self {
|
||||||
weedle::types::ReturnType::Type(ty) => (*ty).type_to_string(record, dst),
|
UnionMemberType::Single(single) => single.get_argument_possibilities(record),
|
||||||
|
UnionMemberType::Union(union) => union.get_argument_possibilities(record),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> GetArgumentPossibilities<'src> for UnionType<'src> {
|
||||||
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
|
let mut result = Vec::new();
|
||||||
|
for ty in &self.body.list {
|
||||||
|
result.extend(ty.get_argument_possibilities(record)?.into_iter());
|
||||||
|
}
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> GetArgumentPossibilities<'src> for Type<'src> {
|
||||||
|
fn get_argument_possibilities(&self, record: &FirstPassRecord<'src>) -> Option<Vec<(syn::Type, String)>> {
|
||||||
|
match self {
|
||||||
|
Type::Single(single) => single.get_argument_possibilities(record),
|
||||||
|
Type::Union(union) => union.get_argument_possibilities(record),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implemented on an AST type node to generate a snake case name.
|
||||||
|
trait GetTypeName {
|
||||||
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String);
|
||||||
|
|
||||||
|
fn get_type_name(&self, record: &FirstPassRecord) -> String {
|
||||||
|
let mut string = String::new();
|
||||||
|
self.push_type_name(record, &mut string);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GetTypeName> GetTypeName for [T] {
|
||||||
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
|
let mut first = true;
|
||||||
|
for union_member_type in self {
|
||||||
|
if first {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
dst.push_str("_and_");
|
||||||
|
}
|
||||||
|
union_member_type.push_type_name(record, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: GetTypeName> GetTypeName for MayBeNull<T> {
|
||||||
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
|
if self.q_mark.is_some() {
|
||||||
|
dst.push_str("opt_");
|
||||||
|
}
|
||||||
|
self.type_.push_type_name(record, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> GetTypeName for weedle::types::ReturnType<'src> {
|
||||||
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
|
match self {
|
||||||
|
weedle::types::ReturnType::Type(ty) => (*ty).push_type_name(record, dst),
|
||||||
weedle::types::ReturnType::Void(_) => dst.push_str("void"),
|
weedle::types::ReturnType::Void(_) => dst.push_str("void"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::types::StringType {
|
impl GetTypeName for weedle::types::StringType {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
match self {
|
match self {
|
||||||
weedle::types::StringType::Byte(_) => dst.push_str("byte_str"),
|
weedle::types::StringType::Byte(_) => dst.push_str("byte_str"),
|
||||||
weedle::types::StringType::DOM(_) => dst.push_str("dom_str"),
|
weedle::types::StringType::DOM(_) => dst.push_str("dom_str"),
|
||||||
@ -552,107 +686,107 @@ impl TypeToString for weedle::types::StringType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Byte {
|
impl GetTypeName for weedle::term::Byte {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("i8");
|
dst.push_str("i8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Octet {
|
impl GetTypeName for weedle::term::Octet {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("u8");
|
dst.push_str("u8");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Boolean {
|
impl GetTypeName for weedle::term::Boolean {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("bool");
|
dst.push_str("bool");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::USVString {
|
impl GetTypeName for weedle::term::USVString {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("usv_str");
|
dst.push_str("usv_str");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::ByteString {
|
impl GetTypeName for weedle::term::ByteString {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("byte_str");
|
dst.push_str("byte_str");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::DOMString {
|
impl GetTypeName for weedle::term::DOMString {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("dom_str");
|
dst.push_str("dom_str");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Float32Array {
|
impl GetTypeName for weedle::term::Float32Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("f32_array");
|
dst.push_str("f32_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Float64Array {
|
impl GetTypeName for weedle::term::Float64Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("f64_array");
|
dst.push_str("f64_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Int8Array {
|
impl GetTypeName for weedle::term::Int8Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("i8_array");
|
dst.push_str("i8_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Int16Array {
|
impl GetTypeName for weedle::term::Int16Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("i16_array");
|
dst.push_str("i16_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Int32Array {
|
impl GetTypeName for weedle::term::Int32Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("i32_array");
|
dst.push_str("i32_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Uint8Array {
|
impl GetTypeName for weedle::term::Uint8Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("u8_array");
|
dst.push_str("u8_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Uint8ClampedArray {
|
impl GetTypeName for weedle::term::Uint8ClampedArray {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("u8_clamped_array");
|
dst.push_str("u8_clamped_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Uint16Array {
|
impl GetTypeName for weedle::term::Uint16Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("u16_array");
|
dst.push_str("u16_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Uint32Array {
|
impl GetTypeName for weedle::term::Uint32Array {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("u32_array");
|
dst.push_str("u32_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> TypeToString for weedle::common::Identifier<'src> {
|
impl<'src> GetTypeName for weedle::common::Identifier<'src> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
match record.typedefs.get(self.0) {
|
match record.typedefs.get(self.0) {
|
||||||
Some(other) => other.type_to_string(record, dst),
|
Some(other) => other.push_type_name(record, dst),
|
||||||
None => dst.push_str(&self.0.to_snake_case()),
|
None => dst.push_str(&self.0.to_snake_case()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for IntegerType {
|
impl GetTypeName for IntegerType {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
match self {
|
match self {
|
||||||
IntegerType::LongLong(l) if l.unsigned.is_some() => dst.push_str("u64"),
|
IntegerType::LongLong(l) if l.unsigned.is_some() => dst.push_str("u64"),
|
||||||
IntegerType::LongLong(_) => dst.push_str("i64"),
|
IntegerType::LongLong(_) => dst.push_str("i64"),
|
||||||
@ -664,8 +798,8 @@ impl TypeToString for IntegerType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for FloatingPointType {
|
impl GetTypeName for FloatingPointType {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
match self {
|
match self {
|
||||||
FloatingPointType::Float(_) => dst.push_str("f32"),
|
FloatingPointType::Float(_) => dst.push_str("f32"),
|
||||||
FloatingPointType::Double(_) => dst.push_str("f64"),
|
FloatingPointType::Double(_) => dst.push_str("f64"),
|
||||||
@ -673,111 +807,133 @@ impl TypeToString for FloatingPointType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::ArrayBuffer {
|
impl GetTypeName for weedle::term::ArrayBuffer {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("array_buffer");
|
dst.push_str("array_buffer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Symbol {
|
impl GetTypeName for weedle::term::Symbol {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("symbol");
|
dst.push_str("symbol");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Object {
|
impl GetTypeName for weedle::term::Object {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("object");
|
dst.push_str("object");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::DataView {
|
impl GetTypeName for weedle::term::DataView {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("data_view");
|
dst.push_str("data_view");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeToString for weedle::term::Error {
|
impl GetTypeName for weedle::term::Error {
|
||||||
fn type_to_string(&self, _record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, _record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("error");
|
dst.push_str("error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> TypeToString for weedle::types::SequenceType<'src> {
|
impl<'src> GetTypeName for SequenceType<'src> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("seq_");
|
self.generics.body.push_type_name(record, dst);
|
||||||
self.generics.body.type_to_string(record, dst);
|
dst.push_str("_seq");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> TypeToString for weedle::types::PromiseType<'src> {
|
impl<'src> GetTypeName for PromiseType<'src> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("promise_");
|
self.generics.body.push_type_name(record, dst);
|
||||||
self.generics.body.type_to_string(record, dst);
|
dst.push_str("_promise");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> TypeToString for weedle::types::FrozenArrayType<'src> {
|
impl<'src> GetTypeName for FrozenArrayType<'src> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("frozen_array_");
|
self.generics.body.push_type_name(record, dst);
|
||||||
self.generics.body.type_to_string(record, dst);
|
dst.push_str("_frozen_array");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> TypeToString for weedle::types::RecordType<'src> {
|
impl<'src> GetTypeName for RecordType<'src> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
dst.push_str("record_from_");
|
dst.push_str("record_from_");
|
||||||
self.generics.body.0.type_to_string(record, dst);
|
self.generics.body.0.push_type_name(record, dst);
|
||||||
dst.push_str("_to_");
|
dst.push_str("_to_");
|
||||||
self.generics.body.2.type_to_string(record, dst);
|
self.generics.body.2.push_type_name(record, dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TypeToString for weedle::types::Type<'a> {
|
impl<'a> GetTypeName for NonAnyType<'a> {
|
||||||
fn type_to_string(&self, record: &FirstPassRecord, dst: &mut String) {
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
use weedle::types::NonAnyType::*;
|
match self {
|
||||||
|
NonAnyType::Boolean(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Octet(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Byte(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Identifier(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Integer(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::FloatingPoint(s) => s.push_type_name(record, dst),
|
||||||
|
|
||||||
let single = match self {
|
NonAnyType::Float32Array(s) => s.push_type_name(record, dst),
|
||||||
Type::Single(s) => s,
|
NonAnyType::Float64Array(s) => s.push_type_name(record, dst),
|
||||||
Type::Union(_) => panic!("unions not supported"),
|
NonAnyType::Int8Array(s) => s.push_type_name(record, dst),
|
||||||
};
|
NonAnyType::Int16Array(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Int32Array(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Uint8Array(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Uint8ClampedArray(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Uint16Array(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Uint32Array(s) => s.push_type_name(record, dst),
|
||||||
|
|
||||||
let ty = match single {
|
NonAnyType::DOMString(s) => s.push_type_name(record, dst),
|
||||||
SingleType::Any(_) => return dst.push_str("any"),
|
NonAnyType::ByteString(s) => s.push_type_name(record, dst),
|
||||||
SingleType::NonAny(other) => other,
|
NonAnyType::USVString(s) => s.push_type_name(record, dst),
|
||||||
};
|
NonAnyType::ArrayBuffer(s) => s.push_type_name(record, dst),
|
||||||
|
|
||||||
match ty {
|
NonAnyType::DataView(s) => s.push_type_name(record, dst),
|
||||||
Boolean(s) => s.type_to_string(record, dst),
|
NonAnyType::Error(s) => s.push_type_name(record, dst),
|
||||||
Octet(s) => s.type_to_string(record, dst),
|
NonAnyType::FrozenArrayType(s) => s.push_type_name(record, dst),
|
||||||
Byte(s) => s.type_to_string(record, dst),
|
NonAnyType::Object(s) => s.push_type_name(record, dst),
|
||||||
Identifier(s) => s.type_to_string(record, dst),
|
NonAnyType::Promise(s) => s.push_type_name(record, dst),
|
||||||
Integer(s) => s.type_to_string(record, dst),
|
NonAnyType::RecordType(s) => s.push_type_name(record, dst),
|
||||||
FloatingPoint(s) => s.type_to_string(record, dst),
|
NonAnyType::Sequence(s) => s.push_type_name(record, dst),
|
||||||
|
NonAnyType::Symbol(s) => s.push_type_name(record, dst),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Float32Array(s) => s.type_to_string(record, dst),
|
impl<'a> GetTypeName for SingleType<'a> {
|
||||||
Float64Array(s) => s.type_to_string(record, dst),
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
Int8Array(s) => s.type_to_string(record, dst),
|
match self {
|
||||||
Int16Array(s) => s.type_to_string(record, dst),
|
SingleType::Any(_) => dst.push_str("any"),
|
||||||
Int32Array(s) => s.type_to_string(record, dst),
|
SingleType::NonAny(non_any) => non_any.push_type_name(record, dst),
|
||||||
Uint8Array(s) => s.type_to_string(record, dst),
|
}
|
||||||
Uint8ClampedArray(s) => s.type_to_string(record, dst),
|
}
|
||||||
Uint16Array(s) => s.type_to_string(record, dst),
|
}
|
||||||
Uint32Array(s) => s.type_to_string(record, dst),
|
|
||||||
|
|
||||||
DOMString(s) => s.type_to_string(record, dst),
|
impl<'a> GetTypeName for UnionMemberType<'a> {
|
||||||
ByteString(s) => s.type_to_string(record, dst),
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
USVString(s) => s.type_to_string(record, dst),
|
match self {
|
||||||
ArrayBuffer(s) => s.type_to_string(record, dst),
|
UnionMemberType::Single(single) => single.push_type_name(record, dst),
|
||||||
|
UnionMemberType::Union(union) => union.push_type_name(record, dst),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DataView(s) => s.type_to_string(record, dst),
|
impl<'a> GetTypeName for UnionType<'a> {
|
||||||
Error(s) => s.type_to_string(record, dst),
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
FrozenArrayType(s) => s.type_to_string(record, dst),
|
dst.push_str("union_of_");
|
||||||
Object(s) => s.type_to_string(record, dst),
|
self.body.list.push_type_name(record, dst);
|
||||||
Promise(s) => s.type_to_string(record, dst),
|
}
|
||||||
RecordType(s) => s.type_to_string(record, dst),
|
}
|
||||||
Sequence(s) => s.type_to_string(record, dst),
|
|
||||||
Symbol(s) => s.type_to_string(record, dst),
|
impl<'a> GetTypeName for Type<'a> {
|
||||||
|
fn push_type_name(&self, record: &FirstPassRecord, dst: &mut String) {
|
||||||
|
match self {
|
||||||
|
Type::Single(single) => single.push_type_name(record, dst),
|
||||||
|
Type::Union(union) => union.push_type_name(record, dst),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -787,46 +943,110 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
///
|
///
|
||||||
/// `kind` is whether the function is a method, in which case we would need a `self`
|
/// `kind` is whether the function is a method, in which case we would need a `self`
|
||||||
/// parameter.
|
/// parameter.
|
||||||
fn webidl_arguments_to_syn_arg_captured(
|
///
|
||||||
|
/// Return option that contains a value if the conversion succeeds.
|
||||||
|
/// The value is a vector of argument variants.
|
||||||
|
/// Each variant is a vector of converted argument types and type names.
|
||||||
|
fn get_variants(
|
||||||
&self,
|
&self,
|
||||||
arguments: &[Argument],
|
arguments: &[Argument],
|
||||||
kind: &backend::ast::ImportFunctionKind,
|
kind: &backend::ast::ImportFunctionKind,
|
||||||
) -> Option<Vec<syn::ArgCaptured>>
|
) -> Option<Vec<Vec<(syn::ArgCaptured, Option<String>)>>>
|
||||||
{
|
{
|
||||||
let mut res = if let backend::ast::ImportFunctionKind::Method {
|
let arguments_possibilities = {
|
||||||
ty,
|
fn get_argument_possibilities(record: &FirstPassRecord, argument: &Argument) -> Option<Vec<(syn::Type, String)>> {
|
||||||
kind:
|
let single = match argument {
|
||||||
backend::ast::MethodKind::Operation(backend::ast::Operation {
|
Argument::Single(single) => single,
|
||||||
is_static: false, ..
|
Argument::Variadic(_) => return None,
|
||||||
}),
|
};
|
||||||
..
|
match single.type_.type_.get_argument_possibilities(record) {
|
||||||
} = kind
|
None => {
|
||||||
{
|
warn!("Argument's type is not yet supported: {:?}", argument);
|
||||||
let mut res = Vec::with_capacity(arguments.len() + 1);
|
None
|
||||||
res.push(simple_fn_arg(raw_ident("self_"), shared_ref(ty.clone())));
|
},
|
||||||
res
|
Some(value) => Some(value),
|
||||||
} else {
|
|
||||||
Vec::with_capacity(arguments.len())
|
|
||||||
};
|
|
||||||
|
|
||||||
for argument in arguments {
|
|
||||||
let argument = match argument {
|
|
||||||
Argument::Single(arg) => arg,
|
|
||||||
Argument::Variadic(_) => return None,
|
|
||||||
};
|
|
||||||
match argument.type_.type_.to_syn_type(self, TypePosition::Argument) {
|
|
||||||
None => {
|
|
||||||
warn!("Argument's type is not yet supported: {:?}", argument);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(ty) => {
|
|
||||||
let name = argument.identifier.0.to_snake_case();
|
|
||||||
res.push(simple_fn_arg(rust_ident(&name), ty))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
let mut optional_arguments_possibilities = Vec::new();
|
||||||
|
if let Argument::Single(ref single) = arguments[0] {
|
||||||
|
if single.optional.is_some() {
|
||||||
|
optional_arguments_possibilities.push(Vec::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut arguments_possibilities: Vec<_> = get_argument_possibilities(
|
||||||
|
self,
|
||||||
|
&arguments[0]
|
||||||
|
)?
|
||||||
|
.into_iter()
|
||||||
|
.map(|argument_possibility| vec![argument_possibility])
|
||||||
|
.collect();
|
||||||
|
for argument in arguments[1..].iter() {
|
||||||
|
let mut new_arguments_possibilities = Vec::new();
|
||||||
|
for arguments_possibility in arguments_possibilities {
|
||||||
|
if let Argument::Single(single) = argument {
|
||||||
|
if single.optional.is_some() {
|
||||||
|
optional_arguments_possibilities.push(arguments_possibility.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut element_argument_possibilities = get_argument_possibilities(
|
||||||
|
self,
|
||||||
|
&argument
|
||||||
|
)?;
|
||||||
|
for element_argument_possibility in element_argument_possibilities {
|
||||||
|
new_arguments_possibilities.push(
|
||||||
|
arguments_possibility
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain(iter::once(element_argument_possibility))
|
||||||
|
.collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arguments_possibilities = new_arguments_possibilities
|
||||||
|
}
|
||||||
|
optional_arguments_possibilities.extend(arguments_possibilities.into_iter());
|
||||||
|
optional_arguments_possibilities
|
||||||
|
} else {
|
||||||
|
vec![Vec::new()]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut result = Vec::new();
|
||||||
|
for arguments_possibility in arguments_possibilities {
|
||||||
|
let mut res = if let backend::ast::ImportFunctionKind::Method {
|
||||||
|
ty,
|
||||||
|
kind: backend::ast::MethodKind::Operation(
|
||||||
|
backend::ast::Operation {
|
||||||
|
is_static: false, ..
|
||||||
|
}
|
||||||
|
),
|
||||||
|
..
|
||||||
|
} = kind {
|
||||||
|
let mut res = Vec::with_capacity(arguments.len() + 1);
|
||||||
|
res.push((simple_fn_arg(raw_ident("self_"), shared_ref(ty.clone())), None));
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
Vec::with_capacity(arguments.len())
|
||||||
|
};
|
||||||
|
for (argument, argument_possibility) in arguments.iter().zip(arguments_possibility) {
|
||||||
|
let single = match argument {
|
||||||
|
Argument::Single(single) => single,
|
||||||
|
Argument::Variadic(_) => return None,
|
||||||
|
};
|
||||||
|
res.push(
|
||||||
|
(
|
||||||
|
simple_fn_arg(
|
||||||
|
rust_ident(&single.identifier.0.to_snake_case()),
|
||||||
|
argument_possibility.0.clone()
|
||||||
|
),
|
||||||
|
Some(argument_possibility.1.clone()),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
result.push(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(res)
|
Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a wasm-bindgen function, if possible.
|
/// Create a wasm-bindgen function, if possible.
|
||||||
@ -841,37 +1061,32 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
structural: bool,
|
structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
doc_comment: Option<String>,
|
doc_comment: Option<String>,
|
||||||
) -> Option<backend::ast::ImportFunction>
|
) -> Option<Vec<backend::ast::ImportFunction>>
|
||||||
{
|
{
|
||||||
let ast_arguments = self.webidl_arguments_to_syn_arg_captured(arguments, &kind)?;
|
let rust_name = if overloaded && !arguments.is_empty() {
|
||||||
|
let mut argument_type_names = String::new();
|
||||||
let rust_name = rust_ident(
|
for arg in arguments {
|
||||||
&if overloaded && !arguments.is_empty() {
|
let arg = match arg {
|
||||||
let mut argument_type_names = String::new();
|
Argument::Single(single) => single,
|
||||||
for arg in arguments {
|
Argument::Variadic(_) => return None,
|
||||||
let arg = match arg {
|
};
|
||||||
Argument::Single(single) => single,
|
if argument_type_names.len() > 0 {
|
||||||
Argument::Variadic(_) => return None,
|
argument_type_names.push_str("_and_");
|
||||||
};
|
|
||||||
if argument_type_names.len() > 0 {
|
|
||||||
argument_type_names.push_str("_and_");
|
|
||||||
}
|
|
||||||
if same_argument_names {
|
|
||||||
arg.type_.type_.type_to_string(self, &mut argument_type_names);
|
|
||||||
} else {
|
|
||||||
argument_type_names.push_str(&arg.identifier.0.to_snake_case());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if name == "new" {
|
if same_argument_names {
|
||||||
"with_".to_owned() + &argument_type_names
|
arg.type_.type_.push_type_name(self, &mut argument_type_names);
|
||||||
} else {
|
} else {
|
||||||
name.to_snake_case() + "_with_" + &argument_type_names
|
argument_type_names.push_str(&arg.identifier.0.to_snake_case());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
name.to_snake_case()
|
|
||||||
}
|
}
|
||||||
);
|
if name == "new" {
|
||||||
let name = name.to_string();
|
"with_".to_owned() + &argument_type_names
|
||||||
|
} else {
|
||||||
|
name.to_snake_case() + "_with_" + &argument_type_names
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
name.to_snake_case()
|
||||||
|
};
|
||||||
|
|
||||||
let js_ret = ret.clone();
|
let js_ret = ret.clone();
|
||||||
|
|
||||||
@ -879,31 +1094,57 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
ret = Some(ret.map_or_else(|| result_ty(unit_ty()), result_ty))
|
ret = Some(ret.map_or_else(|| result_ty(unit_ty()), result_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
let shim = {
|
let variants = self.get_variants(arguments, &kind)?;
|
||||||
let ns = match kind {
|
let multiple_variants = variants.len() > 1;
|
||||||
backend::ast::ImportFunctionKind::Normal => "",
|
let mut result = Vec::new();
|
||||||
backend::ast::ImportFunctionKind::Method { ref class, .. } => class,
|
for variant in variants {
|
||||||
|
let (variant_types, variant_names): (Vec<_>, Vec<_>) = variant.into_iter().unzip();
|
||||||
|
let rust_name = if multiple_variants {
|
||||||
|
let mut rust_name = rust_name.clone();
|
||||||
|
let mut first = true;
|
||||||
|
for variant_name in variant_names {
|
||||||
|
if let Some(type_name) = variant_name {
|
||||||
|
if first {
|
||||||
|
rust_name.push_str("_using_");
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
rust_name.push_str("_and_");
|
||||||
|
}
|
||||||
|
rust_name.push_str(&type_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rust_name
|
||||||
|
} else {
|
||||||
|
rust_name.clone()
|
||||||
|
};
|
||||||
|
let rust_name = rust_ident(&rust_name);
|
||||||
|
let shim = {
|
||||||
|
let ns = match kind {
|
||||||
|
backend::ast::ImportFunctionKind::Normal => "",
|
||||||
|
backend::ast::ImportFunctionKind::Method { ref class, .. } => class,
|
||||||
|
};
|
||||||
|
|
||||||
|
raw_ident(&format!("__widl_f_{}_{}", rust_name, ns))
|
||||||
};
|
};
|
||||||
|
|
||||||
raw_ident(&format!("__widl_f_{}_{}", rust_name, ns))
|
result.push(backend::ast::ImportFunction {
|
||||||
};
|
function: backend::ast::Function {
|
||||||
|
name: name.to_string(),
|
||||||
Some(backend::ast::ImportFunction {
|
arguments: variant_types,
|
||||||
function: backend::ast::Function {
|
ret: ret.clone(),
|
||||||
name,
|
rust_attrs: vec![],
|
||||||
arguments: ast_arguments,
|
rust_vis: public(),
|
||||||
ret,
|
},
|
||||||
rust_attrs: vec![],
|
rust_name,
|
||||||
rust_vis: public(),
|
js_ret: js_ret.clone(),
|
||||||
},
|
catch,
|
||||||
rust_name,
|
structural,
|
||||||
js_ret,
|
kind: kind.clone(),
|
||||||
catch,
|
shim,
|
||||||
structural,
|
doc_comment: doc_comment.clone(),
|
||||||
kind,
|
})
|
||||||
shim,
|
}
|
||||||
doc_comment,
|
Some(result)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a wasm-bindgen method, if possible.
|
/// Create a wasm-bindgen method, if possible.
|
||||||
@ -916,7 +1157,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
structural: bool,
|
structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
) -> Option<backend::ast::ImportFunction> {
|
) -> Option<Vec<backend::ast::ImportFunction>> {
|
||||||
let (overloaded, same_argument_names) = self.get_operation_overloading(
|
let (overloaded, same_argument_names) = self.get_operation_overloading(
|
||||||
arguments,
|
arguments,
|
||||||
&operation_id,
|
&operation_id,
|
||||||
@ -999,14 +1240,36 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
id: &::first_pass::OperationId,
|
id: &::first_pass::OperationId,
|
||||||
self_name: &str,
|
self_name: &str,
|
||||||
) -> (bool, bool) {
|
) -> (bool, bool) {
|
||||||
let data = match self.interfaces.get(self_name) {
|
fn get_operation_data<'src>(
|
||||||
Some(data) => data,
|
record: &'src FirstPassRecord,
|
||||||
None => return (false, false),
|
id: &'src ::first_pass::OperationId,
|
||||||
};
|
self_name: &str,
|
||||||
let data = match data.operations.get(id) {
|
mixin_name: &str,
|
||||||
Some(data) => data,
|
) -> Option<&'src ::first_pass::OperationData<'src>> {
|
||||||
None => return (false, false),
|
if let Some(mixin_data) = record.mixins.get(mixin_name) {
|
||||||
};
|
if let Some(operation_data) = mixin_data.operations.get(id) {
|
||||||
|
return Some(operation_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(mixin_names) = record.includes.get(mixin_name) {
|
||||||
|
for mixin_name in mixin_names {
|
||||||
|
if let Some(operation_data) = get_operation_data(record, id, self_name, mixin_name) {
|
||||||
|
return Some(operation_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
let operation_data = self
|
||||||
|
.interfaces
|
||||||
|
.get(self_name)
|
||||||
|
.and_then(|interface_data| interface_data.operations.get(id))
|
||||||
|
.unwrap_or_else(||
|
||||||
|
get_operation_data(self, id, self_name, self_name)
|
||||||
|
.expect(&format!("not found operation {:?} in interface {}", id, self_name))
|
||||||
|
);
|
||||||
|
|
||||||
let mut names = Vec::with_capacity(arguments.len());
|
let mut names = Vec::with_capacity(arguments.len());
|
||||||
for arg in arguments {
|
for arg in arguments {
|
||||||
match arg {
|
match arg {
|
||||||
@ -1015,8 +1278,8 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
data.overloaded,
|
operation_data.overloaded,
|
||||||
*data
|
*operation_data
|
||||||
.argument_names_same
|
.argument_names_same
|
||||||
.get(&names)
|
.get(&names)
|
||||||
.unwrap_or(&false)
|
.unwrap_or(&false)
|
||||||
@ -1032,7 +1295,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
is_structural: bool,
|
is_structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
) -> Option<backend::ast::ImportFunction> {
|
) -> Option<Vec<backend::ast::ImportFunction>> {
|
||||||
let ret = match ty.to_syn_type(self, TypePosition::Return) {
|
let ret = match ty.to_syn_type(self, TypePosition::Return) {
|
||||||
None => {
|
None => {
|
||||||
warn!("Attribute's type does not yet support reading: {:?}", ty);
|
warn!("Attribute's type does not yet support reading: {:?}", ty);
|
||||||
@ -1063,7 +1326,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
is_structural: bool,
|
is_structural: bool,
|
||||||
catch: bool,
|
catch: bool,
|
||||||
) -> Option<backend::ast::ImportFunction> {
|
) -> Option<Vec<backend::ast::ImportFunction>> {
|
||||||
let kind = backend::ast::ImportFunctionKind::Method {
|
let kind = backend::ast::ImportFunctionKind::Method {
|
||||||
class: self_name.to_string(),
|
class: self_name.to_string(),
|
||||||
ty: ident_ty(rust_ident(camel_case_ident(&self_name).as_str())),
|
ty: ident_ty(rust_ident(camel_case_ident(&self_name).as_str())),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user