mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-04-25 06:02:13 +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:
parent
d26068dc6c
commit
99c59a771e
@ -14,7 +14,8 @@ Easy support for interacting between JS and Rust.
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ['serde-serialize']
|
features = ["serde-serialize"]
|
||||||
|
rustc-args = ["--cfg=web_sys_unstable_apis"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
test = false
|
test = false
|
||||||
|
@ -122,6 +122,10 @@ jobs:
|
|||||||
- script: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Element
|
- script: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Element
|
||||||
- script: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Window
|
- script: cargo build --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --features Window
|
||||||
- script: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features
|
- script: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features
|
||||||
|
- script: cargo test --manifest-path crates/web-sys/Cargo.toml --target wasm32-unknown-unknown --all-features
|
||||||
|
displayName: "web-sys unstable APIs"
|
||||||
|
env:
|
||||||
|
RUSTFLAGS: --cfg=web_sys_unstable_apis
|
||||||
|
|
||||||
- job: test_js_sys
|
- job: test_js_sys
|
||||||
displayName: "Run js-sys crate tests"
|
displayName: "Run js-sys crate tests"
|
||||||
@ -150,6 +154,10 @@ jobs:
|
|||||||
- script: cargo test -p webidl-tests --target wasm32-unknown-unknown
|
- script: cargo test -p webidl-tests --target wasm32-unknown-unknown
|
||||||
env:
|
env:
|
||||||
WBINDGEN_I_PROMISE_JS_SYNTAX_WORKS_IN_NODE: 1
|
WBINDGEN_I_PROMISE_JS_SYNTAX_WORKS_IN_NODE: 1
|
||||||
|
- script: cargo test -p webidl-tests --target wasm32-unknown-unknown
|
||||||
|
displayName: "webidl-tests unstable APIs"
|
||||||
|
env:
|
||||||
|
RUSTFLAGS: --cfg=web_sys_unstable_apis
|
||||||
|
|
||||||
- job: test_ui
|
- job: test_ui
|
||||||
displayName: "Run UI tests"
|
displayName: "Run UI tests"
|
||||||
@ -319,6 +327,8 @@ jobs:
|
|||||||
displayName: "Document js-sys"
|
displayName: "Document js-sys"
|
||||||
- script: cargo doc --no-deps --manifest-path crates/web-sys/Cargo.toml --all-features
|
- script: cargo doc --no-deps --manifest-path crates/web-sys/Cargo.toml --all-features
|
||||||
displayName: "Document web-sys"
|
displayName: "Document web-sys"
|
||||||
|
env:
|
||||||
|
RUSTFLAGS: --cfg=web_sys_unstable_apis
|
||||||
- script: cargo doc --no-deps --manifest-path crates/futures/Cargo.toml
|
- script: cargo doc --no-deps --manifest-path crates/futures/Cargo.toml
|
||||||
displayName: "Document wasm-bindgen-futures"
|
displayName: "Document wasm-bindgen-futures"
|
||||||
# Make a tarball even though a zip is uploaded, it looks like the tarball
|
# Make a tarball even though a zip is uploaded, it looks like the tarball
|
||||||
|
@ -51,6 +51,8 @@ pub struct Export {
|
|||||||
/// Whether or not this function should be flagged as the wasm start
|
/// Whether or not this function should be flagged as the wasm start
|
||||||
/// function.
|
/// function.
|
||||||
pub start: bool,
|
pub start: bool,
|
||||||
|
/// Whether the API is unstable. This is only used internally.
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The 3 types variations of `self`.
|
/// The 3 types variations of `self`.
|
||||||
@ -71,6 +73,7 @@ pub struct Import {
|
|||||||
pub module: ImportModule,
|
pub module: ImportModule,
|
||||||
pub js_namespace: Option<Ident>,
|
pub js_namespace: Option<Ident>,
|
||||||
pub kind: ImportKind,
|
pub kind: ImportKind,
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug))]
|
||||||
@ -126,6 +129,7 @@ pub struct ImportFunction {
|
|||||||
pub kind: ImportFunctionKind,
|
pub kind: ImportFunctionKind,
|
||||||
pub shim: Ident,
|
pub shim: Ident,
|
||||||
pub doc_comment: Option<String>,
|
pub doc_comment: Option<String>,
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
@ -182,6 +186,7 @@ pub struct ImportType {
|
|||||||
pub js_name: String,
|
pub js_name: String,
|
||||||
pub attrs: Vec<syn::Attribute>,
|
pub attrs: Vec<syn::Attribute>,
|
||||||
pub typescript_name: Option<String>,
|
pub typescript_name: Option<String>,
|
||||||
|
pub unstable_api: bool,
|
||||||
pub doc_comment: Option<String>,
|
pub doc_comment: Option<String>,
|
||||||
pub instanceof_shim: String,
|
pub instanceof_shim: String,
|
||||||
pub is_type_of: Option<syn::Expr>,
|
pub is_type_of: Option<syn::Expr>,
|
||||||
@ -202,6 +207,8 @@ pub struct ImportEnum {
|
|||||||
pub variant_values: Vec<String>,
|
pub variant_values: Vec<String>,
|
||||||
/// Attributes to apply to the Rust enum
|
/// Attributes to apply to the Rust enum
|
||||||
pub rust_attrs: Vec<syn::Attribute>,
|
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))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug))]
|
||||||
@ -237,6 +244,7 @@ pub struct StructField {
|
|||||||
pub getter: Ident,
|
pub getter: Ident,
|
||||||
pub setter: Ident,
|
pub setter: Ident,
|
||||||
pub comments: Vec<String>,
|
pub comments: Vec<String>,
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
@ -246,6 +254,7 @@ pub struct Enum {
|
|||||||
pub variants: Vec<Variant>,
|
pub variants: Vec<Variant>,
|
||||||
pub comments: Vec<String>,
|
pub comments: Vec<String>,
|
||||||
pub hole: u32,
|
pub hole: u32,
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
@ -278,6 +287,7 @@ pub struct Const {
|
|||||||
pub class: Option<Ident>,
|
pub class: Option<Ident>,
|
||||||
pub ty: syn::Type,
|
pub ty: syn::Type,
|
||||||
pub value: ConstValue,
|
pub value: ConstValue,
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq))]
|
||||||
@ -299,6 +309,7 @@ pub struct Dictionary {
|
|||||||
pub ctor: bool,
|
pub ctor: bool,
|
||||||
pub doc_comment: Option<String>,
|
pub doc_comment: Option<String>,
|
||||||
pub ctor_doc_comment: Option<String>,
|
pub ctor_doc_comment: Option<String>,
|
||||||
|
pub unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(feature = "extra-traits", derive(Debug, PartialEq, Eq))]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::ast;
|
use crate::ast;
|
||||||
use crate::encode;
|
use crate::encode;
|
||||||
use crate::util::ShortHash;
|
use crate::util::{self, ShortHash};
|
||||||
use crate::Diagnostic;
|
use crate::Diagnostic;
|
||||||
use proc_macro2::{Ident, Literal, Span, TokenStream};
|
use proc_macro2::{Ident, Literal, Span, TokenStream};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
@ -39,7 +39,10 @@ impl TryToTokens for ast::Program {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i in self.imports.iter() {
|
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,
|
// 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.
|
// this import might be a method on that type.
|
||||||
@ -296,12 +299,13 @@ impl ToTokens for ast::StructField {
|
|||||||
})
|
})
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
|
|
||||||
Descriptor(
|
Descriptor {
|
||||||
&getter,
|
ident: &getter,
|
||||||
quote! {
|
inner: quote! {
|
||||||
<#ty as WasmDescribe>::describe();
|
<#ty as WasmDescribe>::describe();
|
||||||
},
|
},
|
||||||
)
|
unstable_api: self.unstable_api,
|
||||||
|
}
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
|
|
||||||
if self.readonly {
|
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
|
// this, but the tl;dr; is that this is stripped from the final wasm
|
||||||
// binary along with anything it references.
|
// binary along with anything it references.
|
||||||
let export = Ident::new(&export_name, Span::call_site());
|
let export = Ident::new(&export_name, Span::call_site());
|
||||||
Descriptor(
|
Descriptor {
|
||||||
&export,
|
ident: &export,
|
||||||
quote! {
|
inner: quote! {
|
||||||
inform(FUNCTION);
|
inform(FUNCTION);
|
||||||
inform(0);
|
inform(0);
|
||||||
inform(#nargs);
|
inform(#nargs);
|
||||||
#(<#argtys as WasmDescribe>::describe();)*
|
#(<#argtys as WasmDescribe>::describe();)*
|
||||||
#describe_ret
|
#describe_ret
|
||||||
},
|
},
|
||||||
)
|
unstable_api: self.unstable_api,
|
||||||
|
}
|
||||||
.to_tokens(into);
|
.to_tokens(into);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -562,6 +567,7 @@ impl ToTokens for ast::ImportType {
|
|||||||
let vis = &self.vis;
|
let vis = &self.vis;
|
||||||
let rust_name = &self.rust_name;
|
let rust_name = &self.rust_name;
|
||||||
let attrs = &self.attrs;
|
let attrs = &self.attrs;
|
||||||
|
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||||
let doc_comment = match &self.doc_comment {
|
let doc_comment = match &self.doc_comment {
|
||||||
None => "",
|
None => "",
|
||||||
Some(comment) => comment,
|
Some(comment) => comment,
|
||||||
@ -610,12 +616,14 @@ impl ToTokens for ast::ImportType {
|
|||||||
#[doc = #doc_comment]
|
#[doc = #doc_comment]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
#vis struct #rust_name {
|
#vis struct #rust_name {
|
||||||
obj: #internal_obj
|
obj: #internal_obj
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(bad_style)]
|
#[allow(bad_style)]
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
const #const_name: () = {
|
const #const_name: () = {
|
||||||
use wasm_bindgen::convert::{IntoWasmAbi, FromWasmAbi};
|
use wasm_bindgen::convert::{IntoWasmAbi, FromWasmAbi};
|
||||||
use wasm_bindgen::convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
|
use wasm_bindgen::convert::{OptionIntoWasmAbi, OptionFromWasmAbi};
|
||||||
@ -766,6 +774,7 @@ impl ToTokens for ast::ImportType {
|
|||||||
for superclass in self.extends.iter() {
|
for superclass in self.extends.iter() {
|
||||||
(quote! {
|
(quote! {
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl From<#rust_name> for #superclass {
|
impl From<#rust_name> for #superclass {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(obj: #rust_name) -> #superclass {
|
fn from(obj: #rust_name) -> #superclass {
|
||||||
@ -775,6 +784,7 @@ impl ToTokens for ast::ImportType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl AsRef<#superclass> for #rust_name {
|
impl AsRef<#superclass> for #rust_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &#superclass {
|
fn as_ref(&self) -> &#superclass {
|
||||||
@ -796,6 +806,7 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
let variants = &self.variants;
|
let variants = &self.variants;
|
||||||
let variant_strings = &self.variant_values;
|
let variant_strings = &self.variant_values;
|
||||||
let attrs = &self.rust_attrs;
|
let attrs = &self.rust_attrs;
|
||||||
|
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||||
|
|
||||||
let mut current_idx: usize = 0;
|
let mut current_idx: usize = 0;
|
||||||
let variant_indexes: Vec<Literal> = variants
|
let variant_indexes: Vec<Literal> = variants
|
||||||
@ -824,6 +835,7 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
#[allow(bad_style)]
|
#[allow(bad_style)]
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
#vis enum #name {
|
#vis enum #name {
|
||||||
#(#variants = #variant_indexes_ref,)*
|
#(#variants = #variant_indexes_ref,)*
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -831,6 +843,7 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl #name {
|
impl #name {
|
||||||
#vis fn from_js_value(obj: &wasm_bindgen::JsValue) -> Option<#name> {
|
#vis fn from_js_value(obj: &wasm_bindgen::JsValue) -> Option<#name> {
|
||||||
obj.as_string().and_then(|obj_str| match obj_str.as_str() {
|
obj.as_string().and_then(|obj_str| match obj_str.as_str() {
|
||||||
@ -841,6 +854,7 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::describe::WasmDescribe for #name {
|
impl wasm_bindgen::describe::WasmDescribe for #name {
|
||||||
fn describe() {
|
fn describe() {
|
||||||
wasm_bindgen::JsValue::describe()
|
wasm_bindgen::JsValue::describe()
|
||||||
@ -848,6 +862,7 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::IntoWasmAbi for #name {
|
impl wasm_bindgen::convert::IntoWasmAbi for #name {
|
||||||
type Abi = <wasm_bindgen::JsValue as
|
type Abi = <wasm_bindgen::JsValue as
|
||||||
wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
wasm_bindgen::convert::IntoWasmAbi>::Abi;
|
||||||
@ -859,6 +874,7 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::FromWasmAbi for #name {
|
impl wasm_bindgen::convert::FromWasmAbi for #name {
|
||||||
type Abi = <wasm_bindgen::JsValue as
|
type Abi = <wasm_bindgen::JsValue as
|
||||||
wasm_bindgen::convert::FromWasmAbi>::Abi;
|
wasm_bindgen::convert::FromWasmAbi>::Abi;
|
||||||
@ -869,18 +885,21 @@ impl ToTokens for ast::ImportEnum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::OptionIntoWasmAbi for #name {
|
impl wasm_bindgen::convert::OptionIntoWasmAbi for #name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn none() -> Self::Abi { Object::none() }
|
fn none() -> Self::Abi { Object::none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::OptionFromWasmAbi for #name {
|
impl wasm_bindgen::convert::OptionFromWasmAbi for #name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_none(abi: &Self::Abi) -> bool { Object::is_none(abi) }
|
fn is_none(abi: &Self::Abi) -> bool { Object::is_none(abi) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl From<#name> for wasm_bindgen::JsValue {
|
impl From<#name> for wasm_bindgen::JsValue {
|
||||||
fn from(obj: #name) -> wasm_bindgen::JsValue {
|
fn from(obj: #name) -> wasm_bindgen::JsValue {
|
||||||
match obj {
|
match obj {
|
||||||
@ -992,6 +1011,7 @@ impl TryToTokens for ast::ImportFunction {
|
|||||||
let arguments = &arguments;
|
let arguments = &arguments;
|
||||||
let abi_arguments = &abi_arguments;
|
let abi_arguments = &abi_arguments;
|
||||||
let abi_argument_names = &abi_argument_names;
|
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 {
|
let doc_comment = match &self.doc_comment {
|
||||||
None => "",
|
None => "",
|
||||||
@ -1058,6 +1078,7 @@ impl TryToTokens for ast::ImportFunction {
|
|||||||
|
|
||||||
if let Some(class) = class_ty {
|
if let Some(class) = class_ty {
|
||||||
(quote! {
|
(quote! {
|
||||||
|
#unstable_api_attr
|
||||||
impl #class {
|
impl #class {
|
||||||
#invocation
|
#invocation
|
||||||
}
|
}
|
||||||
@ -1072,11 +1093,14 @@ impl TryToTokens for ast::ImportFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// See comment above in ast::Export for what's going on here.
|
// 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> {
|
impl<'a> ToTokens for DescribeImport<'a> {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
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::Function(ref f) => f,
|
||||||
ast::ImportKind::Static(_) => return,
|
ast::ImportKind::Static(_) => return,
|
||||||
ast::ImportKind::Type(_) => return,
|
ast::ImportKind::Type(_) => return,
|
||||||
@ -1089,16 +1113,17 @@ impl<'a> ToTokens for DescribeImport<'a> {
|
|||||||
None => quote! { <() as WasmDescribe>::describe(); },
|
None => quote! { <() as WasmDescribe>::describe(); },
|
||||||
};
|
};
|
||||||
|
|
||||||
Descriptor(
|
Descriptor {
|
||||||
&f.shim,
|
ident: &f.shim,
|
||||||
quote! {
|
inner: quote! {
|
||||||
inform(FUNCTION);
|
inform(FUNCTION);
|
||||||
inform(0);
|
inform(0);
|
||||||
inform(#nargs);
|
inform(#nargs);
|
||||||
#(<#argtys as WasmDescribe>::describe();)*
|
#(<#argtys as WasmDescribe>::describe();)*
|
||||||
#inform_ret
|
#inform_ret
|
||||||
},
|
},
|
||||||
)
|
unstable_api: self.unstable_api,
|
||||||
|
}
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1107,6 +1132,7 @@ impl ToTokens for ast::Enum {
|
|||||||
fn to_tokens(&self, into: &mut TokenStream) {
|
fn to_tokens(&self, into: &mut TokenStream) {
|
||||||
let enum_name = &self.name;
|
let enum_name = &self.name;
|
||||||
let hole = &self.hole;
|
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 cast_clauses = self.variants.iter().map(|variant| {
|
||||||
let variant_name = &variant.name;
|
let variant_name = &variant.name;
|
||||||
quote! {
|
quote! {
|
||||||
@ -1117,6 +1143,7 @@ impl ToTokens for ast::Enum {
|
|||||||
});
|
});
|
||||||
(quote! {
|
(quote! {
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::IntoWasmAbi for #enum_name {
|
impl wasm_bindgen::convert::IntoWasmAbi for #enum_name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
@ -1127,6 +1154,7 @@ impl ToTokens for ast::Enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::FromWasmAbi for #enum_name {
|
impl wasm_bindgen::convert::FromWasmAbi for #enum_name {
|
||||||
type Abi = u32;
|
type Abi = u32;
|
||||||
|
|
||||||
@ -1139,18 +1167,21 @@ impl ToTokens for ast::Enum {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name {
|
impl wasm_bindgen::convert::OptionFromWasmAbi for #enum_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_none(val: &u32) -> bool { *val == #hole }
|
fn is_none(val: &u32) -> bool { *val == #hole }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::convert::OptionIntoWasmAbi for #enum_name {
|
impl wasm_bindgen::convert::OptionIntoWasmAbi for #enum_name {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn none() -> Self::Abi { #hole }
|
fn none() -> Self::Abi { #hole }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl wasm_bindgen::describe::WasmDescribe for #enum_name {
|
impl wasm_bindgen::describe::WasmDescribe for #enum_name {
|
||||||
fn describe() {
|
fn describe() {
|
||||||
use wasm_bindgen::describe::*;
|
use wasm_bindgen::describe::*;
|
||||||
@ -1196,12 +1227,13 @@ impl ToTokens for ast::ImportStatic {
|
|||||||
})
|
})
|
||||||
.to_tokens(into);
|
.to_tokens(into);
|
||||||
|
|
||||||
Descriptor(
|
Descriptor {
|
||||||
&shim_name,
|
ident: &shim_name,
|
||||||
quote! {
|
inner: quote! {
|
||||||
<#ty as WasmDescribe>::describe();
|
<#ty as WasmDescribe>::describe();
|
||||||
},
|
},
|
||||||
)
|
unstable_api: false,
|
||||||
|
}
|
||||||
.to_tokens(into);
|
.to_tokens(into);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1213,6 +1245,7 @@ impl ToTokens for ast::Const {
|
|||||||
let vis = &self.vis;
|
let vis = &self.vis;
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
let ty = &self.ty;
|
let ty = &self.ty;
|
||||||
|
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||||
|
|
||||||
let value: TokenStream = match self.value {
|
let value: TokenStream = match self.value {
|
||||||
BooleanLiteral(false) => quote!(false),
|
BooleanLiteral(false) => quote!(false),
|
||||||
@ -1244,6 +1277,7 @@ impl ToTokens for ast::Const {
|
|||||||
|
|
||||||
if let Some(class) = &self.class {
|
if let Some(class) = &self.class {
|
||||||
(quote! {
|
(quote! {
|
||||||
|
#unstable_api_attr
|
||||||
impl #class {
|
impl #class {
|
||||||
#declaration
|
#declaration
|
||||||
}
|
}
|
||||||
@ -1257,6 +1291,7 @@ impl ToTokens for ast::Const {
|
|||||||
|
|
||||||
impl ToTokens for ast::Dictionary {
|
impl ToTokens for ast::Dictionary {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
|
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
let mut methods = TokenStream::new();
|
let mut methods = TokenStream::new();
|
||||||
for field in self.fields.iter() {
|
for field in self.fields.iter() {
|
||||||
@ -1304,11 +1339,13 @@ impl ToTokens for ast::Dictionary {
|
|||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
#[doc = #doc_comment]
|
#[doc = #doc_comment]
|
||||||
|
#unstable_api_attr
|
||||||
pub struct #name {
|
pub struct #name {
|
||||||
obj: ::js_sys::Object,
|
obj: ::js_sys::Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
impl #name {
|
impl #name {
|
||||||
#ctor
|
#ctor
|
||||||
#methods
|
#methods
|
||||||
@ -1316,6 +1353,7 @@ impl ToTokens for ast::Dictionary {
|
|||||||
|
|
||||||
#[allow(bad_style)]
|
#[allow(bad_style)]
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
const #const_name: () = {
|
const #const_name: () = {
|
||||||
use js_sys::Object;
|
use js_sys::Object;
|
||||||
use wasm_bindgen::describe::WasmDescribe;
|
use wasm_bindgen::describe::WasmDescribe;
|
||||||
@ -1443,7 +1481,11 @@ impl ToTokens for ast::DictionaryField {
|
|||||||
|
|
||||||
/// Emits the necessary glue tokens for "descriptor", generating an appropriate
|
/// Emits the necessary glue tokens for "descriptor", generating an appropriate
|
||||||
/// symbol name as well as attributes around the descriptor function itself.
|
/// 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> {
|
impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
@ -1458,22 +1500,27 @@ impl<'a, T: ToTokens> ToTokens for Descriptor<'a, T> {
|
|||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref DESCRIPTORS_EMITTED: Mutex<HashSet<String>> = Default::default();
|
static ref DESCRIPTORS_EMITTED: Mutex<HashSet<String>> = Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let ident = self.ident;
|
||||||
|
|
||||||
if !DESCRIPTORS_EMITTED
|
if !DESCRIPTORS_EMITTED
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(self.0.to_string())
|
.insert(ident.to_string())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = Ident::new(&format!("__wbindgen_describe_{}", self.0), self.0.span());
|
let name = Ident::new(&format!("__wbindgen_describe_{}", ident), ident.span());
|
||||||
let inner = &self.1;
|
let unstable_api_attr = util::maybe_unstable_api_attr(self.unstable_api);
|
||||||
|
let inner = &self.inner;
|
||||||
(quote! {
|
(quote! {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
|
||||||
#[allow(clippy::all)]
|
#[allow(clippy::all)]
|
||||||
|
#unstable_api_attr
|
||||||
pub extern "C" fn #name() {
|
pub extern "C" fn #name() {
|
||||||
use wasm_bindgen::describe::*;
|
use wasm_bindgen::describe::*;
|
||||||
// See definition of `link_mem_intrinsics` for what this is doing
|
// 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),
|
function: shared_function(&export.function, intern),
|
||||||
method_kind,
|
method_kind,
|
||||||
start: export.start,
|
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 {
|
pub fn wrap_import_function(function: ast::ImportFunction) -> ast::Import {
|
||||||
|
let unstable_api = function.unstable_api;
|
||||||
ast::Import {
|
ast::Import {
|
||||||
module: ast::ImportModule::None,
|
module: ast::ImportModule::None,
|
||||||
js_namespace: None,
|
js_namespace: None,
|
||||||
kind: ast::ImportKind::Function(function),
|
kind: ast::ImportKind::Function(function),
|
||||||
|
unstable_api,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,3 +156,20 @@ impl<T: Hash> fmt::Display for ShortHash<T> {
|
|||||||
write!(f, "{:016x}", h.finish())
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ struct AttributeParseState {
|
|||||||
pub struct BindgenAttrs {
|
pub struct BindgenAttrs {
|
||||||
/// List of parsed attributes
|
/// List of parsed attributes
|
||||||
pub attrs: Vec<(Cell<bool>, BindgenAttr)>,
|
pub attrs: Vec<(Cell<bool>, BindgenAttr)>,
|
||||||
|
pub unstable_api_attr: Option<syn::Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! attrgen {
|
macro_rules! attrgen {
|
||||||
@ -186,7 +187,7 @@ impl Default for BindgenAttrs {
|
|||||||
// sanity check that we call `check_used` an appropriate number of
|
// sanity check that we call `check_used` an appropriate number of
|
||||||
// times.
|
// times.
|
||||||
ATTRS.with(|state| state.parsed.set(state.parsed.get() + 1));
|
ATTRS.with(|state| state.parsed.set(state.parsed.get() + 1));
|
||||||
BindgenAttrs { attrs: Vec::new() }
|
BindgenAttrs { attrs: Vec::new(), unstable_api_attr: None, }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,6 +354,7 @@ impl<'a> ConvertToAst<BindgenAttrs> for &'a mut syn::ItemStruct {
|
|||||||
getter: Ident::new(&getter, Span::call_site()),
|
getter: Ident::new(&getter, Span::call_site()),
|
||||||
setter: Ident::new(&setter, Span::call_site()),
|
setter: Ident::new(&setter, Span::call_site()),
|
||||||
comments,
|
comments,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
attrs.check_used()?;
|
attrs.check_used()?;
|
||||||
}
|
}
|
||||||
@ -513,6 +515,7 @@ impl<'a> ConvertToAst<(BindgenAttrs, &'a ast::ImportModule)> for syn::ForeignIte
|
|||||||
rust_name: self.sig.ident.clone(),
|
rust_name: self.sig.ident.clone(),
|
||||||
shim: Ident::new(&shim, Span::call_site()),
|
shim: Ident::new(&shim, Span::call_site()),
|
||||||
doc_comment: None,
|
doc_comment: None,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
opts.check_used()?;
|
opts.check_used()?;
|
||||||
|
|
||||||
@ -550,6 +553,7 @@ impl ConvertToAst<BindgenAttrs> for syn::ForeignItemType {
|
|||||||
Ok(ast::ImportKind::Type(ast::ImportType {
|
Ok(ast::ImportKind::Type(ast::ImportType {
|
||||||
vis: self.vis,
|
vis: self.vis,
|
||||||
attrs: self.attrs,
|
attrs: self.attrs,
|
||||||
|
unstable_api: false,
|
||||||
doc_comment: None,
|
doc_comment: None,
|
||||||
instanceof_shim: shim,
|
instanceof_shim: shim,
|
||||||
is_type_of,
|
is_type_of,
|
||||||
@ -777,6 +781,7 @@ impl<'a> MacroParse<(Option<BindgenAttrs>, &'a mut TokenStream)> for syn::Item {
|
|||||||
rust_class: None,
|
rust_class: None,
|
||||||
rust_name,
|
rust_name,
|
||||||
start,
|
start,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
syn::Item::Struct(mut s) => {
|
syn::Item::Struct(mut s) => {
|
||||||
@ -977,6 +982,7 @@ impl<'a, 'b> MacroParse<(&'a Ident, &'a str)> for &'b mut syn::ImplItemMethod {
|
|||||||
rust_class: Some(class.clone()),
|
rust_class: Some(class.clone()),
|
||||||
rust_name: self.sig.ident.clone(),
|
rust_name: self.sig.ident.clone(),
|
||||||
start: false,
|
start: false,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
opts.check_used()?;
|
opts.check_used()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1071,6 +1077,7 @@ impl MacroParse<()> for syn::ItemEnum {
|
|||||||
variants,
|
variants,
|
||||||
comments,
|
comments,
|
||||||
hole,
|
hole,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -1175,6 +1182,7 @@ impl MacroParse<ast::ImportModule> for syn::ForeignItem {
|
|||||||
module,
|
module,
|
||||||
js_namespace,
|
js_namespace,
|
||||||
kind,
|
kind,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -94,6 +94,7 @@ macro_rules! shared_api {
|
|||||||
function: Function<'a>,
|
function: Function<'a>,
|
||||||
method_kind: MethodKind<'a>,
|
method_kind: MethodKind<'a>,
|
||||||
start: bool,
|
start: bool,
|
||||||
|
unstable_api: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Enum<'a> {
|
struct Enum<'a> {
|
||||||
|
@ -389,6 +389,105 @@ Geolocation = []
|
|||||||
GetNotificationOptions = []
|
GetNotificationOptions = []
|
||||||
GetRootNodeOptions = []
|
GetRootNodeOptions = []
|
||||||
GetUserMediaRequest = []
|
GetUserMediaRequest = []
|
||||||
|
Gpu = []
|
||||||
|
GpuAdapter = []
|
||||||
|
GpuAddressMode = []
|
||||||
|
GpuBindGroup = []
|
||||||
|
GpuBindGroupBinding = []
|
||||||
|
GpuBindGroupDescriptor = []
|
||||||
|
GpuBindGroupLayout = []
|
||||||
|
GpuBindGroupLayoutBinding = []
|
||||||
|
GpuBindGroupLayoutDescriptor = []
|
||||||
|
GpuBindingType = []
|
||||||
|
GpuBlendDescriptor = []
|
||||||
|
GpuBlendFactor = []
|
||||||
|
GpuBlendOperation = []
|
||||||
|
GpuBuffer = []
|
||||||
|
GpuBufferBinding = []
|
||||||
|
GpuBufferCopyView = []
|
||||||
|
GpuBufferDescriptor = []
|
||||||
|
GpuBufferUsage = []
|
||||||
|
GpuCanvasContext = []
|
||||||
|
GpuColorDict = []
|
||||||
|
GpuColorStateDescriptor = []
|
||||||
|
GpuColorWrite = []
|
||||||
|
GpuCommandBuffer = []
|
||||||
|
GpuCommandBufferDescriptor = []
|
||||||
|
GpuCommandEncoder = []
|
||||||
|
GpuCommandEncoderDescriptor = []
|
||||||
|
GpuCompareFunction = []
|
||||||
|
GpuComputePassDescriptor = []
|
||||||
|
GpuComputePassEncoder = []
|
||||||
|
GpuComputePipeline = []
|
||||||
|
GpuComputePipelineDescriptor = []
|
||||||
|
GpuCullMode = []
|
||||||
|
GpuDepthStencilStateDescriptor = []
|
||||||
|
GpuDevice = []
|
||||||
|
GpuDeviceDescriptor = []
|
||||||
|
GpuDeviceLostInfo = []
|
||||||
|
GpuErrorFilter = []
|
||||||
|
GpuExtensionName = []
|
||||||
|
GpuExtent3dDict = []
|
||||||
|
GpuFence = []
|
||||||
|
GpuFenceDescriptor = []
|
||||||
|
GpuFilterMode = []
|
||||||
|
GpuFrontFace = []
|
||||||
|
GpuImageBitmapCopyView = []
|
||||||
|
GpuIndexFormat = []
|
||||||
|
GpuInputStepMode = []
|
||||||
|
GpuLimits = []
|
||||||
|
GpuLoadOp = []
|
||||||
|
GpuObjectDescriptorBase = []
|
||||||
|
GpuOrigin2dDict = []
|
||||||
|
GpuOrigin3dDict = []
|
||||||
|
GpuOutOfMemoryError = []
|
||||||
|
GpuPipelineDescriptorBase = []
|
||||||
|
GpuPipelineLayout = []
|
||||||
|
GpuPipelineLayoutDescriptor = []
|
||||||
|
GpuPowerPreference = []
|
||||||
|
GpuPrimitiveTopology = []
|
||||||
|
GpuProgrammableStageDescriptor = []
|
||||||
|
GpuQueue = []
|
||||||
|
GpuRasterizationStateDescriptor = []
|
||||||
|
GpuRenderBundle = []
|
||||||
|
GpuRenderBundleDescriptor = []
|
||||||
|
GpuRenderBundleEncoder = []
|
||||||
|
GpuRenderBundleEncoderDescriptor = []
|
||||||
|
GpuRenderPassColorAttachmentDescriptor = []
|
||||||
|
GpuRenderPassDepthStencilAttachmentDescriptor = []
|
||||||
|
GpuRenderPassDescriptor = []
|
||||||
|
GpuRenderPassEncoder = []
|
||||||
|
GpuRenderPipeline = []
|
||||||
|
GpuRenderPipelineDescriptor = []
|
||||||
|
GpuRequestAdapterOptions = []
|
||||||
|
GpuSampler = []
|
||||||
|
GpuSamplerDescriptor = []
|
||||||
|
GpuShaderModule = []
|
||||||
|
GpuShaderModuleDescriptor = []
|
||||||
|
GpuShaderStage = []
|
||||||
|
GpuStencilOperation = []
|
||||||
|
GpuStencilStateFaceDescriptor = []
|
||||||
|
GpuStoreOp = []
|
||||||
|
GpuSwapChain = []
|
||||||
|
GpuSwapChainDescriptor = []
|
||||||
|
GpuTexture = []
|
||||||
|
GpuTextureAspect = []
|
||||||
|
GpuTextureComponentType = []
|
||||||
|
GpuTextureCopyView = []
|
||||||
|
GpuTextureDescriptor = []
|
||||||
|
GpuTextureDimension = []
|
||||||
|
GpuTextureFormat = []
|
||||||
|
GpuTextureUsage = []
|
||||||
|
GpuTextureView = []
|
||||||
|
GpuTextureViewDescriptor = []
|
||||||
|
GpuTextureViewDimension = []
|
||||||
|
GpuUncapturedErrorEvent = []
|
||||||
|
GpuUncapturedErrorEventInit = []
|
||||||
|
GpuValidationError = []
|
||||||
|
GpuVertexAttributeDescriptor = []
|
||||||
|
GpuVertexBufferLayoutDescriptor = []
|
||||||
|
GpuVertexFormat = []
|
||||||
|
GpuVertexStateDescriptor = []
|
||||||
GridDeclaration = []
|
GridDeclaration = []
|
||||||
GridTrackState = []
|
GridTrackState = []
|
||||||
GroupedHistoryEventInit = []
|
GroupedHistoryEventInit = []
|
||||||
|
@ -7,16 +7,12 @@ use std::fs;
|
|||||||
use std::path::{self, PathBuf};
|
use std::path::{self, PathBuf};
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
/// Read all WebIDL files in a directory into a single `SourceFile`
|
||||||
#[cfg(feature = "env_logger")]
|
fn read_source_from_path(dir: &str) -> Result<SourceFile> {
|
||||||
env_logger::init();
|
let entries = fs::read_dir(dir).context("reading webidls/enabled directory")?;
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
|
||||||
println!("cargo:rerun-if-changed=webidls/enabled");
|
|
||||||
|
|
||||||
let entries = fs::read_dir("webidls/enabled").context("reading webidls/enabled directory")?;
|
|
||||||
let mut source = SourceFile::default();
|
let mut source = SourceFile::default();
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
let entry = entry.context("getting webidls/enabled/*.webidl entry")?;
|
let entry = entry.context(format!("getting {}/*.webidl entry", dir))?;
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.extension() != Some(OsStr::new("webidl")) {
|
if path.extension() != Some(OsStr::new("webidl")) {
|
||||||
continue;
|
continue;
|
||||||
@ -27,6 +23,16 @@ fn main() -> Result<()> {
|
|||||||
.with_context(|| format!("reading contents of file \"{}\"", path.display()))?;
|
.with_context(|| format!("reading contents of file \"{}\"", path.display()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
#[cfg(feature = "env_logger")]
|
||||||
|
env_logger::init();
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rerun-if-changed=webidls/enabled");
|
||||||
|
println!("cargo:rerun-if-changed=webidls/unstable");
|
||||||
|
|
||||||
// Read our manifest, learn all `[feature]` directives with "toml parsing".
|
// Read our manifest, learn all `[feature]` directives with "toml parsing".
|
||||||
// Use all these names to match against environment variables set by Cargo
|
// Use all these names to match against environment variables set by Cargo
|
||||||
// to figure out which features are activated to we can pass that down to
|
// to figure out which features are activated to we can pass that down to
|
||||||
@ -63,7 +69,10 @@ fn main() -> Result<()> {
|
|||||||
Some(&allowed[..])
|
Some(&allowed[..])
|
||||||
};
|
};
|
||||||
|
|
||||||
let bindings = match wasm_bindgen_webidl::compile(&source.contents, allowed) {
|
let source = read_source_from_path("webidls/enabled")?;
|
||||||
|
let unstable_source = read_source_from_path("webidls/unstable")?;
|
||||||
|
|
||||||
|
let bindings = match wasm_bindgen_webidl::compile(&source.contents, &unstable_source.contents, allowed) {
|
||||||
Ok(bindings) => bindings,
|
Ok(bindings) => bindings,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(err) = e.downcast_ref::<wasm_bindgen_webidl::WebIDLParseError>() {
|
if let Some(err) = e.downcast_ref::<wasm_bindgen_webidl::WebIDLParseError>() {
|
||||||
|
638
crates/web-sys/webidls/disabled/WebGPU.webidl
vendored
638
crates/web-sys/webidls/disabled/WebGPU.webidl
vendored
@ -1,638 +0,0 @@
|
|||||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*
|
|
||||||
* The origin of this IDL file is
|
|
||||||
* https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef unsigned long u32;
|
|
||||||
typedef unsigned long long u64;
|
|
||||||
|
|
||||||
// ****************************************************************************
|
|
||||||
// ERROR HANDLING
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
enum WebGPULogEntryType {
|
|
||||||
"device-lost",
|
|
||||||
"validation-error",
|
|
||||||
"recoverable-out-of-memory",
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPULogEntry {
|
|
||||||
readonly attribute WebGPULogEntryType type;
|
|
||||||
readonly attribute any obj;
|
|
||||||
readonly attribute DOMString? reason;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum WebGPUObjectStatus {
|
|
||||||
"valid",
|
|
||||||
"out-of-memory",
|
|
||||||
"invalid",
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef (WebGPUBuffer or WebGPUTexture) WebGPUStatusable;
|
|
||||||
|
|
||||||
callback WebGPULogCallback = void (WebGPULogEntry error);
|
|
||||||
|
|
||||||
// ****************************************************************************
|
|
||||||
// SHADER RESOURCES (buffer, textures, texture views, samples)
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
// Buffer
|
|
||||||
typedef u32 WebGPUBufferUsageFlags;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBufferUsage {
|
|
||||||
const u32 NONE = 0;
|
|
||||||
const u32 MAP_READ = 1;
|
|
||||||
const u32 MAP_WRITE = 2;
|
|
||||||
const u32 TRANSFER_SRC = 4;
|
|
||||||
const u32 TRANSFER_DST = 8;
|
|
||||||
const u32 INDEX = 16;
|
|
||||||
const u32 VERTEX = 32;
|
|
||||||
const u32 UNIFORM = 64;
|
|
||||||
const u32 STORAGE = 128;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUBufferDescriptor {
|
|
||||||
u32 size;
|
|
||||||
WebGPUBufferUsageFlags usage;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBuffer {
|
|
||||||
readonly attribute ArrayBuffer? mapping;
|
|
||||||
void unmap();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Texture view
|
|
||||||
dictionary WebGPUTextureViewDescriptor {
|
|
||||||
// TODO Investigate what goes in there.
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUTextureView {
|
|
||||||
};
|
|
||||||
|
|
||||||
// Texture
|
|
||||||
typedef u32 WebGPUTextureDimensionEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUTextureDimension {
|
|
||||||
const u32 e1D = 0;
|
|
||||||
const u32 e2D = 1;
|
|
||||||
const u32 e3D = 2;
|
|
||||||
// TODO other dimensions (cube, arrays)
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUTextureFormatEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUTextureFormat {
|
|
||||||
const u32 R8_G8_B8_A8_UNORM = 0;
|
|
||||||
const u32 R8_G8_B8_A8_UINT = 1;
|
|
||||||
const u32 B8_G8_R8_A8_UNORM = 2;
|
|
||||||
const u32 D32_FLOAT_S8_UINT = 3;
|
|
||||||
// TODO other formats
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUTextureUsageFlags;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUTextureUsage {
|
|
||||||
const u32 NONE = 0;
|
|
||||||
const u32 TRANSFER_SRC = 1;
|
|
||||||
const u32 TRANSFER_DST = 2;
|
|
||||||
const u32 SAMPLED = 4;
|
|
||||||
const u32 STORAGE = 8;
|
|
||||||
const u32 OUTPUT_ATTACHMENT = 16;
|
|
||||||
const u32 PRESENT = 32;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUTextureDescriptor {
|
|
||||||
u32 width;
|
|
||||||
u32 height;
|
|
||||||
u32 depth;
|
|
||||||
u32 arraySize;
|
|
||||||
WebGPUTextureDimensionEnum dimension;
|
|
||||||
WebGPUTextureFormatEnum format;
|
|
||||||
WebGPUTextureUsageFlags usage;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUTexture {
|
|
||||||
WebGPUTextureView createTextureView(optional WebGPUTextureViewDescriptor desc);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Sampler
|
|
||||||
typedef u32 WebGPUFilterModeEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUFilterMode {
|
|
||||||
const u32 NEAREST = 0;
|
|
||||||
const u32 LINEAR = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUSamplerDescriptor {
|
|
||||||
WebGPUFilterModeEnum magFilter;
|
|
||||||
WebGPUFilterModeEnum minFilter;
|
|
||||||
WebGPUFilterModeEnum mipmapFilter;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUSampler {
|
|
||||||
};
|
|
||||||
|
|
||||||
// ****************************************************************************
|
|
||||||
// BINDING MODEL (bindgroup layout, bindgroup)
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
// BindGroupLayout
|
|
||||||
typedef u32 WebGPUShaderStageFlags;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUShaderStageBit {
|
|
||||||
const u32 NONE = 0;
|
|
||||||
const u32 VERTEX = 1;
|
|
||||||
const u32 FRAGMENT = 2;
|
|
||||||
const u32 COMPUTE = 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUBindingTypeEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBindingType {
|
|
||||||
const u32 UNIFORM_BUFFER = 0;
|
|
||||||
const u32 SAMPLER = 1;
|
|
||||||
const u32 SAMPLED_TEXTURE = 2;
|
|
||||||
const u32 STORAGE_BUFFER = 3;
|
|
||||||
// TODO other binding types (storage images, ...)
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUBindGroupBinding {
|
|
||||||
WebGPUShaderStageFlags visibility;
|
|
||||||
WebGPUBindingTypeEnum type;
|
|
||||||
u32 start;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUBindGroupLayoutDescriptor {
|
|
||||||
sequence<WebGPUBindGroupBinding> bindingTypes;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBindGroupLayout {
|
|
||||||
};
|
|
||||||
|
|
||||||
// PipelineLayout
|
|
||||||
dictionary WebGPUPipelineLayoutDescriptor {
|
|
||||||
sequence<WebGPUBindGroupLayout> bindGroupLayouts;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUPipelineLayout {
|
|
||||||
};
|
|
||||||
|
|
||||||
// BindGroup
|
|
||||||
/* Moved to WebGPUExtras.webidl for now.
|
|
||||||
dictionary WebGPUBufferBinding {
|
|
||||||
WebGPUBuffer buffer;
|
|
||||||
u32 offset;
|
|
||||||
u32 size;
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef (WebGPUSampler or WebGPUTextureView or WebGPUBufferBinding) WebGPUBindingResource;
|
|
||||||
|
|
||||||
dictionary WebGPUBinding {
|
|
||||||
sequence<WebGPUBindingResource> resources;
|
|
||||||
u32 start;
|
|
||||||
u32 count;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUBindGroupDescriptor {
|
|
||||||
WebGPUBindGroupLayout layout;
|
|
||||||
sequence<WebGPUBinding> bindings;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBindGroup {
|
|
||||||
};
|
|
||||||
|
|
||||||
// ****************************************************************************
|
|
||||||
// PIPELINE CREATION (blend state, DS state, ..., pipelines)
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
// BlendState
|
|
||||||
typedef u32 WebGPUBlendFactorEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBlendFactor {
|
|
||||||
const u32 ZERO = 0;
|
|
||||||
const u32 ONE = 1;
|
|
||||||
const u32 SRC_COLOR = 2;
|
|
||||||
const u32 ONE_MINUS_SRC_COLOR = 3;
|
|
||||||
const u32 SRC_ALPHA = 4;
|
|
||||||
const u32 ONE_MINUS_SRC_ALPHA = 5;
|
|
||||||
const u32 DST_COLOR = 6;
|
|
||||||
const u32 ONE_MINUS_DST_COLOR = 7;
|
|
||||||
const u32 DST_ALPHA = 8;
|
|
||||||
const u32 ONE_MINUS_DST_ALPHA = 9;
|
|
||||||
const u32 SRC_ALPHA_SATURATED = 10;
|
|
||||||
const u32 BLEND_COLOR = 11;
|
|
||||||
const u32 ONE_MINUS_BLEND_COLOR = 12;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUBlendOperationEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBlendOperation {
|
|
||||||
const u32 ADD = 0;
|
|
||||||
const u32 SUBTRACT = 1;
|
|
||||||
const u32 REVERSE_SUBTRACT = 2;
|
|
||||||
const u32 MIN = 3;
|
|
||||||
const u32 MAX = 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUColorWriteFlags;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUColorWriteBits {
|
|
||||||
const u32 NONE = 0;
|
|
||||||
const u32 RED = 1;
|
|
||||||
const u32 GREEN = 2;
|
|
||||||
const u32 BLUE = 4;
|
|
||||||
const u32 ALPHA = 8;
|
|
||||||
const u32 ALL = 15;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUBlendDescriptor {
|
|
||||||
WebGPUBlendFactorEnum srcFactor;
|
|
||||||
WebGPUBlendFactorEnum dstFactor;
|
|
||||||
WebGPUBlendOperationEnum operation;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUBlendStateDescriptor {
|
|
||||||
boolean blendEnabled;
|
|
||||||
WebGPUBlendDescriptor alpha;
|
|
||||||
WebGPUBlendDescriptor color;
|
|
||||||
WebGPUColorWriteFlags writeMask;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUBlendState {
|
|
||||||
};
|
|
||||||
|
|
||||||
// DepthStencilState
|
|
||||||
typedef u32 WebGPUCompareFunctionEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUCompareFunction {
|
|
||||||
const u32 NEVER = 0;
|
|
||||||
const u32 LESS = 1;
|
|
||||||
const u32 LESS_EQUAL = 2;
|
|
||||||
const u32 GREATER = 3;
|
|
||||||
const u32 GREATER_EQUAL = 4;
|
|
||||||
const u32 EQUAL = 5;
|
|
||||||
const u32 NOT_EQUAL = 6;
|
|
||||||
const u32 ALWAYS = 7;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUStencilOperationEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUStencilOperation {
|
|
||||||
const u32 KEEP = 0;
|
|
||||||
const u32 ZERO = 1;
|
|
||||||
const u32 REPLACE = 2;
|
|
||||||
const u32 INVERT = 3;
|
|
||||||
const u32 INCREMENT_CLAMP = 4;
|
|
||||||
const u32 DECREMENT_CLAMP = 5;
|
|
||||||
const u32 INCREMENT_WRAP = 6;
|
|
||||||
const u32 DECREMENT_WRAP = 7;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUStencilStateFaceDescriptor {
|
|
||||||
WebGPUCompareFunctionEnum compare;
|
|
||||||
WebGPUStencilOperationEnum stencilFailOp;
|
|
||||||
WebGPUStencilOperationEnum depthFailOp;
|
|
||||||
WebGPUStencilOperationEnum passOp;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUDepthStencilStateDescriptor {
|
|
||||||
boolean depthWriteEnabled;
|
|
||||||
WebGPUCompareFunctionEnum depthCompare;
|
|
||||||
|
|
||||||
WebGPUStencilStateFaceDescriptor front;
|
|
||||||
WebGPUStencilStateFaceDescriptor back;
|
|
||||||
|
|
||||||
u32 stencilReadMask;
|
|
||||||
u32 stencilWriteMask;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUDepthStencilState {
|
|
||||||
};
|
|
||||||
|
|
||||||
// InputState
|
|
||||||
typedef u32 WebGPUIndexFormatEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUIndexFormat {
|
|
||||||
const u32 UINT16 = 0;
|
|
||||||
const u32 UINT32 = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUVertexFormatEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUVertexFormat {
|
|
||||||
const u32 FLOAT_R32_G32_B32_A32 = 0;
|
|
||||||
const u32 FLOAT_R32_G32_B32 = 1;
|
|
||||||
const u32 FLOAT_R32_G32 = 2;
|
|
||||||
const u32 FLOAT_R32 = 3;
|
|
||||||
// TODO other vertex formats
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUInputStepModeEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUInputStepMode {
|
|
||||||
const u32 VERTEX = 0;
|
|
||||||
const u32 INSTANCE = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUVertexAttributeDescriptor {
|
|
||||||
u32 shaderLocation;
|
|
||||||
u32 inputSlot;
|
|
||||||
u32 offset;
|
|
||||||
WebGPUVertexFormatEnum format;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUVertexInputDescriptor {
|
|
||||||
u32 inputSlot;
|
|
||||||
u32 stride;
|
|
||||||
WebGPUInputStepModeEnum stepMode;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUInputStateDescriptor {
|
|
||||||
WebGPUIndexFormatEnum indexFormat;
|
|
||||||
|
|
||||||
sequence<WebGPUVertexAttributeDescriptor> attributes;
|
|
||||||
sequence<WebGPUVertexInputDescriptor> inputs;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUInputState {
|
|
||||||
};
|
|
||||||
|
|
||||||
// ShaderModule
|
|
||||||
dictionary WebGPUShaderModuleDescriptor {
|
|
||||||
required ArrayBuffer code;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUShaderModule {
|
|
||||||
};
|
|
||||||
|
|
||||||
// AttachmentState
|
|
||||||
dictionary WebGPUAttachmentStateDescriptor {
|
|
||||||
sequence<WebGPUTextureFormatEnum> formats;
|
|
||||||
// TODO other stuff like sample count etc.
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUAttachmentState {
|
|
||||||
};
|
|
||||||
|
|
||||||
// Common stuff for ComputePipeline and RenderPipeline
|
|
||||||
typedef u32 WebGPUShaderStageEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUShaderStage {
|
|
||||||
const u32 VERTEX = 0;
|
|
||||||
const u32 FRAGMENT = 1;
|
|
||||||
const u32 COMPUTE = 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUPipelineStageDescriptor {
|
|
||||||
required WebGPUShaderModule shaderModule;
|
|
||||||
required WebGPUShaderStageEnum stage;
|
|
||||||
required DOMString entryPoint;
|
|
||||||
// TODO other stuff like specialization constants?
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUPipelineDescriptorBase {
|
|
||||||
required WebGPUPipelineLayout layout;
|
|
||||||
sequence<WebGPUPipelineStageDescriptor> stages;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ComputePipeline
|
|
||||||
dictionary WebGPUComputePipelineDescriptor : WebGPUPipelineDescriptorBase {
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUComputePipeline {
|
|
||||||
};
|
|
||||||
|
|
||||||
// WebGPURenderPipeline
|
|
||||||
typedef u32 WebGPUPrimitiveTopologyEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUPrimitiveTopology {
|
|
||||||
const u32 POINT_LIST = 0;
|
|
||||||
const u32 LINE_LIST = 1;
|
|
||||||
const u32 LINE_STRIP = 2;
|
|
||||||
const u32 TRIANGLE_LIST = 3;
|
|
||||||
const u32 TRIANGLE_STRIP = 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPURenderPipelineDescriptor : WebGPUPipelineDescriptorBase {
|
|
||||||
WebGPUPrimitiveTopologyEnum primitiveTopology;
|
|
||||||
sequence<WebGPUBlendState> blendState;
|
|
||||||
WebGPUDepthStencilState depthStencilState;
|
|
||||||
WebGPUInputState inputState;
|
|
||||||
WebGPUAttachmentState attachmentState;
|
|
||||||
// TODO other properties
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPURenderPipeline {
|
|
||||||
};
|
|
||||||
// ****************************************************************************
|
|
||||||
// COMMAND RECORDING (Command buffer and all relevant structures)
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
typedef u32 WebGPULoadOpEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPULoadOp {
|
|
||||||
const u32 CLEAR = 0;
|
|
||||||
const u32 LOAD = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef u32 WebGPUStoreOpEnum;
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUStoreOp {
|
|
||||||
const u32 STORE = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPURenderPassAttachmentDescriptor {
|
|
||||||
WebGPUTextureView attachment;
|
|
||||||
WebGPULoadOpEnum loadOp;
|
|
||||||
WebGPUStoreOpEnum storeOp;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPURenderPassDescriptor {
|
|
||||||
sequence<WebGPURenderPassAttachmentDescriptor> colorAttachments;
|
|
||||||
WebGPURenderPassAttachmentDescriptor depthStencilAttachment;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUCommandBuffer {
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUCommandEncoderDescriptor {
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUCommandEncoder {
|
|
||||||
WebGPUCommandBuffer finishEncoding();
|
|
||||||
|
|
||||||
// Commands allowed outside of "passes"
|
|
||||||
void copyBufferToBuffer(WebGPUBuffer src,
|
|
||||||
u32 srcOffset,
|
|
||||||
WebGPUBuffer dst,
|
|
||||||
u32 dstOffset,
|
|
||||||
u32 size);
|
|
||||||
// TODO figure out all the arguments required for these
|
|
||||||
void copyBufferToTexture();
|
|
||||||
void copyTextureToBuffer();
|
|
||||||
void copyTextureToTexture();
|
|
||||||
void blit();
|
|
||||||
|
|
||||||
void transitionBuffer(WebGPUBuffer b, WebGPUBufferUsageFlags f);
|
|
||||||
|
|
||||||
// Allowed in both compute and render passes
|
|
||||||
void setPushConstants(WebGPUShaderStageFlags stage,
|
|
||||||
u32 offset,
|
|
||||||
u32 count,
|
|
||||||
ArrayBuffer data);
|
|
||||||
void setBindGroup(u32 index, WebGPUBindGroup bindGroup);
|
|
||||||
void setPipeline((WebGPUComputePipeline or WebGPURenderPipeline) pipeline);
|
|
||||||
|
|
||||||
// Compute pass commands
|
|
||||||
void beginComputePass();
|
|
||||||
void endComputePass();
|
|
||||||
|
|
||||||
void dispatch(u32 x, u32 y, u32 z);
|
|
||||||
|
|
||||||
// Render pass commands
|
|
||||||
void beginRenderPass(optional WebGPURenderPassDescriptor descriptor);
|
|
||||||
void endRenderPass();
|
|
||||||
|
|
||||||
void setBlendColor(float r, float g, float b, float a);
|
|
||||||
void setIndexBuffer(WebGPUBuffer buffer, u32 offset);
|
|
||||||
void setVertexBuffers(u32 startSlot, sequence<WebGPUBuffer> buffers, sequence<u32> offsets);
|
|
||||||
|
|
||||||
void draw(u32 vertexCount, u32 instanceCount, u32 firstVertex, u32 firstInstance);
|
|
||||||
void drawIndexed(u32 indexCount, u32 instanceCount, u32 firstIndex, u32 firstInstance, u32 firstVertex);
|
|
||||||
|
|
||||||
// TODO add missing commands
|
|
||||||
};
|
|
||||||
|
|
||||||
// ****************************************************************************
|
|
||||||
// OTHER (Fence, Queue SwapChain, Device)
|
|
||||||
// ****************************************************************************
|
|
||||||
|
|
||||||
// Fence
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUFence {
|
|
||||||
boolean wait(double milliseconds);
|
|
||||||
readonly attribute Promise<void> promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Queue
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUQueue {
|
|
||||||
void submit(sequence<WebGPUCommandBuffer> buffers);
|
|
||||||
WebGPUFence insertFence();
|
|
||||||
};
|
|
||||||
|
|
||||||
// SwapChain / RenderingContext
|
|
||||||
dictionary WebGPUSwapChainDescriptor {
|
|
||||||
WebGPUTextureUsageFlags usage;
|
|
||||||
WebGPUTextureFormatEnum format;
|
|
||||||
u32 width;
|
|
||||||
u32 height;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUSwapChain {
|
|
||||||
void configure(optional WebGPUSwapChainDescriptor descriptor);
|
|
||||||
WebGPUTexture getNextTexture();
|
|
||||||
void present();
|
|
||||||
};
|
|
||||||
|
|
||||||
//[Pref="dom.webgpu.enable"]
|
|
||||||
//interface WebGPURenderingContext : WebGPUSwapChain {
|
|
||||||
//};
|
|
||||||
|
|
||||||
// WebGPU "namespace" used for device creation
|
|
||||||
dictionary WebGPUExtensions {
|
|
||||||
boolean anisotropicFiltering;
|
|
||||||
boolean logicOp; // Previously a "Feature".
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPULimits {
|
|
||||||
u32 maxBindGroups;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Device
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUDevice {
|
|
||||||
readonly attribute WebGPUAdapter adapter;
|
|
||||||
WebGPUExtensions extensions();
|
|
||||||
WebGPULimits limits();
|
|
||||||
|
|
||||||
WebGPUBuffer createBuffer(optional WebGPUBufferDescriptor descriptor);
|
|
||||||
WebGPUTexture createTexture(optional WebGPUTextureDescriptor descriptor);
|
|
||||||
WebGPUSampler createSampler(optional WebGPUSamplerDescriptor descriptor);
|
|
||||||
|
|
||||||
WebGPUBindGroupLayout createBindGroupLayout(optional WebGPUBindGroupLayoutDescriptor descriptor);
|
|
||||||
WebGPUPipelineLayout createPipelineLayout(optional WebGPUPipelineLayoutDescriptor descriptor);
|
|
||||||
WebGPUBindGroup createBindGroup(optional WebGPUBindGroupDescriptor descriptor);
|
|
||||||
|
|
||||||
WebGPUBlendState createBlendState(optional WebGPUBlendStateDescriptor descriptor);
|
|
||||||
WebGPUDepthStencilState createDepthStencilState(optional WebGPUDepthStencilStateDescriptor descriptor);
|
|
||||||
WebGPUInputState createInputState(optional WebGPUInputStateDescriptor descriptor);
|
|
||||||
WebGPUShaderModule createShaderModule(WebGPUShaderModuleDescriptor descriptor);
|
|
||||||
WebGPUAttachmentState createAttachmentState(optional WebGPUAttachmentStateDescriptor descriptor);
|
|
||||||
WebGPUComputePipeline createComputePipeline(WebGPUComputePipelineDescriptor descriptor);
|
|
||||||
WebGPURenderPipeline createRenderPipeline(WebGPURenderPipelineDescriptor descriptor);
|
|
||||||
|
|
||||||
WebGPUCommandEncoder createCommandEncoder(optional WebGPUCommandEncoderDescriptor descriptor);
|
|
||||||
|
|
||||||
WebGPUQueue getQueue();
|
|
||||||
|
|
||||||
attribute WebGPULogCallback onLog;
|
|
||||||
Promise<WebGPUObjectStatus> getObjectStatus(WebGPUStatusable obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary WebGPUDeviceDescriptor {
|
|
||||||
WebGPUExtensions extensions;
|
|
||||||
//WebGPULimits limits; Don't expose higher limits for now.
|
|
||||||
|
|
||||||
// TODO are other things configurable like queues?
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPUAdapter {
|
|
||||||
readonly attribute DOMString name;
|
|
||||||
WebGPUExtensions extensions();
|
|
||||||
//WebGPULimits limits(); Don't expose higher limits for now.
|
|
||||||
|
|
||||||
WebGPUDevice createDevice(optional WebGPUDeviceDescriptor descriptor);
|
|
||||||
};
|
|
||||||
|
|
||||||
enum WebGPUPowerPreference { "default", "low-power", "high-performance" };
|
|
||||||
|
|
||||||
dictionary WebGPUAdapterDescriptor {
|
|
||||||
WebGPUPowerPreference powerPreference;
|
|
||||||
};
|
|
||||||
|
|
||||||
[Pref="dom.webgpu.enable"]
|
|
||||||
interface WebGPU {
|
|
||||||
WebGPUAdapter getAdapter(optional WebGPUAdapterDescriptor desc);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add a "webgpu" member to Window that contains the global instance of a "WebGPU"
|
|
||||||
interface mixin WebGPUProvider {
|
|
||||||
[SameObject, Replaceable, Pref="dom.webgpu.enable"] readonly attribute WebGPU webgpu;
|
|
||||||
};
|
|
||||||
//Window includes WebGPUProvider;
|
|
@ -1,14 +0,0 @@
|
|||||||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*
|
|
||||||
* Some parts of WebGPU.webidl need to be pulled into a different file due to a codegen
|
|
||||||
* bug/missing support.
|
|
||||||
*/
|
|
||||||
|
|
||||||
dictionary WebGPUBufferBinding {
|
|
||||||
WebGPUBuffer buffer;
|
|
||||||
u32 offset;
|
|
||||||
u32 size;
|
|
||||||
};
|
|
2
crates/web-sys/webidls/enabled/Window.webidl
vendored
2
crates/web-sys/webidls/enabled/Window.webidl
vendored
@ -272,5 +272,3 @@ dictionary IdleRequestOptions {
|
|||||||
};
|
};
|
||||||
|
|
||||||
callback IdleRequestCallback = void (IdleDeadline deadline);
|
callback IdleRequestCallback = void (IdleDeadline deadline);
|
||||||
|
|
||||||
//Window includes WebGPUProvider;
|
|
||||||
|
864
crates/web-sys/webidls/unstable/WebGPU.webidl
vendored
Normal file
864
crates/web-sys/webidls/unstable/WebGPU.webidl
vendored
Normal file
@ -0,0 +1,864 @@
|
|||||||
|
interface mixin GPUObjectBase {
|
||||||
|
attribute DOMString? label;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUObjectDescriptorBase {
|
||||||
|
DOMString label;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=Window]
|
||||||
|
partial interface Navigator {
|
||||||
|
[SameObject] readonly attribute GPU gpu;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=DedicatedWorker]
|
||||||
|
partial interface WorkerNavigator {
|
||||||
|
[SameObject] readonly attribute GPU gpu;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=(Window, DedicatedWorker)]
|
||||||
|
interface GPU {
|
||||||
|
Promise<GPUAdapter> requestAdapter(optional GPURequestAdapterOptions options = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPURequestAdapterOptions {
|
||||||
|
GPUPowerPreference powerPreference;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUPowerPreference {
|
||||||
|
"low-power",
|
||||||
|
"high-performance"
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUAdapter {
|
||||||
|
readonly attribute DOMString name;
|
||||||
|
readonly attribute FrozenArray<GPUExtensionName> extensions;
|
||||||
|
//readonly attribute GPULimits limits; Don’t expose higher limits for now.
|
||||||
|
|
||||||
|
Promise<GPUDevice> requestDevice(optional GPUDeviceDescriptor descriptor = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUDeviceDescriptor : GPUObjectDescriptorBase {
|
||||||
|
sequence<GPUExtensionName> extensions = [];
|
||||||
|
GPULimits limits = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUExtensionName {
|
||||||
|
"texture-compression-bc"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPULimits {
|
||||||
|
GPUSize32 maxBindGroups = 4;
|
||||||
|
GPUSize32 maxDynamicUniformBuffersPerPipelineLayout = 8;
|
||||||
|
GPUSize32 maxDynamicStorageBuffersPerPipelineLayout = 4;
|
||||||
|
GPUSize32 maxSampledTexturesPerShaderStage = 16;
|
||||||
|
GPUSize32 maxSamplersPerShaderStage = 16;
|
||||||
|
GPUSize32 maxStorageBuffersPerShaderStage = 4;
|
||||||
|
GPUSize32 maxStorageTexturesPerShaderStage = 4;
|
||||||
|
GPUSize32 maxUniformBuffersPerShaderStage = 12;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Exposed=(Window, DedicatedWorker), Serializable]
|
||||||
|
interface GPUDevice : EventTarget {
|
||||||
|
[SameObject] readonly attribute GPUAdapter adapter;
|
||||||
|
readonly attribute FrozenArray<GPUExtensionName> extensions;
|
||||||
|
readonly attribute object limits;
|
||||||
|
|
||||||
|
[SameObject] readonly attribute GPUQueue defaultQueue;
|
||||||
|
|
||||||
|
GPUBuffer createBuffer(GPUBufferDescriptor descriptor);
|
||||||
|
GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
|
||||||
|
GPUTexture createTexture(GPUTextureDescriptor descriptor);
|
||||||
|
GPUSampler createSampler(optional GPUSamplerDescriptor descriptor = {});
|
||||||
|
|
||||||
|
GPUBindGroupLayout createBindGroupLayout(GPUBindGroupLayoutDescriptor descriptor);
|
||||||
|
GPUPipelineLayout createPipelineLayout(GPUPipelineLayoutDescriptor descriptor);
|
||||||
|
GPUBindGroup createBindGroup(GPUBindGroupDescriptor descriptor);
|
||||||
|
|
||||||
|
GPUShaderModule createShaderModule(GPUShaderModuleDescriptor descriptor);
|
||||||
|
GPUComputePipeline createComputePipeline(GPUComputePipelineDescriptor descriptor);
|
||||||
|
GPURenderPipeline createRenderPipeline(GPURenderPipelineDescriptor descriptor);
|
||||||
|
|
||||||
|
GPUCommandEncoder createCommandEncoder(optional GPUCommandEncoderDescriptor descriptor = {});
|
||||||
|
GPURenderBundleEncoder createRenderBundleEncoder(GPURenderBundleEncoderDescriptor descriptor);
|
||||||
|
};
|
||||||
|
GPUDevice includes GPUObjectBase;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
interface GPUBuffer {
|
||||||
|
Promise<ArrayBuffer> mapReadAsync();
|
||||||
|
Promise<ArrayBuffer> mapWriteAsync();
|
||||||
|
void unmap();
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
};
|
||||||
|
GPUBuffer includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUBufferDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required GPUSize64 size;
|
||||||
|
required GPUBufferUsageFlags usage;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef [EnforceRange] unsigned long GPUBufferUsageFlags;
|
||||||
|
interface GPUBufferUsage {
|
||||||
|
const GPUBufferUsageFlags MAP_READ = 0x0001;
|
||||||
|
const GPUBufferUsageFlags MAP_WRITE = 0x0002;
|
||||||
|
const GPUBufferUsageFlags COPY_SRC = 0x0004;
|
||||||
|
const GPUBufferUsageFlags COPY_DST = 0x0008;
|
||||||
|
const GPUBufferUsageFlags INDEX = 0x0010;
|
||||||
|
const GPUBufferUsageFlags VERTEX = 0x0020;
|
||||||
|
const GPUBufferUsageFlags UNIFORM = 0x0040;
|
||||||
|
const GPUBufferUsageFlags STORAGE = 0x0080;
|
||||||
|
const GPUBufferUsageFlags INDIRECT = 0x0100;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
interface GPUTexture {
|
||||||
|
GPUTextureView createView(optional GPUTextureViewDescriptor descriptor = {});
|
||||||
|
|
||||||
|
void destroy();
|
||||||
|
};
|
||||||
|
GPUTexture includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUTextureDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required GPUExtent3D size;
|
||||||
|
GPUIntegerCoordinate arrayLayerCount = 1;
|
||||||
|
GPUIntegerCoordinate mipLevelCount = 1;
|
||||||
|
GPUSize32 sampleCount = 1;
|
||||||
|
GPUTextureDimension dimension = "2d";
|
||||||
|
required GPUTextureFormat format;
|
||||||
|
required GPUTextureUsageFlags usage;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUTextureDimension {
|
||||||
|
"1d",
|
||||||
|
"2d",
|
||||||
|
"3d"
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef [EnforceRange] unsigned long GPUTextureUsageFlags;
|
||||||
|
interface GPUTextureUsage {
|
||||||
|
const GPUTextureUsageFlags COPY_SRC = 0x01;
|
||||||
|
const GPUTextureUsageFlags COPY_DST = 0x02;
|
||||||
|
const GPUTextureUsageFlags SAMPLED = 0x04;
|
||||||
|
const GPUTextureUsageFlags STORAGE = 0x08;
|
||||||
|
const GPUTextureUsageFlags OUTPUT_ATTACHMENT = 0x10;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUTextureView {
|
||||||
|
};
|
||||||
|
GPUTextureView includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUTextureViewDescriptor : GPUObjectDescriptorBase {
|
||||||
|
GPUTextureFormat format;
|
||||||
|
GPUTextureViewDimension dimension;
|
||||||
|
GPUTextureAspect aspect = "all";
|
||||||
|
GPUIntegerCoordinate baseMipLevel = 0;
|
||||||
|
GPUIntegerCoordinate mipLevelCount = 0;
|
||||||
|
GPUIntegerCoordinate baseArrayLayer = 0;
|
||||||
|
GPUIntegerCoordinate arrayLayerCount = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUTextureViewDimension {
|
||||||
|
"1d",
|
||||||
|
"2d",
|
||||||
|
"2d-array",
|
||||||
|
"cube",
|
||||||
|
"cube-array",
|
||||||
|
"3d"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUTextureAspect {
|
||||||
|
"all",
|
||||||
|
"stencil-only",
|
||||||
|
"depth-only"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUTextureFormat {
|
||||||
|
// 8-bit formats
|
||||||
|
"r8unorm",
|
||||||
|
"r8snorm",
|
||||||
|
"r8uint",
|
||||||
|
"r8sint",
|
||||||
|
|
||||||
|
// 16-bit formats
|
||||||
|
"r16uint",
|
||||||
|
"r16sint",
|
||||||
|
"r16float",
|
||||||
|
"rg8unorm",
|
||||||
|
"rg8snorm",
|
||||||
|
"rg8uint",
|
||||||
|
"rg8sint",
|
||||||
|
|
||||||
|
// 32-bit formats
|
||||||
|
"r32uint",
|
||||||
|
"r32sint",
|
||||||
|
"r32float",
|
||||||
|
"rg16uint",
|
||||||
|
"rg16sint",
|
||||||
|
"rg16float",
|
||||||
|
"rgba8unorm",
|
||||||
|
"rgba8unorm-srgb",
|
||||||
|
"rgba8snorm",
|
||||||
|
"rgba8uint",
|
||||||
|
"rgba8sint",
|
||||||
|
"bgra8unorm",
|
||||||
|
"bgra8unorm-srgb",
|
||||||
|
// Packed 32-bit formats
|
||||||
|
"rgb10a2unorm",
|
||||||
|
"rg11b10float",
|
||||||
|
|
||||||
|
// 64-bit formats
|
||||||
|
"rg32uint",
|
||||||
|
"rg32sint",
|
||||||
|
"rg32float",
|
||||||
|
"rgba16uint",
|
||||||
|
"rgba16sint",
|
||||||
|
"rgba16float",
|
||||||
|
|
||||||
|
// 128-bit formats
|
||||||
|
"rgba32uint",
|
||||||
|
"rgba32sint",
|
||||||
|
"rgba32float",
|
||||||
|
|
||||||
|
// Depth and stencil formats
|
||||||
|
"depth32float",
|
||||||
|
"depth24plus",
|
||||||
|
"depth24plus-stencil8"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUTextureComponentType {
|
||||||
|
"float",
|
||||||
|
"sint",
|
||||||
|
"uint"
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUSampler {
|
||||||
|
};
|
||||||
|
GPUSampler includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUSamplerDescriptor : GPUObjectDescriptorBase {
|
||||||
|
GPUAddressMode addressModeU = "clamp-to-edge";
|
||||||
|
GPUAddressMode addressModeV = "clamp-to-edge";
|
||||||
|
GPUAddressMode addressModeW = "clamp-to-edge";
|
||||||
|
GPUFilterMode magFilter = "nearest";
|
||||||
|
GPUFilterMode minFilter = "nearest";
|
||||||
|
GPUFilterMode mipmapFilter = "nearest";
|
||||||
|
float lodMinClamp = 0;
|
||||||
|
float lodMaxClamp = 0xffffffff; // TODO: What should this be? Was Number.MAX_VALUE.
|
||||||
|
GPUCompareFunction compare = "never";
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUAddressMode {
|
||||||
|
"clamp-to-edge",
|
||||||
|
"repeat",
|
||||||
|
"mirror-repeat"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUFilterMode {
|
||||||
|
"nearest",
|
||||||
|
"linear"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUCompareFunction {
|
||||||
|
"never",
|
||||||
|
"less",
|
||||||
|
"equal",
|
||||||
|
"less-equal",
|
||||||
|
"greater",
|
||||||
|
"not-equal",
|
||||||
|
"greater-equal",
|
||||||
|
"always"
|
||||||
|
};
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
interface GPUBindGroupLayout {
|
||||||
|
};
|
||||||
|
GPUBindGroupLayout includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUBindGroupLayoutDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required sequence<GPUBindGroupLayoutBinding> bindings;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUBindGroupLayoutBinding {
|
||||||
|
required GPUIndex32 binding;
|
||||||
|
required GPUShaderStageFlags visibility;
|
||||||
|
required GPUBindingType type;
|
||||||
|
GPUTextureViewDimension textureDimension = "2d";
|
||||||
|
GPUTextureComponentType textureComponentType = "float";
|
||||||
|
boolean multisampled = false;
|
||||||
|
boolean hasDynamicOffset = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef [EnforceRange] unsigned long GPUShaderStageFlags;
|
||||||
|
interface GPUShaderStage {
|
||||||
|
const GPUShaderStageFlags VERTEX = 0x1;
|
||||||
|
const GPUShaderStageFlags FRAGMENT = 0x2;
|
||||||
|
const GPUShaderStageFlags COMPUTE = 0x4;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUBindingType {
|
||||||
|
"uniform-buffer",
|
||||||
|
"storage-buffer",
|
||||||
|
"readonly-storage-buffer",
|
||||||
|
"sampler",
|
||||||
|
"sampled-texture",
|
||||||
|
"storage-texture"
|
||||||
|
// TODO: other binding types
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUBindGroup {
|
||||||
|
};
|
||||||
|
GPUBindGroup includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUBindGroupDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required GPUBindGroupLayout layout;
|
||||||
|
required sequence<GPUBindGroupBinding> bindings;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef (GPUSampler or GPUTextureView or GPUBufferBinding) GPUBindingResource;
|
||||||
|
|
||||||
|
dictionary GPUBindGroupBinding {
|
||||||
|
required GPUIndex32 binding;
|
||||||
|
required GPUBindingResource resource;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUBufferBinding {
|
||||||
|
required GPUBuffer buffer;
|
||||||
|
GPUSize64 offset = 0;
|
||||||
|
GPUSize64 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUPipelineLayout {
|
||||||
|
};
|
||||||
|
GPUPipelineLayout includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUPipelineLayoutDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required sequence<GPUBindGroupLayout> bindGroupLayouts;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
interface GPUShaderModule {
|
||||||
|
};
|
||||||
|
GPUShaderModule includes GPUObjectBase;
|
||||||
|
|
||||||
|
typedef (Uint32Array or DOMString) GPUShaderCode;
|
||||||
|
|
||||||
|
dictionary GPUShaderModuleDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required GPUShaderCode code;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
|
||||||
|
required GPUPipelineLayout layout;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUProgrammableStageDescriptor {
|
||||||
|
required GPUShaderModule module;
|
||||||
|
required DOMString entryPoint;
|
||||||
|
// TODO: other stuff like specialization constants?
|
||||||
|
};
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
interface GPUComputePipeline {
|
||||||
|
};
|
||||||
|
GPUComputePipeline includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase {
|
||||||
|
required GPUProgrammableStageDescriptor computeStage;
|
||||||
|
};
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
interface GPURenderPipeline {
|
||||||
|
};
|
||||||
|
GPURenderPipeline includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
|
||||||
|
required GPUProgrammableStageDescriptor vertexStage;
|
||||||
|
GPUProgrammableStageDescriptor fragmentStage;
|
||||||
|
|
||||||
|
required GPUPrimitiveTopology primitiveTopology;
|
||||||
|
GPURasterizationStateDescriptor rasterizationState = {};
|
||||||
|
required sequence<GPUColorStateDescriptor> colorStates;
|
||||||
|
GPUDepthStencilStateDescriptor depthStencilState;
|
||||||
|
GPUVertexStateDescriptor vertexState = {};
|
||||||
|
|
||||||
|
GPUSize32 sampleCount = 1;
|
||||||
|
GPUSampleMask sampleMask = 0xFFFFFFFF;
|
||||||
|
boolean alphaToCoverageEnabled = false;
|
||||||
|
// TODO: other properties
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUPrimitiveTopology {
|
||||||
|
"point-list",
|
||||||
|
"line-list",
|
||||||
|
"line-strip",
|
||||||
|
"triangle-list",
|
||||||
|
"triangle-strip"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPURasterizationStateDescriptor {
|
||||||
|
GPUFrontFace frontFace = "ccw";
|
||||||
|
GPUCullMode cullMode = "none";
|
||||||
|
|
||||||
|
GPUDepthBias depthBias = 0;
|
||||||
|
float depthBiasSlopeScale = 0;
|
||||||
|
float depthBiasClamp = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUFrontFace {
|
||||||
|
"ccw",
|
||||||
|
"cw"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUCullMode {
|
||||||
|
"none",
|
||||||
|
"front",
|
||||||
|
"back"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUColorStateDescriptor {
|
||||||
|
required GPUTextureFormat format;
|
||||||
|
|
||||||
|
GPUBlendDescriptor alphaBlend = {};
|
||||||
|
GPUBlendDescriptor colorBlend = {};
|
||||||
|
GPUColorWriteFlags writeMask = 0xF; // GPUColorWrite.ALL
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef [EnforceRange] unsigned long GPUColorWriteFlags;
|
||||||
|
interface GPUColorWrite {
|
||||||
|
const GPUColorWriteFlags RED = 0x1;
|
||||||
|
const GPUColorWriteFlags GREEN = 0x2;
|
||||||
|
const GPUColorWriteFlags BLUE = 0x4;
|
||||||
|
const GPUColorWriteFlags ALPHA = 0x8;
|
||||||
|
const GPUColorWriteFlags ALL = 0xF;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUBlendDescriptor {
|
||||||
|
GPUBlendFactor srcFactor = "one";
|
||||||
|
GPUBlendFactor dstFactor = "zero";
|
||||||
|
GPUBlendOperation operation = "add";
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUBlendFactor {
|
||||||
|
"zero",
|
||||||
|
"one",
|
||||||
|
"src-color",
|
||||||
|
"one-minus-src-color",
|
||||||
|
"src-alpha",
|
||||||
|
"one-minus-src-alpha",
|
||||||
|
"dst-color",
|
||||||
|
"one-minus-dst-color",
|
||||||
|
"dst-alpha",
|
||||||
|
"one-minus-dst-alpha",
|
||||||
|
"src-alpha-saturated",
|
||||||
|
"blend-color",
|
||||||
|
"one-minus-blend-color"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUBlendOperation {
|
||||||
|
"add",
|
||||||
|
"subtract",
|
||||||
|
"reverse-subtract",
|
||||||
|
"min",
|
||||||
|
"max"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUStencilOperation {
|
||||||
|
"keep",
|
||||||
|
"zero",
|
||||||
|
"replace",
|
||||||
|
"invert",
|
||||||
|
"increment-clamp",
|
||||||
|
"decrement-clamp",
|
||||||
|
"increment-wrap",
|
||||||
|
"decrement-wrap"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUDepthStencilStateDescriptor {
|
||||||
|
required GPUTextureFormat format;
|
||||||
|
|
||||||
|
boolean depthWriteEnabled = false;
|
||||||
|
GPUCompareFunction depthCompare = "always";
|
||||||
|
|
||||||
|
GPUStencilStateFaceDescriptor stencilFront = {};
|
||||||
|
GPUStencilStateFaceDescriptor stencilBack = {};
|
||||||
|
|
||||||
|
GPUStencilValue stencilReadMask = 0xFFFFFFFF;
|
||||||
|
GPUStencilValue stencilWriteMask = 0xFFFFFFFF;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUStencilStateFaceDescriptor {
|
||||||
|
GPUCompareFunction compare = "always";
|
||||||
|
GPUStencilOperation failOp = "keep";
|
||||||
|
GPUStencilOperation depthFailOp = "keep";
|
||||||
|
GPUStencilOperation passOp = "keep";
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUIndexFormat {
|
||||||
|
"uint16",
|
||||||
|
"uint32"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUVertexFormat {
|
||||||
|
"uchar2",
|
||||||
|
"uchar4",
|
||||||
|
"char2",
|
||||||
|
"char4",
|
||||||
|
"uchar2norm",
|
||||||
|
"uchar4norm",
|
||||||
|
"char2norm",
|
||||||
|
"char4norm",
|
||||||
|
"ushort2",
|
||||||
|
"ushort4",
|
||||||
|
"short2",
|
||||||
|
"short4",
|
||||||
|
"ushort2norm",
|
||||||
|
"ushort4norm",
|
||||||
|
"short2norm",
|
||||||
|
"short4norm",
|
||||||
|
"half2",
|
||||||
|
"half4",
|
||||||
|
"float",
|
||||||
|
"float2",
|
||||||
|
"float3",
|
||||||
|
"float4",
|
||||||
|
"uint",
|
||||||
|
"uint2",
|
||||||
|
"uint3",
|
||||||
|
"uint4",
|
||||||
|
"int",
|
||||||
|
"int2",
|
||||||
|
"int3",
|
||||||
|
"int4"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUInputStepMode {
|
||||||
|
"vertex",
|
||||||
|
"instance"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUVertexStateDescriptor {
|
||||||
|
GPUIndexFormat indexFormat = "uint32";
|
||||||
|
sequence<GPUVertexBufferLayoutDescriptor?> vertexBuffers = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUVertexBufferLayoutDescriptor {
|
||||||
|
required GPUSize64 arrayStride;
|
||||||
|
GPUInputStepMode stepMode = "vertex";
|
||||||
|
required sequence<GPUVertexAttributeDescriptor> attributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUVertexAttributeDescriptor {
|
||||||
|
required GPUVertexFormat format;
|
||||||
|
required GPUSize64 offset;
|
||||||
|
|
||||||
|
required GPUIndex32 shaderLocation;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUCommandBuffer {
|
||||||
|
};
|
||||||
|
GPUCommandBuffer includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUCommandBufferDescriptor : GPUObjectDescriptorBase {
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUCommandEncoder {
|
||||||
|
GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor);
|
||||||
|
GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor = {});
|
||||||
|
|
||||||
|
void copyBufferToBuffer(
|
||||||
|
GPUBuffer source,
|
||||||
|
GPUSize64 sourceOffset,
|
||||||
|
GPUBuffer destination,
|
||||||
|
GPUSize64 destinationOffset,
|
||||||
|
GPUSize64 size);
|
||||||
|
|
||||||
|
void copyBufferToTexture(
|
||||||
|
GPUBufferCopyView source,
|
||||||
|
GPUTextureCopyView destination,
|
||||||
|
GPUExtent3D copySize);
|
||||||
|
|
||||||
|
void copyTextureToBuffer(
|
||||||
|
GPUTextureCopyView source,
|
||||||
|
GPUBufferCopyView destination,
|
||||||
|
GPUExtent3D copySize);
|
||||||
|
|
||||||
|
void copyTextureToTexture(
|
||||||
|
GPUTextureCopyView source,
|
||||||
|
GPUTextureCopyView destination,
|
||||||
|
GPUExtent3D copySize);
|
||||||
|
|
||||||
|
void pushDebugGroup(DOMString groupLabel);
|
||||||
|
void popDebugGroup();
|
||||||
|
void insertDebugMarker(DOMString markerLabel);
|
||||||
|
|
||||||
|
GPUCommandBuffer finish(optional GPUCommandBufferDescriptor descriptor = {});
|
||||||
|
};
|
||||||
|
GPUCommandEncoder includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase {
|
||||||
|
// TODO: reusability flag?
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUBufferCopyView {
|
||||||
|
required GPUBuffer buffer;
|
||||||
|
GPUSize64 offset = 0;
|
||||||
|
required GPUSize32 rowPitch;
|
||||||
|
required GPUSize32 imageHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUTextureCopyView {
|
||||||
|
required GPUTexture texture;
|
||||||
|
GPUIntegerCoordinate mipLevel = 0;
|
||||||
|
GPUIntegerCoordinate arrayLayer = 0;
|
||||||
|
GPUOrigin3D origin = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUImageBitmapCopyView {
|
||||||
|
required ImageBitmap imageBitmap;
|
||||||
|
GPUOrigin2D origin = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
interface mixin GPUProgrammablePassEncoder {
|
||||||
|
void setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup,
|
||||||
|
optional sequence<GPUBufferDynamicOffset> dynamicOffsets = []);
|
||||||
|
|
||||||
|
void setBindGroup(GPUIndex32 index, GPUBindGroup bindGroup,
|
||||||
|
Uint32Array dynamicOffsetsData,
|
||||||
|
GPUSize64 dynamicOffsetsDataStart,
|
||||||
|
GPUSize32 dynamicOffsetsDataLength);
|
||||||
|
|
||||||
|
void pushDebugGroup(DOMString groupLabel);
|
||||||
|
void popDebugGroup();
|
||||||
|
void insertDebugMarker(DOMString markerLabel);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUComputePassEncoder {
|
||||||
|
void setPipeline(GPUComputePipeline pipeline);
|
||||||
|
void dispatch(GPUSize32 x, optional GPUSize32 y = 1, optional GPUSize32 z = 1);
|
||||||
|
void dispatchIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
|
||||||
|
|
||||||
|
void endPass();
|
||||||
|
};
|
||||||
|
GPUComputePassEncoder includes GPUObjectBase;
|
||||||
|
GPUComputePassEncoder includes GPUProgrammablePassEncoder;
|
||||||
|
|
||||||
|
dictionary GPUComputePassDescriptor : GPUObjectDescriptorBase {
|
||||||
|
};
|
||||||
|
|
||||||
|
interface mixin GPURenderEncoderBase {
|
||||||
|
void setPipeline(GPURenderPipeline pipeline);
|
||||||
|
|
||||||
|
void setIndexBuffer(GPUBuffer buffer, optional GPUSize64 offset = 0);
|
||||||
|
void setVertexBuffer(GPUIndex32 slot, GPUBuffer buffer, optional GPUSize64 offset = 0);
|
||||||
|
|
||||||
|
void draw(GPUSize32 vertexCount, GPUSize32 instanceCount,
|
||||||
|
GPUSize32 firstVertex, GPUSize32 firstInstance);
|
||||||
|
void drawIndexed(GPUSize32 indexCount, GPUSize32 instanceCount,
|
||||||
|
GPUSize32 firstIndex, GPUSignedOffset32 baseVertex, GPUSize32 firstInstance);
|
||||||
|
|
||||||
|
void drawIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
|
||||||
|
void drawIndexedIndirect(GPUBuffer indirectBuffer, GPUSize64 indirectOffset);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPURenderPassEncoder {
|
||||||
|
void setViewport(float x, float y,
|
||||||
|
float width, float height,
|
||||||
|
float minDepth, float maxDepth);
|
||||||
|
|
||||||
|
void setScissorRect(GPUIntegerCoordinate x, GPUIntegerCoordinate y,
|
||||||
|
GPUIntegerCoordinate width, GPUIntegerCoordinate height);
|
||||||
|
|
||||||
|
void setBlendColor(GPUColor color);
|
||||||
|
void setStencilReference(GPUStencilValue reference);
|
||||||
|
|
||||||
|
void executeBundles(sequence<GPURenderBundle> bundles);
|
||||||
|
void endPass();
|
||||||
|
};
|
||||||
|
GPURenderPassEncoder includes GPUObjectBase;
|
||||||
|
GPURenderPassEncoder includes GPUProgrammablePassEncoder;
|
||||||
|
GPURenderPassEncoder includes GPURenderEncoderBase;
|
||||||
|
|
||||||
|
dictionary GPURenderPassDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required sequence<GPURenderPassColorAttachmentDescriptor> colorAttachments;
|
||||||
|
GPURenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPURenderPassColorAttachmentDescriptor {
|
||||||
|
required GPUTextureView attachment;
|
||||||
|
GPUTextureView resolveTarget;
|
||||||
|
|
||||||
|
required (GPULoadOp or GPUColor) loadValue;
|
||||||
|
GPUStoreOp storeOp = "store";
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPURenderPassDepthStencilAttachmentDescriptor {
|
||||||
|
required GPUTextureView attachment;
|
||||||
|
|
||||||
|
required (GPULoadOp or float) depthLoadValue;
|
||||||
|
required GPUStoreOp depthStoreOp;
|
||||||
|
|
||||||
|
required (GPULoadOp or GPUStencilValue) stencilLoadValue;
|
||||||
|
required GPUStoreOp stencilStoreOp;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPULoadOp {
|
||||||
|
"load"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUStoreOp {
|
||||||
|
"store",
|
||||||
|
"clear"
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPURenderBundle {
|
||||||
|
};
|
||||||
|
GPURenderBundle includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPURenderBundleDescriptor : GPUObjectDescriptorBase {
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPURenderBundleEncoder {
|
||||||
|
GPURenderBundle finish(optional GPURenderBundleDescriptor descriptor = {});
|
||||||
|
};
|
||||||
|
GPURenderBundleEncoder includes GPUObjectBase;
|
||||||
|
GPURenderBundleEncoder includes GPUProgrammablePassEncoder;
|
||||||
|
GPURenderBundleEncoder includes GPURenderEncoderBase;
|
||||||
|
|
||||||
|
dictionary GPURenderBundleEncoderDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required sequence<GPUTextureFormat> colorFormats;
|
||||||
|
GPUTextureFormat depthStencilFormat;
|
||||||
|
GPUSize32 sampleCount = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUQueue {
|
||||||
|
void submit(sequence<GPUCommandBuffer> commandBuffers);
|
||||||
|
|
||||||
|
GPUFence createFence(optional GPUFenceDescriptor descriptor = {});
|
||||||
|
void signal(GPUFence fence, GPUFenceValue signalValue);
|
||||||
|
|
||||||
|
void copyImageBitmapToTexture(
|
||||||
|
GPUImageBitmapCopyView source,
|
||||||
|
GPUTextureCopyView destination,
|
||||||
|
GPUExtent3D copySize);
|
||||||
|
};
|
||||||
|
GPUQueue includes GPUObjectBase;
|
||||||
|
|
||||||
|
interface GPUFence {
|
||||||
|
GPUFenceValue getCompletedValue();
|
||||||
|
Promise<void> onCompletion(GPUFenceValue completionValue);
|
||||||
|
};
|
||||||
|
GPUFence includes GPUObjectBase;
|
||||||
|
|
||||||
|
dictionary GPUFenceDescriptor : GPUObjectDescriptorBase {
|
||||||
|
GPUFenceValue initialValue = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUCanvasContext {
|
||||||
|
GPUSwapChain configureSwapChain(GPUSwapChainDescriptor descriptor);
|
||||||
|
|
||||||
|
Promise<GPUTextureFormat> getSwapChainPreferredFormat(GPUDevice device);
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUSwapChainDescriptor : GPUObjectDescriptorBase {
|
||||||
|
required GPUDevice device;
|
||||||
|
required GPUTextureFormat format;
|
||||||
|
GPUTextureUsageFlags usage = 0x10; // GPUTextureUsage.OUTPUT_ATTACHMENT
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUSwapChain {
|
||||||
|
GPUTexture getCurrentTexture();
|
||||||
|
};
|
||||||
|
GPUSwapChain includes GPUObjectBase;
|
||||||
|
|
||||||
|
interface GPUDeviceLostInfo {
|
||||||
|
readonly attribute DOMString message;
|
||||||
|
};
|
||||||
|
|
||||||
|
partial interface GPUDevice {
|
||||||
|
readonly attribute Promise<GPUDeviceLostInfo> lost;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum GPUErrorFilter {
|
||||||
|
"none",
|
||||||
|
"out-of-memory",
|
||||||
|
"validation"
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUOutOfMemoryError {
|
||||||
|
constructor();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GPUValidationError {
|
||||||
|
constructor(DOMString message);
|
||||||
|
readonly attribute DOMString message;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef (GPUOutOfMemoryError or GPUValidationError) GPUError;
|
||||||
|
|
||||||
|
partial interface GPUDevice {
|
||||||
|
void pushErrorScope(GPUErrorFilter filter);
|
||||||
|
Promise<GPUError?> popErrorScope();
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
Exposed=(Window, DedicatedWorker)
|
||||||
|
]
|
||||||
|
interface GPUUncapturedErrorEvent : Event {
|
||||||
|
constructor(
|
||||||
|
DOMString type,
|
||||||
|
GPUUncapturedErrorEventInit gpuUncapturedErrorEventInitDict
|
||||||
|
);
|
||||||
|
[SameObject] readonly attribute GPUError error;
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary GPUUncapturedErrorEventInit : EventInit {
|
||||||
|
required GPUError error;
|
||||||
|
};
|
||||||
|
|
||||||
|
partial interface GPUDevice {
|
||||||
|
[Exposed=(Window, DedicatedWorker)]
|
||||||
|
attribute EventHandler onuncapturederror;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef [EnforceRange] unsigned long GPUBufferDynamicOffset;
|
||||||
|
typedef [EnforceRange] unsigned long long GPUFenceValue;
|
||||||
|
typedef [EnforceRange] unsigned long GPUStencilValue;
|
||||||
|
typedef [EnforceRange] unsigned long GPUSampleMask;
|
||||||
|
typedef [EnforceRange] long GPUDepthBias;
|
||||||
|
|
||||||
|
typedef [EnforceRange] unsigned long long GPUSize64;
|
||||||
|
typedef [EnforceRange] unsigned long GPUIntegerCoordinate;
|
||||||
|
typedef [EnforceRange] unsigned long GPUIndex32;
|
||||||
|
typedef [EnforceRange] unsigned long GPUSize32;
|
||||||
|
typedef [EnforceRange] long GPUSignedOffset32;
|
||||||
|
|
||||||
|
dictionary GPUColorDict {
|
||||||
|
required double r;
|
||||||
|
required double g;
|
||||||
|
required double b;
|
||||||
|
required double a;
|
||||||
|
};
|
||||||
|
typedef (sequence<double> or GPUColorDict) GPUColor;
|
||||||
|
|
||||||
|
dictionary GPUOrigin2DDict {
|
||||||
|
GPUIntegerCoordinate x = 0;
|
||||||
|
GPUIntegerCoordinate y = 0;
|
||||||
|
};
|
||||||
|
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin2DDict) GPUOrigin2D;
|
||||||
|
|
||||||
|
dictionary GPUOrigin3DDict {
|
||||||
|
GPUIntegerCoordinate x = 0;
|
||||||
|
GPUIntegerCoordinate y = 0;
|
||||||
|
GPUIntegerCoordinate z = 0;
|
||||||
|
};
|
||||||
|
typedef (sequence<GPUIntegerCoordinate> or GPUOrigin3DDict) GPUOrigin3D;
|
||||||
|
|
||||||
|
dictionary GPUExtent3DDict {
|
||||||
|
required GPUIntegerCoordinate width;
|
||||||
|
required GPUIntegerCoordinate height;
|
||||||
|
required GPUIntegerCoordinate depth;
|
||||||
|
};
|
||||||
|
typedef (sequence<GPUIntegerCoordinate> or GPUExtent3DDict) GPUExtent3D;
|
||||||
|
|
||||||
|
typedef sequence<(GPUBuffer or ArrayBuffer)> GPUMappedBuffer;
|
@ -11,13 +11,22 @@ fn main() {
|
|||||||
let idls = fs::read_dir(".")
|
let idls = fs::read_dir(".")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|f| f.unwrap().path())
|
.map(|f| f.unwrap().path())
|
||||||
.filter(|f| f.extension().and_then(|s| s.to_str()) == Some("webidl"))
|
.filter(|path| path.extension().and_then(|s| s.to_str()) == Some("webidl"))
|
||||||
.map(|f| (fs::read_to_string(&f).unwrap(), f));
|
.map(|path| {
|
||||||
|
let unstable = path.file_name().and_then(|s| s.to_str()) == Some("unstable.webidl");
|
||||||
|
let file = fs::read_to_string(&path).unwrap();
|
||||||
|
(file, path, unstable)
|
||||||
|
});
|
||||||
|
|
||||||
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
for (i, (idl, path)) in idls.enumerate() {
|
for (i, (idl, path, unstable)) in idls.enumerate() {
|
||||||
println!("processing {:?}", path);
|
println!("processing {:?}", path);
|
||||||
let mut generated_rust = wasm_bindgen_webidl::compile(&idl, None).unwrap();
|
let (stable_source, experimental_source) = if unstable {
|
||||||
|
(String::new(), idl)
|
||||||
|
} else {
|
||||||
|
(idl, String::new())
|
||||||
|
};
|
||||||
|
let mut generated_rust = wasm_bindgen_webidl::compile(&stable_source, &experimental_source, None).unwrap();
|
||||||
|
|
||||||
generated_rust.insert_str(
|
generated_rust.insert_str(
|
||||||
0,
|
0,
|
||||||
|
@ -13,3 +13,4 @@ pub mod namespace;
|
|||||||
pub mod no_interface;
|
pub mod no_interface;
|
||||||
pub mod simple;
|
pub mod simple;
|
||||||
pub mod throws;
|
pub mod throws;
|
||||||
|
pub mod unstable;
|
||||||
|
13
crates/webidl-tests/unstable.js
Normal file
13
crates/webidl-tests/unstable.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
global.GetUnstableInterface = class {
|
||||||
|
static get() {
|
||||||
|
return {
|
||||||
|
enum_value(dict) {
|
||||||
|
if (!dict) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict.unstableEnum === "a" ? 1 : 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
crates/webidl-tests/unstable.rs
Normal file
17
crates/webidl-tests/unstable.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
use wasm_bindgen_test::*;
|
||||||
|
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/unstable.rs"));
|
||||||
|
|
||||||
|
#[cfg(web_sys_unstable_apis)]
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn can_use_unstable_apis() {
|
||||||
|
let unstable_interface = GetUnstableInterface::get();
|
||||||
|
assert_eq!(0u32, unstable_interface.enum_value());
|
||||||
|
|
||||||
|
let mut dict = UnstableDictionary::new();
|
||||||
|
dict.unstable_enum(UnstableEnum::B);
|
||||||
|
assert_eq!(
|
||||||
|
2u32,
|
||||||
|
unstable_interface.enum_value_with_unstable_dictionary(&dict)
|
||||||
|
);
|
||||||
|
}
|
19
crates/webidl-tests/unstable.webidl
vendored
Normal file
19
crates/webidl-tests/unstable.webidl
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
enum UnstableEnum {
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
};
|
||||||
|
|
||||||
|
dictionary UnstableDictionary {
|
||||||
|
UnstableEnum unstableEnum;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned long UnstableTypedef;
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
partial interface UnstableInterface {
|
||||||
|
UnstableTypedef enum_value(optional UnstableDictionary unstableDictionary = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GetUnstableInterface {
|
||||||
|
static UnstableInterface get();
|
||||||
|
};
|
@ -20,15 +20,14 @@ use weedle::CallbackInterfaceDefinition;
|
|||||||
use weedle::{DictionaryDefinition, PartialDictionaryDefinition};
|
use weedle::{DictionaryDefinition, PartialDictionaryDefinition};
|
||||||
|
|
||||||
use super::Result;
|
use super::Result;
|
||||||
use crate::util;
|
use crate::{util::{self, camel_case_ident}, ApiStability};
|
||||||
use crate::util::camel_case_ident;
|
|
||||||
|
|
||||||
/// Collection of constructs that may use partial.
|
/// Collection of constructs that may use partial.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct FirstPassRecord<'src> {
|
pub(crate) struct FirstPassRecord<'src> {
|
||||||
pub(crate) builtin_idents: BTreeSet<Ident>,
|
pub(crate) builtin_idents: BTreeSet<Ident>,
|
||||||
pub(crate) interfaces: BTreeMap<&'src str, InterfaceData<'src>>,
|
pub(crate) interfaces: BTreeMap<&'src str, InterfaceData<'src>>,
|
||||||
pub(crate) enums: BTreeMap<&'src str, &'src weedle::EnumDefinition<'src>>,
|
pub(crate) enums: BTreeMap<&'src str, EnumData<'src>>,
|
||||||
/// 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, MixinData<'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>>,
|
||||||
@ -40,6 +39,11 @@ pub(crate) struct FirstPassRecord<'src> {
|
|||||||
pub(crate) immutable_slice_whitelist: BTreeSet<&'static str>,
|
pub(crate) immutable_slice_whitelist: BTreeSet<&'static str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct AttributeInterfaceData<'src> {
|
||||||
|
pub(crate) definition: &'src AttributeInterfaceMember<'src>,
|
||||||
|
pub(crate) stability: ApiStability,
|
||||||
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(crate) struct InterfaceData<'src> {
|
pub(crate) struct InterfaceData<'src> {
|
||||||
@ -47,11 +51,17 @@ pub(crate) struct InterfaceData<'src> {
|
|||||||
pub(crate) partial: bool,
|
pub(crate) partial: bool,
|
||||||
pub(crate) has_interface: bool,
|
pub(crate) has_interface: bool,
|
||||||
pub(crate) deprecated: Option<String>,
|
pub(crate) deprecated: Option<String>,
|
||||||
pub(crate) attributes: Vec<&'src AttributeInterfaceMember<'src>>,
|
pub(crate) attributes: Vec<AttributeInterfaceData<'src>>,
|
||||||
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
||||||
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||||
pub(crate) superclass: Option<&'src str>,
|
pub(crate) superclass: Option<&'src str>,
|
||||||
pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>,
|
pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>,
|
||||||
|
pub(crate) stability: ApiStability,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct AttributeMixinData<'src> {
|
||||||
|
pub(crate) definition: &'src AttributeMixinMember<'src>,
|
||||||
|
pub(crate) stability: ApiStability,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We need to collect mixin data during the first pass, to be used later.
|
/// We need to collect mixin data during the first pass, to be used later.
|
||||||
@ -59,10 +69,11 @@ pub(crate) struct InterfaceData<'src> {
|
|||||||
pub(crate) struct MixinData<'src> {
|
pub(crate) struct MixinData<'src> {
|
||||||
/// Whether only partial mixins were encountered
|
/// Whether only partial mixins were encountered
|
||||||
pub(crate) partial: bool,
|
pub(crate) partial: bool,
|
||||||
pub(crate) attributes: Vec<&'src AttributeMixinMember<'src>>,
|
pub(crate) attributes: Vec<AttributeMixinData<'src>>,
|
||||||
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
pub(crate) consts: Vec<&'src ConstMember<'src>>,
|
||||||
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
pub(crate) operations: BTreeMap<OperationId<'src>, OperationData<'src>>,
|
||||||
pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>,
|
pub(crate) definition_attributes: Option<&'src ExtendedAttributeList<'src>>,
|
||||||
|
pub(crate) stability: ApiStability,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
@ -75,6 +86,12 @@ pub(crate) struct NamespaceData<'src> {
|
|||||||
pub(crate) struct DictionaryData<'src> {
|
pub(crate) struct DictionaryData<'src> {
|
||||||
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) stability: ApiStability,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct EnumData<'src> {
|
||||||
|
pub(crate) definition: &'src weedle::EnumDefinition<'src>,
|
||||||
|
pub(crate) stability: ApiStability,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct CallbackInterfaceData<'src> {
|
pub(crate) struct CallbackInterfaceData<'src> {
|
||||||
@ -121,29 +138,29 @@ pub(crate) trait FirstPass<'src, Ctx> {
|
|||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, ctx: Ctx) -> Result<()>;
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, ctx: Ctx) -> Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for [weedle::Definition<'src>] {
|
impl<'src> FirstPass<'src, ApiStability> for [weedle::Definition<'src>] {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
for def in self {
|
for def in self {
|
||||||
def.first_pass(record, ())?;
|
def.first_pass(record, stability)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::Definition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::Definition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
use weedle::Definition::*;
|
use weedle::Definition::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Dictionary(dictionary) => dictionary.first_pass(record, ()),
|
Dictionary(dictionary) => dictionary.first_pass(record, stability),
|
||||||
PartialDictionary(dictionary) => dictionary.first_pass(record, ()),
|
PartialDictionary(dictionary) => dictionary.first_pass(record, ()),
|
||||||
Enum(enum_) => enum_.first_pass(record, ()),
|
Enum(enum_) => enum_.first_pass(record, stability),
|
||||||
IncludesStatement(includes) => includes.first_pass(record, ()),
|
IncludesStatement(includes) => includes.first_pass(record, ()),
|
||||||
Interface(interface) => interface.first_pass(record, ()),
|
Interface(interface) => interface.first_pass(record, stability),
|
||||||
PartialInterface(interface) => interface.first_pass(record, ()),
|
PartialInterface(interface) => interface.first_pass(record, stability),
|
||||||
InterfaceMixin(mixin) => mixin.first_pass(record, ()),
|
InterfaceMixin(mixin) => mixin.first_pass(record, stability),
|
||||||
PartialInterfaceMixin(mixin) => mixin.first_pass(record, ()),
|
PartialInterfaceMixin(mixin) => mixin.first_pass(record, stability),
|
||||||
Namespace(namespace) => namespace.first_pass(record, ()),
|
Namespace(namespace) => namespace.first_pass(record, ()),
|
||||||
PartialNamespace(namespace) => namespace.first_pass(record, ()),
|
PartialNamespace(namespace) => namespace.first_pass(record, ()),
|
||||||
Typedef(typedef) => typedef.first_pass(record, ()),
|
Typedef(typedef) => typedef.first_pass(record, ()),
|
||||||
@ -154,17 +171,20 @@ impl<'src> FirstPass<'src, ()> for weedle::Definition<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::DictionaryDefinition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::DictionaryDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
record
|
let dictionary_data = record
|
||||||
.dictionaries
|
.dictionaries
|
||||||
.entry(self.identifier.0)
|
.entry(self.identifier.0)
|
||||||
.or_default()
|
.or_default();
|
||||||
.definition = Some(self);
|
|
||||||
|
dictionary_data.definition = Some(self);
|
||||||
|
dictionary_data.stability = stability;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,17 +201,23 @@ impl<'src> FirstPass<'src, ()> for weedle::PartialDictionaryDefinition<'src> {
|
|||||||
.or_default()
|
.or_default()
|
||||||
.partials
|
.partials
|
||||||
.push(self);
|
.push(self);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::EnumDefinition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::EnumDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if record.enums.insert(self.identifier.0, self).is_some() {
|
let enum_data = EnumData {
|
||||||
|
definition: self,
|
||||||
|
stability,
|
||||||
|
};
|
||||||
|
|
||||||
|
if record.enums.insert(self.identifier.0, enum_data).is_some() {
|
||||||
log::info!(
|
log::info!(
|
||||||
"Encountered multiple enum declarations: {}",
|
"Encountered multiple enum declarations: {}",
|
||||||
self.identifier.0
|
self.identifier.0
|
||||||
@ -298,8 +324,8 @@ fn first_pass_operation<'src>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::InterfaceDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -311,6 +337,7 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
|||||||
interface_data.deprecated =
|
interface_data.deprecated =
|
||||||
util::get_rust_deprecated(&self.attributes).map(|s| s.to_string());
|
util::get_rust_deprecated(&self.attributes).map(|s| s.to_string());
|
||||||
interface_data.has_interface = !util::is_no_interface_object(&self.attributes);
|
interface_data.has_interface = !util::is_no_interface_object(&self.attributes);
|
||||||
|
interface_data.stability = stability;
|
||||||
if let Some(attrs) = &self.attributes {
|
if let Some(attrs) = &self.attributes {
|
||||||
for attr in attrs.body.list.iter() {
|
for attr in attrs.body.list.iter() {
|
||||||
process_interface_attribute(record, self.identifier.0, attr);
|
process_interface_attribute(record, self.identifier.0, attr);
|
||||||
@ -318,7 +345,7 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceDefinition<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for member in &self.members.body {
|
for member in &self.members.body {
|
||||||
member.first_pass(record, self.identifier.0)?;
|
member.first_pass(record, (self.identifier.0, stability))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -382,8 +409,8 @@ fn process_interface_attribute<'src>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::PartialInterfaceDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -392,31 +419,33 @@ impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceDefinition<'src> {
|
|||||||
.entry(self.identifier.0)
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(|| InterfaceData {
|
.or_insert_with(|| InterfaceData {
|
||||||
partial: true,
|
partial: true,
|
||||||
|
stability,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
for member in &self.members.body {
|
for member in &self.members.body {
|
||||||
member.first_pass(record, self.identifier.0)?;
|
member.first_pass(record, (self.identifier.0, stability))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, &'src str> for weedle::interface::InterfaceMember<'src> {
|
impl<'src> FirstPass<'src, (&'src str, ApiStability)> for weedle::interface::InterfaceMember<'src> {
|
||||||
fn first_pass(
|
fn first_pass(
|
||||||
&'src self,
|
&'src self,
|
||||||
record: &mut FirstPassRecord<'src>,
|
record: &mut FirstPassRecord<'src>,
|
||||||
self_name: &'src str,
|
ctx: (&'src str, ApiStability),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
InterfaceMember::Attribute(attr) => attr.first_pass(record, self_name),
|
InterfaceMember::Attribute(attr) => attr.first_pass(record, ctx),
|
||||||
InterfaceMember::Operation(op) => op.first_pass(record, self_name),
|
InterfaceMember::Operation(op) => op.first_pass(record, ctx.0),
|
||||||
InterfaceMember::Const(const_) => {
|
InterfaceMember::Const(const_) => {
|
||||||
if util::is_chrome_only(&const_.attributes) {
|
if util::is_chrome_only(&const_.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
record
|
record
|
||||||
.interfaces
|
.interfaces
|
||||||
.get_mut(self_name)
|
.get_mut(ctx.0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.consts
|
.consts
|
||||||
.push(const_);
|
.push(const_);
|
||||||
@ -484,11 +513,11 @@ impl<'src> FirstPass<'src, &'src str> for weedle::interface::OperationInterfaceM
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, &'src str> for weedle::interface::AttributeInterfaceMember<'src> {
|
impl<'src> FirstPass<'src, (&'src str, ApiStability)> for weedle::interface::AttributeInterfaceMember<'src> {
|
||||||
fn first_pass(
|
fn first_pass(
|
||||||
&'src self,
|
&'src self,
|
||||||
record: &mut FirstPassRecord<'src>,
|
record: &mut FirstPassRecord<'src>,
|
||||||
self_name: &'src str,
|
ctx: (&'src str, ApiStability),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -496,16 +525,19 @@ impl<'src> FirstPass<'src, &'src str> for weedle::interface::AttributeInterfaceM
|
|||||||
|
|
||||||
record
|
record
|
||||||
.interfaces
|
.interfaces
|
||||||
.get_mut(self_name)
|
.get_mut(ctx.0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.attributes
|
.attributes
|
||||||
.push(self);
|
.push(AttributeInterfaceData {
|
||||||
|
definition: self,
|
||||||
|
stability: ctx.1
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::InterfaceMixinDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -514,18 +546,19 @@ impl<'src> FirstPass<'src, ()> for weedle::InterfaceMixinDefinition<'src> {
|
|||||||
let mixin_data = record.mixins.entry(self.identifier.0).or_default();
|
let mixin_data = record.mixins.entry(self.identifier.0).or_default();
|
||||||
mixin_data.partial = false;
|
mixin_data.partial = false;
|
||||||
mixin_data.definition_attributes = self.attributes.as_ref();
|
mixin_data.definition_attributes = self.attributes.as_ref();
|
||||||
|
mixin_data.stability = stability;
|
||||||
}
|
}
|
||||||
|
|
||||||
for member in &self.members.body {
|
for member in &self.members.body {
|
||||||
member.first_pass(record, self.identifier.0)?;
|
member.first_pass(record, (self.identifier.0, stability))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceMixinDefinition<'src> {
|
impl<'src> FirstPass<'src, ApiStability> for weedle::PartialInterfaceMixinDefinition<'src> {
|
||||||
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, (): ()) -> Result<()> {
|
fn first_pass(&'src self, record: &mut FirstPassRecord<'src>, stability: ApiStability) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -535,31 +568,32 @@ impl<'src> FirstPass<'src, ()> for weedle::PartialInterfaceMixinDefinition<'src>
|
|||||||
.entry(self.identifier.0)
|
.entry(self.identifier.0)
|
||||||
.or_insert_with(|| MixinData {
|
.or_insert_with(|| MixinData {
|
||||||
partial: true,
|
partial: true,
|
||||||
|
stability,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
for member in &self.members.body {
|
for member in &self.members.body {
|
||||||
member.first_pass(record, self.identifier.0)?;
|
member.first_pass(record, (self.identifier.0, stability))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, &'src str> for weedle::mixin::MixinMember<'src> {
|
impl<'src> FirstPass<'src, (&'src str, ApiStability)> for weedle::mixin::MixinMember<'src> {
|
||||||
fn first_pass(
|
fn first_pass(
|
||||||
&'src self,
|
&'src self,
|
||||||
record: &mut FirstPassRecord<'src>,
|
record: &mut FirstPassRecord<'src>,
|
||||||
self_name: &'src str,
|
ctx: (&'src str, ApiStability),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match self {
|
match self {
|
||||||
MixinMember::Operation(op) => op.first_pass(record, self_name),
|
MixinMember::Operation(op) => op.first_pass(record, ctx),
|
||||||
MixinMember::Attribute(a) => a.first_pass(record, self_name),
|
MixinMember::Attribute(a) => a.first_pass(record, ctx),
|
||||||
MixinMember::Const(a) => {
|
MixinMember::Const(a) => {
|
||||||
if util::is_chrome_only(&a.attributes) {
|
if util::is_chrome_only(&a.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
record.mixins.get_mut(self_name).unwrap().consts.push(a);
|
record.mixins.get_mut(ctx.0).unwrap().consts.push(a);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
MixinMember::Stringifier(_) => {
|
MixinMember::Stringifier(_) => {
|
||||||
@ -570,11 +604,11 @@ impl<'src> FirstPass<'src, &'src str> for weedle::mixin::MixinMember<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, &'src str> for weedle::mixin::OperationMixinMember<'src> {
|
impl<'src> FirstPass<'src, (&'src str, ApiStability)> for weedle::mixin::OperationMixinMember<'src> {
|
||||||
fn first_pass(
|
fn first_pass(
|
||||||
&'src self,
|
&'src self,
|
||||||
record: &mut FirstPassRecord<'src>,
|
record: &mut FirstPassRecord<'src>,
|
||||||
self_name: &'src str,
|
ctx: (&'src str, ApiStability),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if self.stringifier.is_some() {
|
if self.stringifier.is_some() {
|
||||||
log::warn!("Unsupported webidl stringifier: {:?}", self);
|
log::warn!("Unsupported webidl stringifier: {:?}", self);
|
||||||
@ -584,7 +618,7 @@ impl<'src> FirstPass<'src, &'src str> for weedle::mixin::OperationMixinMember<'s
|
|||||||
first_pass_operation(
|
first_pass_operation(
|
||||||
record,
|
record,
|
||||||
FirstPassOperationType::Mixin,
|
FirstPassOperationType::Mixin,
|
||||||
self_name,
|
ctx.0,
|
||||||
&[OperationId::Operation(self.identifier.map(|s| s.0.clone()))],
|
&[OperationId::Operation(self.identifier.map(|s| s.0.clone()))],
|
||||||
&self.args.body.list,
|
&self.args.body.list,
|
||||||
&self.return_type,
|
&self.return_type,
|
||||||
@ -595,21 +629,24 @@ impl<'src> FirstPass<'src, &'src str> for weedle::mixin::OperationMixinMember<'s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPass<'src, &'src str> for weedle::mixin::AttributeMixinMember<'src> {
|
impl<'src> FirstPass<'src, (&'src str, ApiStability)> for weedle::mixin::AttributeMixinMember<'src> {
|
||||||
fn first_pass(
|
fn first_pass(
|
||||||
&'src self,
|
&'src self,
|
||||||
record: &mut FirstPassRecord<'src>,
|
record: &mut FirstPassRecord<'src>,
|
||||||
self_name: &'src str,
|
ctx: (&'src str, ApiStability),
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if util::is_chrome_only(&self.attributes) {
|
if util::is_chrome_only(&self.attributes) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
record
|
record
|
||||||
.mixins
|
.mixins
|
||||||
.get_mut(self_name)
|
.get_mut(ctx.0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.attributes
|
.attributes
|
||||||
.push(self);
|
.push(AttributeMixinData {
|
||||||
|
definition: self,
|
||||||
|
stability: ctx.1
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use crate::util::{
|
|||||||
camel_case_ident, mdn_doc, public, shouty_snake_case_ident, snake_case_ident,
|
camel_case_ident, mdn_doc, public, shouty_snake_case_ident, snake_case_ident,
|
||||||
webidl_const_v_to_backend_const_v, TypePosition,
|
webidl_const_v_to_backend_const_v, TypePosition,
|
||||||
};
|
};
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use std::collections::{BTreeSet, HashSet};
|
use std::collections::{BTreeSet, HashSet};
|
||||||
@ -55,37 +55,59 @@ impl fmt::Display for WebIDLParseError {
|
|||||||
|
|
||||||
impl std::error::Error for WebIDLParseError {}
|
impl std::error::Error for WebIDLParseError {}
|
||||||
|
|
||||||
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
fn parse(webidl_source: &str, allowed_types: Option<&[&str]>) -> Result<Program> {
|
pub(crate) enum ApiStability {
|
||||||
let definitions = match weedle::parse(webidl_source) {
|
Stable,
|
||||||
Ok(def) => def,
|
Unstable,
|
||||||
Err(e) => {
|
}
|
||||||
match &e {
|
|
||||||
weedle::Err::Incomplete(needed) => bail!("needed {:?} more bytes", needed),
|
|
||||||
weedle::Err::Error(cx) | weedle::Err::Failure(cx) => {
|
|
||||||
// Note that #[allow] here is a workaround for Geal/nom#843
|
|
||||||
// because the `Context` type here comes from `nom` and if
|
|
||||||
// something else in our crate graph enables the
|
|
||||||
// `verbose-errors` feature then we need to still compiled
|
|
||||||
// against the changed enum definition.
|
|
||||||
#[allow(unreachable_patterns)]
|
|
||||||
let remaining = match cx {
|
|
||||||
weedle::Context::Code(remaining, _) => remaining.len(),
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
let pos = webidl_source.len() - remaining;
|
|
||||||
|
|
||||||
bail!(WebIDLParseError(pos))
|
impl ApiStability {
|
||||||
}
|
pub(crate) fn is_unstable(self) -> bool {
|
||||||
|
self == Self::Unstable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for ApiStability {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Stable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_source(source: &str) -> Result<Vec<weedle::Definition>> {
|
||||||
|
weedle::parse(source).map_err(|e| {
|
||||||
|
match &e {
|
||||||
|
weedle::Err::Incomplete(needed) => anyhow::anyhow!("needed {:?} more bytes", needed),
|
||||||
|
weedle::Err::Error(cx) | weedle::Err::Failure(cx) => {
|
||||||
|
// Note that #[allow] here is a workaround for Geal/nom#843
|
||||||
|
// because the `Context` type here comes from `nom` and if
|
||||||
|
// something else in our crate graph enables the
|
||||||
|
// `verbose-errors` feature then we need to still compiled
|
||||||
|
// against the changed enum definition.
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
let remaining = match cx {
|
||||||
|
weedle::Context::Code(remaining, _) => remaining.len(),
|
||||||
|
_ => 0,
|
||||||
|
};
|
||||||
|
let pos = source.len() - remaining;
|
||||||
|
|
||||||
|
WebIDLParseError(pos).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a string of WebIDL source text into a wasm-bindgen AST.
|
||||||
|
fn parse(webidl_source: &str, unstable_source: &str, allowed_types: Option<&[&str]>) -> Result<Program> {
|
||||||
let mut first_pass_record: FirstPassRecord = Default::default();
|
let mut first_pass_record: FirstPassRecord = Default::default();
|
||||||
first_pass_record.builtin_idents = builtin_idents();
|
first_pass_record.builtin_idents = builtin_idents();
|
||||||
first_pass_record.immutable_slice_whitelist = immutable_slice_whitelist();
|
first_pass_record.immutable_slice_whitelist = immutable_slice_whitelist();
|
||||||
|
|
||||||
definitions.first_pass(&mut first_pass_record, ())?;
|
let definitions = parse_source(webidl_source)?;
|
||||||
|
definitions.first_pass(&mut first_pass_record, ApiStability::Stable)?;
|
||||||
|
|
||||||
|
let unstable_definitions = parse_source(unstable_source)?;
|
||||||
|
unstable_definitions.first_pass(&mut first_pass_record, ApiStability::Unstable)?;
|
||||||
|
|
||||||
let mut program = Default::default();
|
let mut program = Default::default();
|
||||||
let mut submodules = Vec::new();
|
let mut submodules = Vec::new();
|
||||||
|
|
||||||
@ -136,14 +158,14 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>) -> Result<Program>
|
|||||||
|
|
||||||
Ok(Program {
|
Ok(Program {
|
||||||
main: program,
|
main: program,
|
||||||
submodules: submodules,
|
submodules,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile the given WebIDL source text into Rust source text containing
|
/// Compile the given WebIDL source text into Rust source text containing
|
||||||
/// `wasm-bindgen` bindings to the things described in the WebIDL.
|
/// `wasm-bindgen` bindings to the things described in the WebIDL.
|
||||||
pub fn compile(webidl_source: &str, allowed_types: Option<&[&str]>) -> Result<String> {
|
pub fn compile(webidl_source: &str, experimental_source: &str, allowed_types: Option<&[&str]>) -> Result<String> {
|
||||||
let ast = parse(webidl_source, allowed_types)?;
|
let ast = parse(webidl_source, experimental_source, allowed_types)?;
|
||||||
Ok(compile_ast(ast))
|
Ok(compile_ast(ast))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,8 +314,10 @@ fn compile_ast(mut ast: Program) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> FirstPassRecord<'src> {
|
impl<'src> FirstPassRecord<'src> {
|
||||||
fn append_enum(&self, program: &mut ast::Program, enum_: &'src weedle::EnumDefinition<'src>) {
|
fn append_enum(&self, program: &mut ast::Program, data: &first_pass::EnumData<'src>) {
|
||||||
|
let enum_ = data.definition;
|
||||||
let variants = &enum_.values.body.list;
|
let variants = &enum_.values.body.list;
|
||||||
|
let unstable_api = data.stability.is_unstable();
|
||||||
program.imports.push(ast::Import {
|
program.imports.push(ast::Import {
|
||||||
module: ast::ImportModule::None,
|
module: ast::ImportModule::None,
|
||||||
js_namespace: None,
|
js_namespace: None,
|
||||||
@ -312,7 +336,9 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
.collect(),
|
.collect(),
|
||||||
variant_values: variants.iter().map(|v| v.0.to_string()).collect(),
|
variant_values: variants.iter().map(|v| v.0.to_string()).collect(),
|
||||||
rust_attrs: vec![syn::parse_quote!(#[derive(Copy, Clone, PartialEq, Debug)])],
|
rust_attrs: vec![syn::parse_quote!(#[derive(Copy, Clone, PartialEq, Debug)])],
|
||||||
|
unstable_api,
|
||||||
}),
|
}),
|
||||||
|
unstable_api,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,6 +378,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
ctor: true,
|
ctor: true,
|
||||||
doc_comment: Some(doc_comment),
|
doc_comment: Some(doc_comment),
|
||||||
ctor_doc_comment: None,
|
ctor_doc_comment: None,
|
||||||
|
unstable_api: data.stability.is_unstable(),
|
||||||
};
|
};
|
||||||
let mut ctor_doc_comment = Some(format!("Construct a new `{}`\n", def.identifier.0));
|
let mut ctor_doc_comment = Some(format!("Construct a new `{}`\n", def.identifier.0));
|
||||||
self.append_required_features_doc(&dict, &mut ctor_doc_comment, &[&extra_feature]);
|
self.append_required_features_doc(&dict, &mut ctor_doc_comment, &[&extra_feature]);
|
||||||
@ -504,7 +531,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
let kind = ast::ImportFunctionKind::Normal;
|
let kind = ast::ImportFunctionKind::Normal;
|
||||||
let extra = snake_case_ident(self_name);
|
let extra = snake_case_ident(self_name);
|
||||||
let extra = &[&extra[..]];
|
let extra = &[&extra[..]];
|
||||||
for mut import_function in self.create_imports(None, kind, id, data) {
|
for mut import_function in self.create_imports(None, kind, id, data, false) {
|
||||||
let mut doc = Some(doc_comment.clone());
|
let mut doc = Some(doc_comment.clone());
|
||||||
self.append_required_features_doc(&import_function, &mut doc, extra);
|
self.append_required_features_doc(&import_function, &mut doc, extra);
|
||||||
import_function.doc_comment = doc;
|
import_function.doc_comment = doc;
|
||||||
@ -512,6 +539,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
module: ast::ImportModule::None,
|
module: ast::ImportModule::None,
|
||||||
js_namespace: Some(raw_ident(self_name)),
|
js_namespace: Some(raw_ident(self_name)),
|
||||||
kind: ast::ImportKind::Function(import_function),
|
kind: ast::ImportKind::Function(import_function),
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -521,6 +549,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
program: &mut ast::Program,
|
program: &mut ast::Program,
|
||||||
self_name: &'src str,
|
self_name: &'src str,
|
||||||
member: &'src weedle::interface::ConstMember<'src>,
|
member: &'src weedle::interface::ConstMember<'src>,
|
||||||
|
unstable_api: bool,
|
||||||
) {
|
) {
|
||||||
let idl_type = member.const_type.to_idl_type(self);
|
let idl_type = member.const_type.to_idl_type(self);
|
||||||
let ty = match idl_type.to_syn_type(TypePosition::Return) {
|
let ty = match idl_type.to_syn_type(TypePosition::Return) {
|
||||||
@ -542,6 +571,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
class: Some(rust_ident(camel_case_ident(&self_name).as_str())),
|
class: Some(rust_ident(camel_case_ident(&self_name).as_str())),
|
||||||
ty,
|
ty,
|
||||||
value: webidl_const_v_to_backend_const_v(&member.const_value),
|
value: webidl_const_v_to_backend_const_v(&member.const_value),
|
||||||
|
unstable_api,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,6 +583,8 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
) {
|
) {
|
||||||
let mut doc_comment = Some(format!("The `{}` object\n\n{}", name, mdn_doc(name, None),));
|
let mut doc_comment = Some(format!("The `{}` object\n\n{}", name, mdn_doc(name, None),));
|
||||||
|
|
||||||
|
let interface_unstable = data.stability.is_unstable();
|
||||||
|
|
||||||
let mut attrs = Vec::new();
|
let mut attrs = Vec::new();
|
||||||
attrs.push(syn::parse_quote!( #[derive(Debug, Clone, PartialEq, Eq)] ));
|
attrs.push(syn::parse_quote!( #[derive(Debug, Clone, PartialEq, Eq)] ));
|
||||||
self.add_deprecated(data, &mut attrs);
|
self.add_deprecated(data, &mut attrs);
|
||||||
@ -561,6 +593,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
rust_name: rust_ident(camel_case_ident(name).as_str()),
|
rust_name: rust_ident(camel_case_ident(name).as_str()),
|
||||||
js_name: name.to_string(),
|
js_name: name.to_string(),
|
||||||
attrs,
|
attrs,
|
||||||
|
unstable_api: interface_unstable,
|
||||||
doc_comment: None,
|
doc_comment: None,
|
||||||
instanceof_shim: format!("__widl_instanceof_{}", name),
|
instanceof_shim: format!("__widl_instanceof_{}", name),
|
||||||
is_type_of: if data.has_interface {
|
is_type_of: if data.has_interface {
|
||||||
@ -596,25 +629,28 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
module: ast::ImportModule::None,
|
module: ast::ImportModule::None,
|
||||||
js_namespace: None,
|
js_namespace: None,
|
||||||
kind: ast::ImportKind::Type(import_type),
|
kind: ast::ImportKind::Type(import_type),
|
||||||
|
unstable_api: interface_unstable,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (id, op_data) in data.operations.iter() {
|
for (id, op_data) in data.operations.iter() {
|
||||||
self.member_operation(program, name, data, id, op_data);
|
self.member_operation(program, name, data, id, op_data);
|
||||||
}
|
}
|
||||||
for member in data.consts.iter() {
|
for member in data.consts.iter() {
|
||||||
self.append_const(program, name, member);
|
self.append_const(program, name, member, interface_unstable);
|
||||||
}
|
}
|
||||||
for member in data.attributes.iter() {
|
for member in data.attributes.iter() {
|
||||||
|
let member_def = member.definition;
|
||||||
self.member_attribute(
|
self.member_attribute(
|
||||||
program,
|
program,
|
||||||
name,
|
name,
|
||||||
data,
|
data,
|
||||||
member.modifier,
|
member_def.modifier,
|
||||||
member.readonly.is_some(),
|
member_def.readonly.is_some(),
|
||||||
&member.type_,
|
&member_def.type_,
|
||||||
member.identifier.0,
|
member_def.identifier.0,
|
||||||
&member.attributes,
|
&member_def.attributes,
|
||||||
data.definition_attributes,
|
data.definition_attributes,
|
||||||
|
interface_unstable || member.stability.is_unstable(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,23 +659,25 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
self.member_operation(program, name, data, id, op_data);
|
self.member_operation(program, name, data, id, op_data);
|
||||||
}
|
}
|
||||||
for member in &mixin_data.consts {
|
for member in &mixin_data.consts {
|
||||||
self.append_const(program, name, member);
|
self.append_const(program, name, member, interface_unstable);
|
||||||
}
|
}
|
||||||
for member in &mixin_data.attributes {
|
for member in &mixin_data.attributes {
|
||||||
|
let member_def = member.definition;
|
||||||
self.member_attribute(
|
self.member_attribute(
|
||||||
program,
|
program,
|
||||||
name,
|
name,
|
||||||
data,
|
data,
|
||||||
if let Some(s) = member.stringifier {
|
if let Some(s) = member_def.stringifier {
|
||||||
Some(weedle::interface::StringifierOrInheritOrStatic::Stringifier(s))
|
Some(weedle::interface::StringifierOrInheritOrStatic::Stringifier(s))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
member.readonly.is_some(),
|
member_def.readonly.is_some(),
|
||||||
&member.type_,
|
&member_def.type_,
|
||||||
member.identifier.0,
|
member_def.identifier.0,
|
||||||
&member.attributes,
|
&member_def.attributes,
|
||||||
data.definition_attributes,
|
data.definition_attributes,
|
||||||
|
interface_unstable || member.stability.is_unstable(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -656,6 +694,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
identifier: &'src str,
|
identifier: &'src str,
|
||||||
attrs: &'src Option<ExtendedAttributeList<'src>>,
|
attrs: &'src Option<ExtendedAttributeList<'src>>,
|
||||||
container_attrs: Option<&'src ExtendedAttributeList<'src>>,
|
container_attrs: Option<&'src ExtendedAttributeList<'src>>,
|
||||||
|
unstable_api: bool,
|
||||||
) {
|
) {
|
||||||
use weedle::interface::StringifierOrInheritOrStatic::*;
|
use weedle::interface::StringifierOrInheritOrStatic::*;
|
||||||
|
|
||||||
@ -673,6 +712,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static,
|
is_static,
|
||||||
attrs,
|
attrs,
|
||||||
container_attrs,
|
container_attrs,
|
||||||
|
unstable_api,
|
||||||
) {
|
) {
|
||||||
let mut doc = import_function.doc_comment.take();
|
let mut doc = import_function.doc_comment.take();
|
||||||
self.append_required_features_doc(&import_function, &mut doc, &[]);
|
self.append_required_features_doc(&import_function, &mut doc, &[]);
|
||||||
@ -688,6 +728,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static,
|
is_static,
|
||||||
attrs,
|
attrs,
|
||||||
container_attrs,
|
container_attrs,
|
||||||
|
unstable_api,
|
||||||
) {
|
) {
|
||||||
let mut doc = import_function.doc_comment.take();
|
let mut doc = import_function.doc_comment.take();
|
||||||
self.append_required_features_doc(&import_function, &mut doc, &[]);
|
self.append_required_features_doc(&import_function, &mut doc, &[]);
|
||||||
@ -742,7 +783,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
OperationId::IndexingDeleter => Some(format!("The indexing deleter\n\n")),
|
OperationId::IndexingDeleter => Some(format!("The indexing deleter\n\n")),
|
||||||
};
|
};
|
||||||
let attrs = data.definition_attributes;
|
let attrs = data.definition_attributes;
|
||||||
for mut method in self.create_imports(attrs, kind, id, op_data) {
|
for mut method in self.create_imports(attrs, kind, id, op_data, data.stability.is_unstable()) {
|
||||||
let mut doc = doc.clone();
|
let mut doc = doc.clone();
|
||||||
self.append_required_features_doc(&method, &mut doc, &[]);
|
self.append_required_features_doc(&method, &mut doc, &[]);
|
||||||
method.doc_comment = doc;
|
method.doc_comment = doc;
|
||||||
@ -843,6 +884,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
ctor: true,
|
ctor: true,
|
||||||
doc_comment: None,
|
doc_comment: None,
|
||||||
ctor_doc_comment: None,
|
ctor_doc_comment: None,
|
||||||
|
unstable_api: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,6 +231,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
catch: bool,
|
catch: bool,
|
||||||
variadic: bool,
|
variadic: bool,
|
||||||
doc_comment: Option<String>,
|
doc_comment: Option<String>,
|
||||||
|
unstable_api: bool,
|
||||||
) -> Option<ast::ImportFunction>
|
) -> Option<ast::ImportFunction>
|
||||||
where
|
where
|
||||||
'src: 'a,
|
'src: 'a,
|
||||||
@ -327,6 +328,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
},
|
},
|
||||||
kind,
|
kind,
|
||||||
doc_comment,
|
doc_comment,
|
||||||
|
unstable_api,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,6 +341,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
attrs: &Option<ExtendedAttributeList>,
|
attrs: &Option<ExtendedAttributeList>,
|
||||||
container_attrs: Option<&ExtendedAttributeList>,
|
container_attrs: Option<&ExtendedAttributeList>,
|
||||||
|
unstable_api: bool,
|
||||||
) -> Option<ast::ImportFunction> {
|
) -> Option<ast::ImportFunction> {
|
||||||
let kind = ast::OperationKind::Getter(Some(raw_ident(name)));
|
let kind = ast::OperationKind::Getter(Some(raw_ident(name)));
|
||||||
let kind = self.import_function_kind(self_name, is_static, kind);
|
let kind = self.import_function_kind(self_name, is_static, kind);
|
||||||
@ -357,6 +360,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
name,
|
name,
|
||||||
mdn_doc(self_name, Some(name))
|
mdn_doc(self_name, Some(name))
|
||||||
)),
|
)),
|
||||||
|
unstable_api,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,6 +373,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
is_static: bool,
|
is_static: bool,
|
||||||
attrs: &Option<ExtendedAttributeList>,
|
attrs: &Option<ExtendedAttributeList>,
|
||||||
container_attrs: Option<&ExtendedAttributeList>,
|
container_attrs: Option<&ExtendedAttributeList>,
|
||||||
|
unstable_api: bool,
|
||||||
) -> Option<ast::ImportFunction> {
|
) -> Option<ast::ImportFunction> {
|
||||||
let kind = ast::OperationKind::Setter(Some(raw_ident(name)));
|
let kind = ast::OperationKind::Setter(Some(raw_ident(name)));
|
||||||
let kind = self.import_function_kind(self_name, is_static, kind);
|
let kind = self.import_function_kind(self_name, is_static, kind);
|
||||||
@ -387,6 +392,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
name,
|
name,
|
||||||
mdn_doc(self_name, Some(name))
|
mdn_doc(self_name, Some(name))
|
||||||
)),
|
)),
|
||||||
|
unstable_api,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,6 +420,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
kind: ast::ImportFunctionKind,
|
kind: ast::ImportFunctionKind,
|
||||||
id: &OperationId<'src>,
|
id: &OperationId<'src>,
|
||||||
data: &OperationData<'src>,
|
data: &OperationData<'src>,
|
||||||
|
unstable_api: bool,
|
||||||
) -> Vec<ast::ImportFunction> {
|
) -> Vec<ast::ImportFunction> {
|
||||||
// First up, prune all signatures that reference unsupported arguments.
|
// First up, prune all signatures that reference unsupported arguments.
|
||||||
// We won't consider these until said arguments are implemented.
|
// We won't consider these until said arguments are implemented.
|
||||||
@ -618,6 +625,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
catch,
|
catch,
|
||||||
variadic,
|
variadic,
|
||||||
None,
|
None,
|
||||||
|
unstable_api,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if !variadic {
|
if !variadic {
|
||||||
@ -644,6 +652,7 @@ impl<'src> FirstPassRecord<'src> {
|
|||||||
catch,
|
catch,
|
||||||
false,
|
false,
|
||||||
None,
|
None,
|
||||||
|
unstable_api,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,7 @@
|
|||||||
- [Function Overloads](./web-sys/function-overloads.md)
|
- [Function Overloads](./web-sys/function-overloads.md)
|
||||||
- [Type Translations](./web-sys/type-translations.md)
|
- [Type Translations](./web-sys/type-translations.md)
|
||||||
- [Inheritance](./web-sys/inheritance.md)
|
- [Inheritance](./web-sys/inheritance.md)
|
||||||
|
- [Unstable APIs](./web-sys/unstable-apis.md)
|
||||||
|
|
||||||
- [Testing with `wasm-bindgen-test`](./wasm-bindgen-test/index.md)
|
- [Testing with `wasm-bindgen-test`](./wasm-bindgen-test/index.md)
|
||||||
- [Usage](./wasm-bindgen-test/usage.md)
|
- [Usage](./wasm-bindgen-test/usage.md)
|
||||||
|
31
guide/src/web-sys/unstable-apis.md
Normal file
31
guide/src/web-sys/unstable-apis.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Unstable APIs
|
||||||
|
|
||||||
|
It's common for browsers to implement parts of a web API while the specification
|
||||||
|
for that API is still being written. The API may require frequent changes as the
|
||||||
|
specification continues to be developed, so the WebIDL is relatively unstable.
|
||||||
|
|
||||||
|
This causes some challenges for `web-sys` because it means `web-sys` would have
|
||||||
|
to make breaking API changes whenever the WebIDL changes. It also means that
|
||||||
|
previously published `web-sys` versions would be invalid, because the browser
|
||||||
|
API may have been changed to match the updated WebIDL.
|
||||||
|
|
||||||
|
To avoid frequent breaking changes for unstable APIs, `web-sys` hides all
|
||||||
|
unstable APIs through an attribute that looks like:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[cfg(web_sys_unstable_apis)]
|
||||||
|
pub struct Foo;
|
||||||
|
```
|
||||||
|
|
||||||
|
By hiding unstable APIs through an attribute, it's necessary for crates to
|
||||||
|
explicitly opt-in to these reduced stability guarantees in order to use these
|
||||||
|
APIs. Specifically, these APIs do not follow semver and may break whenever the
|
||||||
|
WebIDL changes.
|
||||||
|
|
||||||
|
Crates can opt-in to unstable APIs at compile-time by passing the `cfg` flag
|
||||||
|
`web_sys_unstable_apis`. Typically the `RUSTFLAGS` environment variable is used
|
||||||
|
to do this. For example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RUSTFLAGS=--cfg=web_sys_unstable_apis cargo run
|
||||||
|
```
|
Loading…
x
Reference in New Issue
Block a user