mirror of
https://github.com/rustwasm/wasm-bindgen.git
synced 2024-12-27 12:06:14 +03:00
Implement WebIDL callback interfaces
This commit implements callback interfaces for WebIDL, the final WebIDL construct that we were unconditionally ignoring! Callback interfaces are implemented as dictionaries of callbacks. Single-operation callback interfaces are also expanded when flattening to accept a `Function` as well, in accordance with the WebIDL spec. New features have been added to `web-sys` for all the new callback interface types. Additionally the `EventTarget.webidl` was tweaked to not have `EventListener?` as this is required for all functional usage and there's no need to keep that sort of web browser compat here. Closes #258
This commit is contained in:
parent
2cf82bc0b3
commit
8181f7fa95
@ -38,7 +38,10 @@ wasm-bindgen-futures = { path = '../futures', version = '0.2.21' }
|
|||||||
AbortController = []
|
AbortController = []
|
||||||
AbortSignal = []
|
AbortSignal = []
|
||||||
AddEventListenerOptions = []
|
AddEventListenerOptions = []
|
||||||
|
AesCbcParams = []
|
||||||
|
AesCtrParams = []
|
||||||
AesDerivedKeyParams = []
|
AesDerivedKeyParams = []
|
||||||
|
AesGcmParams = []
|
||||||
AesKeyAlgorithm = []
|
AesKeyAlgorithm = []
|
||||||
AesKeyGenParams = []
|
AesKeyGenParams = []
|
||||||
Algorithm = []
|
Algorithm = []
|
||||||
@ -289,10 +292,12 @@ Element = []
|
|||||||
ElementCreationOptions = []
|
ElementCreationOptions = []
|
||||||
ElementDefinitionOptions = []
|
ElementDefinitionOptions = []
|
||||||
EndingTypes = []
|
EndingTypes = []
|
||||||
|
ErrorCallback = []
|
||||||
ErrorEvent = []
|
ErrorEvent = []
|
||||||
ErrorEventInit = []
|
ErrorEventInit = []
|
||||||
Event = []
|
Event = []
|
||||||
EventInit = []
|
EventInit = []
|
||||||
|
EventListener = []
|
||||||
EventListenerOptions = []
|
EventListenerOptions = []
|
||||||
EventModifierInit = []
|
EventModifierInit = []
|
||||||
EventSource = []
|
EventSource = []
|
||||||
@ -310,6 +315,7 @@ FetchReadableStreamReadDataArray = []
|
|||||||
FetchReadableStreamReadDataDone = []
|
FetchReadableStreamReadDataDone = []
|
||||||
FetchState = []
|
FetchState = []
|
||||||
File = []
|
File = []
|
||||||
|
FileCallback = []
|
||||||
FileList = []
|
FileList = []
|
||||||
FilePropertyBag = []
|
FilePropertyBag = []
|
||||||
FileReader = []
|
FileReader = []
|
||||||
@ -317,7 +323,9 @@ FileReaderSync = []
|
|||||||
FileSystem = []
|
FileSystem = []
|
||||||
FileSystemDirectoryEntry = []
|
FileSystemDirectoryEntry = []
|
||||||
FileSystemDirectoryReader = []
|
FileSystemDirectoryReader = []
|
||||||
|
FileSystemEntriesCallback = []
|
||||||
FileSystemEntry = []
|
FileSystemEntry = []
|
||||||
|
FileSystemEntryCallback = []
|
||||||
FileSystemFileEntry = []
|
FileSystemFileEntry = []
|
||||||
FileSystemFlags = []
|
FileSystemFlags = []
|
||||||
FillMode = []
|
FillMode = []
|
||||||
@ -602,6 +610,7 @@ NetworkCommandOptions = []
|
|||||||
NetworkInformation = []
|
NetworkInformation = []
|
||||||
NetworkResultOptions = []
|
NetworkResultOptions = []
|
||||||
Node = []
|
Node = []
|
||||||
|
NodeFilter = []
|
||||||
NodeIterator = []
|
NodeIterator = []
|
||||||
NodeList = []
|
NodeList = []
|
||||||
Notification = []
|
Notification = []
|
||||||
@ -611,6 +620,7 @@ NotificationEvent = []
|
|||||||
NotificationEventInit = []
|
NotificationEventInit = []
|
||||||
NotificationOptions = []
|
NotificationOptions = []
|
||||||
NotificationPermission = []
|
NotificationPermission = []
|
||||||
|
ObserverCallback = []
|
||||||
OfflineAudioCompletionEvent = []
|
OfflineAudioCompletionEvent = []
|
||||||
OfflineAudioCompletionEventInit = []
|
OfflineAudioCompletionEventInit = []
|
||||||
OfflineAudioContext = []
|
OfflineAudioContext = []
|
||||||
@ -702,10 +712,13 @@ ProgressEventInit = []
|
|||||||
PromiseRejectionEvent = []
|
PromiseRejectionEvent = []
|
||||||
PromiseRejectionEventInit = []
|
PromiseRejectionEventInit = []
|
||||||
PublicKeyCredential = []
|
PublicKeyCredential = []
|
||||||
|
PublicKeyCredentialDescriptor = []
|
||||||
PublicKeyCredentialEntity = []
|
PublicKeyCredentialEntity = []
|
||||||
PublicKeyCredentialParameters = []
|
PublicKeyCredentialParameters = []
|
||||||
|
PublicKeyCredentialRequestOptions = []
|
||||||
PublicKeyCredentialRpEntity = []
|
PublicKeyCredentialRpEntity = []
|
||||||
PublicKeyCredentialType = []
|
PublicKeyCredentialType = []
|
||||||
|
PublicKeyCredentialUserEntity = []
|
||||||
PushEncryptionKeyName = []
|
PushEncryptionKeyName = []
|
||||||
PushEvent = []
|
PushEvent = []
|
||||||
PushEventInit = []
|
PushEventInit = []
|
||||||
@ -768,6 +781,7 @@ RtcIceServer = []
|
|||||||
RtcIceTransportPolicy = []
|
RtcIceTransportPolicy = []
|
||||||
RtcIdentityAssertion = []
|
RtcIdentityAssertion = []
|
||||||
RtcIdentityAssertionResult = []
|
RtcIdentityAssertionResult = []
|
||||||
|
RtcIdentityProvider = []
|
||||||
RtcIdentityProviderDetails = []
|
RtcIdentityProviderDetails = []
|
||||||
RtcIdentityProviderOptions = []
|
RtcIdentityProviderOptions = []
|
||||||
RtcIdentityValidationResult = []
|
RtcIdentityValidationResult = []
|
||||||
@ -1038,6 +1052,7 @@ VideoPlaybackQuality = []
|
|||||||
VideoStreamTrack = []
|
VideoStreamTrack = []
|
||||||
VideoTrack = []
|
VideoTrack = []
|
||||||
VideoTrackList = []
|
VideoTrackList = []
|
||||||
|
VoidCallback = []
|
||||||
VrDisplay = []
|
VrDisplay = []
|
||||||
VrDisplayCapabilities = []
|
VrDisplayCapabilities = []
|
||||||
VrEye = []
|
VrEye = []
|
||||||
@ -1170,6 +1185,7 @@ WorkerOptions = []
|
|||||||
Worklet = []
|
Worklet = []
|
||||||
WorkletGlobalScope = []
|
WorkletGlobalScope = []
|
||||||
XPathExpression = []
|
XPathExpression = []
|
||||||
|
XPathNsResolver = []
|
||||||
XPathResult = []
|
XPathResult = []
|
||||||
XmlDocument = []
|
XmlDocument = []
|
||||||
XmlHttpRequest = []
|
XmlHttpRequest = []
|
||||||
|
@ -29,12 +29,12 @@ interface EventTarget {
|
|||||||
false. */
|
false. */
|
||||||
[Throws]
|
[Throws]
|
||||||
void addEventListener(DOMString type,
|
void addEventListener(DOMString type,
|
||||||
EventListener? listener,
|
EventListener listener,
|
||||||
optional (AddEventListenerOptions or boolean) options,
|
optional (AddEventListenerOptions or boolean) options,
|
||||||
optional boolean? wantsUntrusted = null);
|
optional boolean? wantsUntrusted = null);
|
||||||
[Throws]
|
[Throws]
|
||||||
void removeEventListener(DOMString type,
|
void removeEventListener(DOMString type,
|
||||||
EventListener? listener,
|
EventListener listener,
|
||||||
optional (EventListenerOptions or boolean) options);
|
optional (EventListenerOptions or boolean) options);
|
||||||
[Throws, NeedsCallerType]
|
[Throws, NeedsCallerType]
|
||||||
boolean dispatchEvent(Event event);
|
boolean dispatchEvent(Event event);
|
||||||
|
4
crates/webidl-tests/callbacks.js
Normal file
4
crates/webidl-tests/callbacks.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
global.TakeCallbackInterface = class {
|
||||||
|
a() {}
|
||||||
|
b() {}
|
||||||
|
};
|
38
crates/webidl-tests/callbacks.rs
Normal file
38
crates/webidl-tests/callbacks.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use wasm_bindgen_test::*;
|
||||||
|
use js_sys::Function;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/callbacks.rs"));
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn multi_op_same_name() {
|
||||||
|
let a = CallbackInterface2::new();
|
||||||
|
let b = TakeCallbackInterface::new().unwrap();
|
||||||
|
b.b(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn single_op_function() {
|
||||||
|
let a = Function::new_no_args("");
|
||||||
|
let b = TakeCallbackInterface::new().unwrap();
|
||||||
|
b.a_with_callback(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn single_op_dict() {
|
||||||
|
let a = CallbackInterface1::new();
|
||||||
|
let b = TakeCallbackInterface::new().unwrap();
|
||||||
|
b.a_with_callback_interface1(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn dict_methods() {
|
||||||
|
let mut a = CallbackInterface1::new();
|
||||||
|
a.foo(&Function::new_no_args(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn dict_methods1() {
|
||||||
|
let mut a = CallbackInterface2::new();
|
||||||
|
a.foo(&Function::new_no_args(""));
|
||||||
|
a.bar(&Function::new_no_args(""));
|
||||||
|
}
|
14
crates/webidl-tests/callbacks.webidl
vendored
Normal file
14
crates/webidl-tests/callbacks.webidl
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
callback interface CallbackInterface1 {
|
||||||
|
void foo();
|
||||||
|
};
|
||||||
|
|
||||||
|
callback interface CallbackInterface2 {
|
||||||
|
void foo();
|
||||||
|
void bar();
|
||||||
|
};
|
||||||
|
|
||||||
|
[Constructor()]
|
||||||
|
interface TakeCallbackInterface {
|
||||||
|
void a(CallbackInterface1 arg);
|
||||||
|
void b(CallbackInterface2 arg);
|
||||||
|
};
|
@ -11,3 +11,4 @@ pub mod simple;
|
|||||||
pub mod throws;
|
pub mod throws;
|
||||||
pub mod dictionary;
|
pub mod dictionary;
|
||||||
pub mod global;
|
pub mod global;
|
||||||
|
pub mod callbacks;
|
||||||
|
@ -12,6 +12,7 @@ use std::collections::{BTreeMap, BTreeSet};
|
|||||||
|
|
||||||
use proc_macro2::Ident;
|
use proc_macro2::Ident;
|
||||||
use weedle::{DictionaryDefinition, PartialDictionaryDefinition};
|
use weedle::{DictionaryDefinition, PartialDictionaryDefinition};
|
||||||
|
use weedle::CallbackInterfaceDefinition;
|
||||||
use weedle::argument::Argument;
|
use weedle::argument::Argument;
|
||||||
use weedle::attribute::*;
|
use weedle::attribute::*;
|
||||||
use weedle::interface::*;
|
use weedle::interface::*;
|
||||||
@ -35,6 +36,7 @@ pub(crate) struct FirstPassRecord<'src> {
|
|||||||
pub(crate) includes: BTreeMap<&'src str, BTreeSet<&'src str>>,
|
pub(crate) includes: BTreeMap<&'src str, BTreeSet<&'src str>>,
|
||||||
pub(crate) dictionaries: BTreeMap<&'src str, DictionaryData<'src>>,
|
pub(crate) dictionaries: BTreeMap<&'src str, DictionaryData<'src>>,
|
||||||
pub(crate) callbacks: BTreeSet<&'src str>,
|
pub(crate) callbacks: BTreeSet<&'src str>,
|
||||||
|
pub(crate) callback_interfaces: BTreeMap<&'src str, CallbackInterfaceData<'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.
|
||||||
@ -64,17 +66,20 @@ pub(crate) struct MixinData<'src> {
|
|||||||
/// We need to collect namespace data during the first pass, to be used later.
|
/// We need to collect namespace data during the first pass, to be used later.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct NamespaceData<'src> {
|
pub(crate) struct NamespaceData<'src> {
|
||||||
/// Whether only partial namespaces were encountered
|
|
||||||
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct DictionaryData<'src> {
|
pub(crate) struct DictionaryData<'src> {
|
||||||
/// Whether only partial namespaces were encountered
|
|
||||||
pub(crate) partials: Vec<&'src PartialDictionaryDefinition<'src>>,
|
pub(crate) partials: Vec<&'src PartialDictionaryDefinition<'src>>,
|
||||||
pub(crate) definition: Option<&'src DictionaryDefinition<'src>>,
|
pub(crate) definition: Option<&'src DictionaryDefinition<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct CallbackInterfaceData<'src> {
|
||||||
|
pub(crate) definition: &'src CallbackInterfaceDefinition<'src>,
|
||||||
|
pub(crate) single_function: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
||||||
pub(crate) enum OperationId<'src> {
|
pub(crate) enum OperationId<'src> {
|
||||||
Constructor(IgnoreTraits<&'src str>),
|
Constructor(IgnoreTraits<&'src str>),
|
||||||
@ -137,12 +142,8 @@ impl<'src> FirstPass<'src, ()> for weedle::Definition<'src> {
|
|||||||
PartialNamespace(namespace) => namespace.first_pass(record, ()),
|
PartialNamespace(namespace) => namespace.first_pass(record, ()),
|
||||||
Typedef(typedef) => typedef.first_pass(record, ()),
|
Typedef(typedef) => typedef.first_pass(record, ()),
|
||||||
Callback(callback) => callback.first_pass(record, ()),
|
Callback(callback) => callback.first_pass(record, ()),
|
||||||
|
CallbackInterface(iface) => iface.first_pass(record, ()),
|
||||||
Implements(_) => Ok(()),
|
Implements(_) => Ok(()),
|
||||||
CallbackInterface(..) => {
|
|
||||||
warn!("Unsupported WebIDL CallbackInterface definition: {:?}", self);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -690,6 +691,25 @@ impl<'src> FirstPass<'src, ()> for weedle::CallbackDefinition<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> FirstPass<'src, ()> for weedle::CallbackInterfaceDefinition<'src> {
|
||||||
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, _: ()) -> Result<()> {
|
||||||
|
if util::is_chrome_only(&self.attributes) {
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
if self.inheritance.is_some() {
|
||||||
|
warn!("skipping callback interface with inheritance: {}",
|
||||||
|
self.identifier.0);
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
let data = CallbackInterfaceData {
|
||||||
|
definition: self,
|
||||||
|
single_function: self.members.body.len() == 1,
|
||||||
|
};
|
||||||
|
record.callback_interfaces.insert(self.identifier.0, data);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> FirstPassRecord<'a> {
|
impl<'a> FirstPassRecord<'a> {
|
||||||
pub fn all_superclasses<'me>(&'me self, interface: &str)
|
pub fn all_superclasses<'me>(&'me self, interface: &str)
|
||||||
-> impl Iterator<Item = String> + 'me
|
-> impl Iterator<Item = String> + 'me
|
||||||
|
@ -48,6 +48,7 @@ pub(crate) enum IdlType<'a> {
|
|||||||
Interface(&'a str),
|
Interface(&'a str),
|
||||||
Dictionary(&'a str),
|
Dictionary(&'a str),
|
||||||
Enum(&'a str),
|
Enum(&'a str),
|
||||||
|
CallbackInterface { name: &'a str, single_function: bool },
|
||||||
|
|
||||||
Nullable(Box<IdlType<'a>>),
|
Nullable(Box<IdlType<'a>>),
|
||||||
FrozenArray(Box<IdlType<'a>>),
|
FrozenArray(Box<IdlType<'a>>),
|
||||||
@ -296,6 +297,11 @@ impl<'a> ToIdlType<'a> for Identifier<'a> {
|
|||||||
Some(IdlType::Enum(self.0))
|
Some(IdlType::Enum(self.0))
|
||||||
} else if record.callbacks.contains(self.0) {
|
} else if record.callbacks.contains(self.0) {
|
||||||
Some(IdlType::Callback)
|
Some(IdlType::Callback)
|
||||||
|
} else if let Some(data) = record.callback_interfaces.get(self.0) {
|
||||||
|
Some(IdlType::CallbackInterface {
|
||||||
|
name: self.0,
|
||||||
|
single_function: data.single_function,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
warn!("Unrecognized type: {}", self.0);
|
warn!("Unrecognized type: {}", self.0);
|
||||||
None
|
None
|
||||||
@ -387,6 +393,9 @@ impl<'a> IdlType<'a> {
|
|||||||
IdlType::Interface(name) => dst.push_str(&snake_case_ident(name)),
|
IdlType::Interface(name) => dst.push_str(&snake_case_ident(name)),
|
||||||
IdlType::Dictionary(name) => dst.push_str(&snake_case_ident(name)),
|
IdlType::Dictionary(name) => dst.push_str(&snake_case_ident(name)),
|
||||||
IdlType::Enum(name) => dst.push_str(&snake_case_ident(name)),
|
IdlType::Enum(name) => dst.push_str(&snake_case_ident(name)),
|
||||||
|
IdlType::CallbackInterface { name, .. } => {
|
||||||
|
dst.push_str(&snake_case_ident(name))
|
||||||
|
}
|
||||||
|
|
||||||
IdlType::Nullable(idl_type) => {
|
IdlType::Nullable(idl_type) => {
|
||||||
dst.push_str("opt_");
|
dst.push_str("opt_");
|
||||||
@ -480,7 +489,8 @@ impl<'a> IdlType<'a> {
|
|||||||
|
|
||||||
IdlType::ArrayBufferView | IdlType::BufferSource => js_sys("Object"),
|
IdlType::ArrayBufferView | IdlType::BufferSource => js_sys("Object"),
|
||||||
IdlType::Interface(name)
|
IdlType::Interface(name)
|
||||||
| IdlType::Dictionary(name) => {
|
| IdlType::Dictionary(name)
|
||||||
|
| IdlType::CallbackInterface { name, .. } => {
|
||||||
let ty = ident_ty(rust_ident(camel_case_ident(name).as_str()));
|
let ty = ident_ty(rust_ident(camel_case_ident(name).as_str()));
|
||||||
if pos == TypePosition::Argument {
|
if pos == TypePosition::Argument {
|
||||||
Some(shared_ref(ty, false))
|
Some(shared_ref(ty, false))
|
||||||
@ -588,6 +598,17 @@ impl<'a> IdlType<'a> {
|
|||||||
IdlType::UnsignedLongLong => {
|
IdlType::UnsignedLongLong => {
|
||||||
vec![IdlType::UnsignedLong, IdlType::Double]
|
vec![IdlType::UnsignedLong, IdlType::Double]
|
||||||
}
|
}
|
||||||
|
IdlType::CallbackInterface { name, single_function: true } => {
|
||||||
|
// According to the webidl spec [1] single-function callback
|
||||||
|
// interfaces can also be replaced in arguments with simply a
|
||||||
|
// single callable function, which we map to a `Callback`.
|
||||||
|
//
|
||||||
|
// [1]: https://heycam.github.io/webidl/#es-user-objects
|
||||||
|
vec![
|
||||||
|
IdlType::Callback,
|
||||||
|
IdlType::CallbackInterface { name, single_function: false },
|
||||||
|
]
|
||||||
|
}
|
||||||
idl_type @ _ => vec![idl_type.clone()],
|
idl_type @ _ => vec![idl_type.clone()],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,10 @@ use backend::util::{ident_ty, rust_ident, raw_ident, wrap_import_function};
|
|||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use weedle::attribute::{ExtendedAttributeList};
|
use weedle::attribute::{ExtendedAttributeList};
|
||||||
use weedle::dictionary::DictionaryMember;
|
use weedle::dictionary::DictionaryMember;
|
||||||
|
use weedle::interface::InterfaceMember;
|
||||||
|
|
||||||
use first_pass::{FirstPass, FirstPassRecord, OperationId, InterfaceData};
|
use first_pass::{FirstPass, FirstPassRecord, OperationId, InterfaceData};
|
||||||
use first_pass::OperationData;
|
use first_pass::{OperationData, CallbackInterfaceData};
|
||||||
use util::{public, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, shouty_snake_case_ident, snake_case_ident, mdn_doc};
|
use util::{public, webidl_const_v_to_backend_const_v, TypePosition, camel_case_ident, shouty_snake_case_ident, snake_case_ident, mdn_doc};
|
||||||
use idl_type::ToIdlType;
|
use idl_type::ToIdlType;
|
||||||
|
|
||||||
@ -108,6 +109,11 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>)
|
|||||||
first_pass_record.append_interface(&mut program, name, d);
|
first_pass_record.append_interface(&mut program, name, d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (name, d) in first_pass_record.callback_interfaces.iter() {
|
||||||
|
if filter(name) {
|
||||||
|
first_pass_record.append_callback_interface(&mut program, d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prune out `extends` annotations that aren't defined as these shouldn't
|
// Prune out `extends` annotations that aren't defined as these shouldn't
|
||||||
// prevent the type from being usable entirely. They're just there for
|
// prevent the type from being usable entirely. They're just there for
|
||||||
@ -644,4 +650,38 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
list,
|
list,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn append_callback_interface(
|
||||||
|
&self,
|
||||||
|
program: &mut backend::ast::Program,
|
||||||
|
item: &CallbackInterfaceData<'src>,
|
||||||
|
) {
|
||||||
|
let mut fields = Vec::new();
|
||||||
|
for member in item.definition.members.body.iter() {
|
||||||
|
match member {
|
||||||
|
InterfaceMember::Operation(op) => {
|
||||||
|
let identifier = match op.identifier {
|
||||||
|
Some(i) => i.0,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
let pos = TypePosition::Argument;
|
||||||
|
fields.push(ast::DictionaryField {
|
||||||
|
required: false,
|
||||||
|
name: rust_ident(&snake_case_ident(identifier)),
|
||||||
|
ty: idl_type::IdlType::Callback.to_syn_type(pos)
|
||||||
|
.unwrap(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
warn!("skipping callback interface member on {}",
|
||||||
|
item.definition.identifier.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
program.dictionaries.push(ast::Dictionary {
|
||||||
|
name: rust_ident(&camel_case_ident(item.definition.identifier.0)),
|
||||||
|
fields,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user