mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-12 04:21:21 +00:00
[WIP] Add support for unstable WebIDL (#1997)
* Re-enable WebGPU WebIDL as experimental * Add `web_sys_unstable_apis` attribute * Add test for unstable WebIDL * Include unstable WebIDL in docs.rs builds * Add docs and doc comment for unstable APIs * Add unstable API checks to CI
This commit is contained in:
@ -51,6 +51,8 @@ pub struct Export {
|
||||
/// Whether or not this function should be flagged as the wasm start
|
||||
/// function.
|
||||
pub start: bool,
|
||||
/// Whether the API is unstable. This is only used internally.
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
/// The 3 types variations of `self`.
|
||||
@ -71,6 +73,7 @@ pub struct Import {
|
||||
pub module: ImportModule,
|
||||
pub js_namespace: Option<Ident>,
|
||||
pub kind: ImportKind,
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug))]
|
||||
@ -126,6 +129,7 @@ pub struct ImportFunction {
|
||||
pub kind: ImportFunctionKind,
|
||||
pub shim: Ident,
|
||||
pub doc_comment: Option<String>,
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
@ -182,6 +186,7 @@ pub struct ImportType {
|
||||
pub js_name: String,
|
||||
pub attrs: Vec<syn::Attribute>,
|
||||
pub typescript_name: Option<String>,
|
||||
pub unstable_api: bool,
|
||||
pub doc_comment: Option<String>,
|
||||
pub instanceof_shim: String,
|
||||
pub is_type_of: Option<syn::Expr>,
|
||||
@ -202,6 +207,8 @@ pub struct ImportEnum {
|
||||
pub variant_values: Vec<String>,
|
||||
/// Attributes to apply to the Rust enum
|
||||
pub rust_attrs: Vec<syn::Attribute>,
|
||||
/// Whether the enum is part of an unstable WebIDL
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug))]
|
||||
@ -237,6 +244,7 @@ pub struct StructField {
|
||||
pub getter: Ident,
|
||||
pub setter: Ident,
|
||||
pub comments: Vec<String>,
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
@ -246,6 +254,7 @@ pub struct Enum {
|
||||
pub variants: Vec<Variant>,
|
||||
pub comments: Vec<String>,
|
||||
pub hole: u32,
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
@ -278,6 +287,7 @@ pub struct Const {
|
||||
pub class: Option<Ident>,
|
||||
pub ty: syn::Type,
|
||||
pub value: ConstValue,
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||
@ -299,6 +309,7 @@ pub struct Dictionary {
|
||||
pub ctor: bool,
|
||||
pub doc_comment: Option<String>,
|
||||
pub ctor_doc_comment: Option<String>,
|
||||
pub unstable_api: bool,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::ast;
|
||||
use crate::encode;
|
||||
use crate::util::ShortHash;
|
||||
use crate::util::{self, ShortHash};
|
||||
use crate::Diagnostic;
|
||||
use proc_macro2::{Ident, Literal, Span, TokenStream};
|
||||
use quote::{quote, ToTokens};
|
||||
@ -39,7 +39,10 @@ impl TryToTokens for ast::Program {
|
||||
}
|
||||
}
|
||||
for i in self.imports.iter() {
|
||||
DescribeImport(&i.kind).to_tokens(tokens);
|
||||
DescribeImport {
|
||||
kind: &i.kind,
|
||||
unstable_api: i.unstable_api,
|
||||
}.to_tokens(tokens);
|
||||
|
||||
// If there is a js namespace, check that name isn't a type. If it is,
|
||||
// this import might be a method on that type.
|
||||
@ -296,12 +299,13 @@ impl ToTokens for ast::StructField {
|
||||
})
|
||||
.to_tokens(tokens);
|
||||
|
||||
Descriptor(
|
||||
&getter,
|
||||
quote! {
|
||||
Descriptor {
|
||||
ident: &getter,
|
||||
inner: quote! {
|
||||
<#ty as WasmDescribe>::describe();
|
||||
},
|
||||
)
|
||||
unstable_api: self.unstable_api,
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
|
||||
if self.readonly {
|
||||
@ -528,16 +532,17 @@ impl TryToTokens for ast::Export {
|
||||
// this, but the tl;dr; is that this is stripped from the final wasm
|
||||
// binary along with anything it references.
|
||||
let export = Ident::new(&export_name, Span::call_site());
|
||||
Descriptor(
|
||||
&export,
|
||||
quote! {
|
||||
Descriptor {
|
||||
ident: &export,
|
||||
inner: quote! {
|
||||
inform(FUNCTION);
|
||||
inform(0);
|
||||
inform(#nargs);
|
||||
#(<#argtys as WasmDescribe>::describe();)*
|
||||
#describe_ret
|
||||
},
|
||||
)
|
||||
unstable_api: self.unstable_api,
|
||||
}
|
||||
.to_tokens(into);
|
||||
|
||||
Ok(())
|
||||
@ -562,6 +567,7 @@ impl ToTokens for ast::ImportType {
|
||||
let vis = &self.vis;
|
||||
let rust_name = &self.rust_name;
|
||||
let attrs = &self.attrs;
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
let doc_comment = match &self.doc_comment {
|
||||
None => "",
|
||||
Some(comment) => comment,
|
||||
@ -610,12 +616,14 @@ impl ToTokens for ast::ImportType {
|
||||
#[doc = #doc_comment]
|
||||
#[repr(transparent)]
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
#vis struct #rust_name {
|
||||
obj: #internal_obj
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
const #const_name: () = {
|
||||
use wasm_bindgen::convert::{IntoWasmAbi, FromWasmAbi};
|
||||
use wasm_bindgen::convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
|
||||
@ -766,6 +774,7 @@ impl ToTokens for ast::ImportType {
|
||||
for superclass in self.extends.iter() {
|
||||
(quote! {
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl From<#rust_name> for #superclass {
|
||||
#[inline]
|
||||
fn from(obj: #rust_name) -> #superclass {
|
||||
@ -775,6 +784,7 @@ impl ToTokens for ast::ImportType {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl AsRef<#superclass> for #rust_name {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &#superclass {
|
||||
@ -796,6 +806,7 @@ impl ToTokens for ast::ImportEnum {
|
||||
let variants = &self.variants;
|
||||
let variant_strings = &self.variant_values;
|
||||
let attrs = &self.rust_attrs;
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
|
||||
let mut current_idx: usize = 0;
|
||||
let variant_indexes: Vec<Literal> = variants
|
||||
@ -824,6 +835,7 @@ impl ToTokens for ast::ImportEnum {
|
||||
#[allow(bad_style)]
|
||||
#(#attrs)*
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
#vis enum #name {
|
||||
#(#variants = #variant_indexes_ref,)*
|
||||
#[doc(hidden)]
|
||||
@ -831,6 +843,7 @@ impl ToTokens for ast::ImportEnum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl #name {
|
||||
#vis fn from_js_value(obj: &wasm_bindgen::JsValue) -> Option<#name> {
|
||||
obj.as_string().and_then(|obj_str| match obj_str.as_str() {
|
||||
@ -841,6 +854,7 @@ impl ToTokens for ast::ImportEnum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::describe::WasmDescribe for #name {
|
||||
fn describe() {
|
||||
wasm_bindgen::JsValue::describe()
|
||||
@ -848,6 +862,7 @@ impl ToTokens for ast::ImportEnum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::IntoWasmAbi for #name {
|
||||
type Abi = <wasm_bindgen::JsValue as
|
||||
wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
||||
@ -859,6 +874,7 @@ impl ToTokens for ast::ImportEnum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::FromWasmAbi for #name {
|
||||
type Abi = <wasm_bindgen::JsValue as
|
||||
wasm_bindgen::convert::FromWasmAbi>::Abi;
|
||||
@ -869,18 +885,21 @@ impl ToTokens for ast::ImportEnum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::OptionIntoWasmAbi for #name {
|
||||
#[inline]
|
||||
fn none() -> Self::Abi { Object::none() }
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::OptionFromWasmAbi for #name {
|
||||
#[inline]
|
||||
fn is_none(abi: &Self::Abi) -> bool { Object::is_none(abi) }
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl From<#name> for wasm_bindgen::JsValue {
|
||||
fn from(obj: #name) -> wasm_bindgen::JsValue {
|
||||
match obj {
|
||||
@ -992,6 +1011,7 @@ impl TryToTokens for ast::ImportFunction {
|
||||
let arguments = &arguments;
|
||||
let abi_arguments = &abi_arguments;
|
||||
let abi_argument_names = &abi_argument_names;
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
|
||||
let doc_comment = match &self.doc_comment {
|
||||
None => "",
|
||||
@ -1058,6 +1078,7 @@ impl TryToTokens for ast::ImportFunction {
|
||||
|
||||
if let Some(class) = class_ty {
|
||||
(quote! {
|
||||
#unstable_api_attr
|
||||
impl #class {
|
||||
#invocation
|
||||
}
|
||||
@ -1072,11 +1093,14 @@ impl TryToTokens for ast::ImportFunction {
|
||||
}
|
||||
|
||||
// See comment above in ast::Export for what's going on here.
|
||||
struct DescribeImport<'a>(&'a ast::ImportKind);
|
||||
struct DescribeImport<'a> {
|
||||
kind: &'a ast::ImportKind,
|
||||
unstable_api: bool,
|
||||
}
|
||||
|
||||
impl<'a> ToTokens for DescribeImport<'a> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let f = match *self.0 {
|
||||
let f = match *self.kind {
|
||||
ast::ImportKind::Function(ref f) => f,
|
||||
ast::ImportKind::Static(_) => return,
|
||||
ast::ImportKind::Type(_) => return,
|
||||
@ -1089,16 +1113,17 @@ impl<'a> ToTokens for DescribeImport<'a> {
|
||||
None => quote! { <() as WasmDescribe>::describe(); },
|
||||
};
|
||||
|
||||
Descriptor(
|
||||
&f.shim,
|
||||
quote! {
|
||||
Descriptor {
|
||||
ident: &f.shim,
|
||||
inner: quote! {
|
||||
inform(FUNCTION);
|
||||
inform(0);
|
||||
inform(#nargs);
|
||||
#(<#argtys as WasmDescribe>::describe();)*
|
||||
#inform_ret
|
||||
},
|
||||
)
|
||||
unstable_api: self.unstable_api,
|
||||
}
|
||||
.to_tokens(tokens);
|
||||
}
|
||||
}
|
||||
@ -1107,6 +1132,7 @@ impl ToTokens for ast::Enum {
|
||||
fn to_tokens(&self, into: &mut TokenStream) {
|
||||
let enum_name = &self.name;
|
||||
let hole = &self.hole;
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
let cast_clauses = self.variants.iter().map(|variant| {
|
||||
let variant_name = &variant.name;
|
||||
quote! {
|
||||
@ -1117,6 +1143,7 @@ impl ToTokens for ast::Enum {
|
||||
});
|
||||
(quote! {
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::IntoWasmAbi for #enum_name {
|
||||
type Abi = u32;
|
||||
|
||||
@ -1127,6 +1154,7 @@ impl ToTokens for ast::Enum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::FromWasmAbi for #enum_name {
|
||||
type Abi = u32;
|
||||
|
||||
@ -1139,18 +1167,21 @@ impl ToTokens for ast::Enum {
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name {
|
||||
#[inline]
|
||||
fn is_none(val: &u32) -> bool { *val == #hole }
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::convert::OptionIntoWasmAbi for #enum_name {
|
||||
#[inline]
|
||||
fn none() -> Self::Abi { #hole }
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl wasm_bindgen::describe::WasmDescribe for #enum_name {
|
||||
fn describe() {
|
||||
use wasm_bindgen::describe::*;
|
||||
@ -1196,12 +1227,13 @@ impl ToTokens for ast::ImportStatic {
|
||||
})
|
||||
.to_tokens(into);
|
||||
|
||||
Descriptor(
|
||||
&shim_name,
|
||||
quote! {
|
||||
Descriptor {
|
||||
ident: &shim_name,
|
||||
inner: quote! {
|
||||
<#ty as WasmDescribe>::describe();
|
||||
},
|
||||
)
|
||||
unstable_api: false,
|
||||
}
|
||||
.to_tokens(into);
|
||||
}
|
||||
}
|
||||
@ -1213,6 +1245,7 @@ impl ToTokens for ast::Const {
|
||||
let vis = &self.vis;
|
||||
let name = &self.name;
|
||||
let ty = &self.ty;
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
|
||||
let value: TokenStream = match self.value {
|
||||
BooleanLiteral(false) => quote!(false),
|
||||
@ -1244,6 +1277,7 @@ impl ToTokens for ast::Const {
|
||||
|
||||
if let Some(class) = &self.class {
|
||||
(quote! {
|
||||
#unstable_api_attr
|
||||
impl #class {
|
||||
#declaration
|
||||
}
|
||||
@ -1257,6 +1291,7 @@ impl ToTokens for ast::Const {
|
||||
|
||||
impl ToTokens for ast::Dictionary {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
let name = &self.name;
|
||||
let mut methods = TokenStream::new();
|
||||
for field in self.fields.iter() {
|
||||
@ -1304,11 +1339,13 @@ impl ToTokens for ast::Dictionary {
|
||||
#[repr(transparent)]
|
||||
#[allow(clippy::all)]
|
||||
#[doc = #doc_comment]
|
||||
#unstable_api_attr
|
||||
pub struct #name {
|
||||
obj: ::js_sys::Object,
|
||||
}
|
||||
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
impl #name {
|
||||
#ctor
|
||||
#methods
|
||||
@ -1316,6 +1353,7 @@ impl ToTokens for ast::Dictionary {
|
||||
|
||||
#[allow(bad_style)]
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
const #const_name: () = {
|
||||
use js_sys::Object;
|
||||
use wasm_bindgen::describe::WasmDescribe;
|
||||
@ -1443,7 +1481,11 @@ impl ToTokens for ast::DictionaryField {
|
||||
|
||||
/// Emits the necessary glue tokens for "descriptor", generating an appropriate
|
||||
/// symbol name as well as attributes around the descriptor function itself.
|
||||
struct Descriptor<'a, T>(&'a Ident, T);
|
||||
struct Descriptor<'a, T> {
|
||||
ident: &'a Ident,
|
||||
inner: T,
|
||||
unstable_api: bool,
|
||||
}
|
||||
|
||||
impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
@ -1458,22 +1500,27 @@ impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> {
|
||||
lazy_static::lazy_static! {
|
||||
static ref DESCRIPTORS_EMITTED: Mutex<HashSet<String>> = Default::default();
|
||||
}
|
||||
|
||||
let ident = self.ident;
|
||||
|
||||
if !DESCRIPTORS_EMITTED
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(self.0.to_string())
|
||||
.insert(ident.to_string())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let name = Ident::new(&format!("__wbindgen_describe_{}", self.0), self.0.span());
|
||||
let inner = &self.1;
|
||||
let name = Ident::new(&format!("__wbindgen_describe_{}", ident), ident.span());
|
||||
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||
let inner = &self.inner;
|
||||
(quote! {
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
#[doc(hidden)]
|
||||
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
||||
#[allow(clippy::all)]
|
||||
#unstable_api_attr
|
||||
pub extern "C" fn #name() {
|
||||
use wasm_bindgen::describe::*;
|
||||
// See definition of `link_mem_intrinsics` for what this is doing
|
||||
|
@ -188,6 +188,7 @@ fn shared_export<'a>(
|
||||
function: shared_function(&export.function, intern),
|
||||
method_kind,
|
||||
start: export.start,
|
||||
unstable_api: export.unstable_api,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -113,10 +113,12 @@ pub fn ident_ty(ident: Ident) -> syn::Type {
|
||||
}
|
||||
|
||||
pub fn wrap_import_function(function: ast::ImportFunction) -> ast::Import {
|
||||
let unstable_api = function.unstable_api;
|
||||
ast::Import {
|
||||
module: ast::ImportModule::None,
|
||||
js_namespace: None,
|
||||
kind: ast::ImportKind::Function(function),
|
||||
unstable_api,
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,3 +156,20 @@ impl<T: Hash> fmt::Display for ShortHash<T> {
|
||||
write!(f, "{:016x}", h.finish())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Create syn attribute for `#[cfg(web_sys_unstable_apis)]` and a doc comment.
|
||||
pub fn unstable_api_attrs() -> proc_macro2::TokenStream {
|
||||
quote::quote!(
|
||||
#[cfg(web_sys_unstable_apis)]
|
||||
#[doc = "\n\n*This API is unstable and requires `--cfg=web_sys_unstable_apis` to be activated, as [described in the `wasm-bindgen` guide](https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html)*"]
|
||||
)
|
||||
}
|
||||
|
||||
pub fn maybe_unstable_api_attr(unstable_api: bool) -> Option<proc_macro2::TokenStream> {
|
||||
if unstable_api {
|
||||
Some(unstable_api_attrs())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user