mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 10:10:52 +00:00
Merge pull request #909 from alexcrichton/fix-webidl
Fix our WebIDL for Safari
This commit is contained in:
commit
3001d1e973
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -37,3 +37,5 @@ interface AudioContext : BaseAudioContext {
|
||||
[NewObject, Throws]
|
||||
MediaStreamAudioDestinationNode createMediaStreamDestination();
|
||||
};
|
||||
|
||||
AudioContext includes rustBaseAudioContext;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -19,3 +19,5 @@ dictionary ConstantSourceOptions {
|
||||
interface ConstantSourceNode : AudioScheduledSourceNode {
|
||||
readonly attribute AudioParam offset;
|
||||
};
|
||||
|
||||
ConstantSourceNode includes rustAudioScheduledSourceNode;
|
||||
|
@ -29,3 +29,5 @@ interface OfflineAudioContext : BaseAudioContext {
|
||||
readonly attribute unsigned long length;
|
||||
attribute EventHandler oncomplete;
|
||||
};
|
||||
|
||||
OfflineAudioContext includes rustBaseAudioContext;
|
||||
|
@ -37,3 +37,5 @@ interface OscillatorNode : AudioScheduledSourceNode {
|
||||
|
||||
void setPeriodicWave(PeriodicWave periodicWave);
|
||||
};
|
||||
|
||||
OscillatorNode includes rustAudioScheduledSourceNode;
|
||||
|
@ -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<String>,
|
||||
pub(crate) attributes: Vec<&'src AttributeInterfaceMember<'src>>,
|
||||
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
||||
pub(crate) operations: BTreeMap<OperationId<'src>, 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() {
|
||||
|
@ -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<weedle::interface::StringifierOrInheritOrStatic>,
|
||||
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<syn::Attribute>) {
|
||||
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,
|
||||
|
@ -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<ExtendedAttributeList>) -> bool
|
||||
has_named_attribute(ext_attrs.as_ref(), "NoInterfaceObject")
|
||||
}
|
||||
|
||||
pub fn get_rust_deprecated<'a>(ext_attrs: &Option<ExtendedAttributeList<'a>>)
|
||||
-> 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>,
|
||||
|
@ -16,8 +16,6 @@ features = [
|
||||
'AudioDestinationNode',
|
||||
'AudioNode',
|
||||
'AudioParam',
|
||||
'AudioScheduledSourceNode',
|
||||
'BaseAudioContext',
|
||||
'GainNode',
|
||||
'OscillatorNode',
|
||||
'OscillatorType',
|
||||
|
@ -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<FmOsc, JsValue> {
|
||||
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::<AudioScheduledSourceNode>::as_ref(&primary)
|
||||
.start()
|
||||
.unwrap();
|
||||
AsRef::<AudioScheduledSourceNode>::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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user