diff --git a/crates/web-sys/src/lib.rs b/crates/web-sys/src/lib.rs index 3f019181..c09c36e3 100755 --- a/crates/web-sys/src/lib.rs +++ b/crates/web-sys/src/lib.rs @@ -12,6 +12,7 @@ //! require. #![doc(html_root_url = "https://docs.rs/web-sys/0.2")] +#![allow(deprecated)] extern crate js_sys; extern crate wasm_bindgen; diff --git a/crates/web-sys/webidls/enabled/AudioBufferSourceNode.webidl b/crates/web-sys/webidls/enabled/AudioBufferSourceNode.webidl index 729550c5..cc98e587 100644 --- a/crates/web-sys/webidls/enabled/AudioBufferSourceNode.webidl +++ b/crates/web-sys/webidls/enabled/AudioBufferSourceNode.webidl @@ -32,7 +32,12 @@ interface AudioBufferSourceNode : AudioScheduledSourceNode { attribute double loopStart; attribute double loopEnd; + attribute EventHandler onended; + [Throws] void start(optional double when = 0, optional double grainOffset = 0, optional double grainDuration); + + [Throws] + void stop (optional double when = 0); }; diff --git a/crates/web-sys/webidls/enabled/AudioContext.webidl b/crates/web-sys/webidls/enabled/AudioContext.webidl index d115b968..ca5187ee 100644 --- a/crates/web-sys/webidls/enabled/AudioContext.webidl +++ b/crates/web-sys/webidls/enabled/AudioContext.webidl @@ -37,3 +37,5 @@ interface AudioContext : BaseAudioContext { [NewObject, Throws] MediaStreamAudioDestinationNode createMediaStreamDestination(); }; + +AudioContext includes rustBaseAudioContext; diff --git a/crates/web-sys/webidls/enabled/AudioScheduledSourceNode.webidl b/crates/web-sys/webidls/enabled/AudioScheduledSourceNode.webidl index 2acf6373..39f4d2c8 100644 --- a/crates/web-sys/webidls/enabled/AudioScheduledSourceNode.webidl +++ b/crates/web-sys/webidls/enabled/AudioScheduledSourceNode.webidl @@ -10,7 +10,13 @@ * liability, trademark and document use rules apply. */ +[RustDeprecated="doesn't exist in Safari, use parent class methods instead"] interface AudioScheduledSourceNode : AudioNode { +}; + +AudioScheduledSourceNode includes rustAudioScheduledSourceNode; + +interface mixin rustAudioScheduledSourceNode { attribute EventHandler onended; [Throws] void start (optional double when = 0); diff --git a/crates/web-sys/webidls/enabled/BaseAudioContext.webidl b/crates/web-sys/webidls/enabled/BaseAudioContext.webidl index e8796bb9..1634cdd3 100644 --- a/crates/web-sys/webidls/enabled/BaseAudioContext.webidl +++ b/crates/web-sys/webidls/enabled/BaseAudioContext.webidl @@ -19,7 +19,13 @@ enum AudioContextState { "closed" }; +[RustDeprecated="doesn't exist in Safari, use `AudioContext` instead now"] interface BaseAudioContext : EventTarget { +}; + +BaseAudioContext includes rustBaseAudioContext; + +interface mixin rustBaseAudioContext { readonly attribute AudioDestinationNode destination; readonly attribute float sampleRate; readonly attribute double currentTime; diff --git a/crates/web-sys/webidls/enabled/ConstantSourceNode.webidl b/crates/web-sys/webidls/enabled/ConstantSourceNode.webidl index cd005897..238e4c05 100644 --- a/crates/web-sys/webidls/enabled/ConstantSourceNode.webidl +++ b/crates/web-sys/webidls/enabled/ConstantSourceNode.webidl @@ -19,3 +19,5 @@ dictionary ConstantSourceOptions { interface ConstantSourceNode : AudioScheduledSourceNode { readonly attribute AudioParam offset; }; + +ConstantSourceNode includes rustAudioScheduledSourceNode; diff --git a/crates/web-sys/webidls/enabled/OfflineAudioContext.webidl b/crates/web-sys/webidls/enabled/OfflineAudioContext.webidl index a2498d6e..d4aae25e 100644 --- a/crates/web-sys/webidls/enabled/OfflineAudioContext.webidl +++ b/crates/web-sys/webidls/enabled/OfflineAudioContext.webidl @@ -29,3 +29,5 @@ interface OfflineAudioContext : BaseAudioContext { readonly attribute unsigned long length; attribute EventHandler oncomplete; }; + +OfflineAudioContext includes rustBaseAudioContext; diff --git a/crates/web-sys/webidls/enabled/OscillatorNode.webidl b/crates/web-sys/webidls/enabled/OscillatorNode.webidl index 65029ccb..2322c4ae 100644 --- a/crates/web-sys/webidls/enabled/OscillatorNode.webidl +++ b/crates/web-sys/webidls/enabled/OscillatorNode.webidl @@ -37,3 +37,5 @@ interface OscillatorNode : AudioScheduledSourceNode { void setPeriodicWave(PeriodicWave periodicWave); }; + +OscillatorNode includes rustAudioScheduledSourceNode; diff --git a/crates/webidl/src/first_pass.rs b/crates/webidl/src/first_pass.rs index 37ce61c2..0fc18c3a 100644 --- a/crates/webidl/src/first_pass.rs +++ b/crates/webidl/src/first_pass.rs @@ -44,6 +44,7 @@ pub(crate) struct FirstPassRecord<'src> { pub(crate) struct InterfaceData<'src> { /// Whether only partial interfaces were encountered pub(crate) partial: bool, + pub(crate) deprecated: Option, pub(crate) attributes: Vec<&'src AttributeInterfaceMember<'src>>, pub(crate) consts: Vec<&'src ConstMember<'src>>, pub(crate) operations: BTreeMap, OperationData<'src>>, @@ -311,6 +312,8 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> { interface_data.partial = false; interface_data.superclass = self.inheritance.map(|s| s.identifier.0); interface_data.definition_attributes = self.attributes.as_ref(); + interface_data.deprecated = util::get_rust_deprecated(&self.attributes) + .map(|s| s.to_string()); } if let Some(attrs) = &self.attributes { for attr in attrs.body.list.iter() { diff --git a/crates/webidl/src/lib.rs b/crates/webidl/src/lib.rs index fc6bab60..f4f64835 100644 --- a/crates/webidl/src/lib.rs +++ b/crates/webidl/src/lib.rs @@ -488,18 +488,15 @@ impl<'src> FirstPassRecord<'src> { data: &InterfaceData<'src>, ) { let mut doc_comment = Some(format!("The `{}` object\n\n{}", name, mdn_doc(name, None),)); - let derive = syn::Attribute { - pound_token: Default::default(), - style: syn::AttrStyle::Outer, - bracket_token: Default::default(), - path: Ident::new("derive", Span::call_site()).into(), - tts: quote!((Debug, Clone)), - }; + + let mut attrs = Vec::new(); + attrs.push(parse_quote!( #[derive(Debug, Clone)] )); + self.add_deprecated(data, &mut attrs); let mut import_type = backend::ast::ImportType { vis: public(), rust_name: rust_ident(camel_case_ident(name).as_str()), js_name: name.to_string(), - attrs: vec![derive], + attrs, doc_comment: None, instanceof_shim: format!("__widl_instanceof_{}", name), extends: Vec::new(), @@ -539,6 +536,7 @@ impl<'src> FirstPassRecord<'src> { self.member_attribute( program, name, + data, member.modifier, member.readonly.is_some(), &member.type_, @@ -559,6 +557,7 @@ impl<'src> FirstPassRecord<'src> { self.member_attribute( program, name, + data, if let Some(s) = member.stringifier { Some(weedle::interface::StringifierOrInheritOrStatic::Stringifier(s)) } else { @@ -578,6 +577,7 @@ impl<'src> FirstPassRecord<'src> { &self, program: &mut backend::ast::Program, self_name: &'src str, + data: &InterfaceData<'src>, modifier: Option, readonly: bool, type_: &'src weedle::types::AttributedType<'src>, @@ -620,6 +620,7 @@ impl<'src> FirstPassRecord<'src> { let mut doc = import_function.doc_comment.take(); self.append_required_features_doc(&import_function, &mut doc, &[]); import_function.doc_comment = doc; + self.add_deprecated(data, &mut import_function.function.rust_attrs); program.imports.push(wrap_import_function(import_function)); } } @@ -677,10 +678,19 @@ impl<'src> FirstPassRecord<'src> { let mut doc = doc.clone(); self.append_required_features_doc(&method, &mut doc, &[]); method.doc_comment = doc; + self.add_deprecated(data, &mut method.function.rust_attrs); program.imports.push(wrap_import_function(method)); } } + fn add_deprecated(&self, data: &InterfaceData<'src>, dst: &mut Vec) { + let msg = match &data.deprecated { + Some(s) => s, + None => return, + }; + dst.push(parse_quote!( #[deprecated(note = #msg)] )); + } + fn append_required_features_doc( &self, item: impl ImportedTypeReferences, diff --git a/crates/webidl/src/util.rs b/crates/webidl/src/util.rs index a67ef256..1fa8ee83 100644 --- a/crates/webidl/src/util.rs +++ b/crates/webidl/src/util.rs @@ -7,7 +7,7 @@ use heck::{CamelCase, ShoutySnakeCase, SnakeCase}; use proc_macro2::{Ident, Span}; use syn; use weedle; -use weedle::attribute::{ExtendedAttribute, ExtendedAttributeList}; +use weedle::attribute::{ExtendedAttribute, ExtendedAttributeList, IdentifierOrString}; use weedle::literal::{ConstValue, FloatLit, IntegerLit}; use first_pass::{FirstPassRecord, OperationData, OperationId, Signature}; @@ -666,6 +666,29 @@ pub fn is_no_interface_object(ext_attrs: &Option) -> bool has_named_attribute(ext_attrs.as_ref(), "NoInterfaceObject") } +pub fn get_rust_deprecated<'a>(ext_attrs: &Option>) + -> Option<&'a str> +{ + ext_attrs.as_ref()? + .body + .list + .iter() + .filter_map(|attr| { + match attr { + ExtendedAttribute::Ident(id) => Some(id), + _ => None, + } + }) + .filter_map(|ident| { + match ident.rhs { + IdentifierOrString::String(s) => Some(s), + IdentifierOrString::Identifier(_) => None, + } + }) + .next() + .map(|s| s.0) +} + /// Whether a webidl object is marked as structural. pub fn is_structural( item_attrs: Option<&ExtendedAttributeList>, diff --git a/examples/webaudio/Cargo.toml b/examples/webaudio/Cargo.toml index 1db5cc9f..d4790b28 100644 --- a/examples/webaudio/Cargo.toml +++ b/examples/webaudio/Cargo.toml @@ -16,8 +16,6 @@ features = [ 'AudioDestinationNode', 'AudioNode', 'AudioParam', - 'AudioScheduledSourceNode', - 'BaseAudioContext', 'GainNode', 'OscillatorNode', 'OscillatorType', diff --git a/examples/webaudio/src/lib.rs b/examples/webaudio/src/lib.rs index 9cbc3836..e518ce7e 100644 --- a/examples/webaudio/src/lib.rs +++ b/examples/webaudio/src/lib.rs @@ -2,9 +2,7 @@ extern crate wasm_bindgen; extern crate web_sys; use wasm_bindgen::prelude::*; -use web_sys::{ - AudioContext, AudioNode, AudioScheduledSourceNode, BaseAudioContext, OscillatorType, -}; +use web_sys::{AudioContext, AudioNode, OscillatorType}; /// Converts a midi note to frequency /// @@ -45,22 +43,14 @@ impl Drop for FmOsc { #[wasm_bindgen] impl FmOsc { #[wasm_bindgen(constructor)] - pub fn new() -> FmOsc { - let ctx = web_sys::AudioContext::new().unwrap(); - let primary; - let fm_osc; - let gain; - let fm_gain; + pub fn new() -> Result { + let ctx = web_sys::AudioContext::new()?; - { - let base: &BaseAudioContext = ctx.as_ref(); - - // Create our web audio objects. - primary = base.create_oscillator().unwrap(); - fm_osc = base.create_oscillator().unwrap(); - gain = base.create_gain().unwrap(); - fm_gain = base.create_gain().unwrap(); - } + // Create our web audio objects. + let primary = ctx.create_oscillator()?; + let fm_osc = ctx.create_oscillator()?; + let gain = ctx.create_gain()?; + let fm_gain = ctx.create_gain()?; // Some initial settings: primary.set_type(OscillatorType::Sine); @@ -76,42 +66,34 @@ impl FmOsc { let gain_node: &AudioNode = gain.as_ref(); let fm_osc_node: &AudioNode = fm_osc.as_ref(); let fm_gain_node: &AudioNode = fm_gain.as_ref(); - let base: &BaseAudioContext = ctx.as_ref(); - let destination = base.destination(); + let destination = ctx.destination(); let destination_node: &AudioNode = destination.as_ref(); // Connect the nodes up! // The primary oscillator is routed through the gain node, so that // it can control the overall output volume. - primary_node.connect_with_audio_node(gain.as_ref()).unwrap(); + primary_node.connect_with_audio_node(gain.as_ref())?; // Then connect the gain node to the AudioContext destination (aka // your speakers). - gain_node.connect_with_audio_node(destination_node).unwrap(); + gain_node.connect_with_audio_node(destination_node)?; // The FM oscillator is connected to its own gain node, so it can // control the amount of modulation. - fm_osc_node - .connect_with_audio_node(fm_gain.as_ref()) - .unwrap(); + fm_osc_node.connect_with_audio_node(fm_gain.as_ref())?; + // Connect the FM oscillator to the frequency parameter of the main // oscillator, so that the FM node can modulate its frequency. - fm_gain_node - .connect_with_audio_param(&primary.frequency()) - .unwrap(); + fm_gain_node.connect_with_audio_param(&primary.frequency())?; } // Start the oscillators! - AsRef::::as_ref(&primary) - .start() - .unwrap(); - AsRef::::as_ref(&fm_osc) - .start() - .unwrap(); + primary.start()?; + fm_osc.start()?; - FmOsc { + Ok(FmOsc { ctx, primary, gain, @@ -119,7 +101,7 @@ impl FmOsc { fm_osc, fm_freq_ratio: 0.0, fm_gain_ratio: 0.0, - } + }) } /// Sets the gain for this oscillator, between 0.0 and 1.0.