/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ext/webgpu/webidl.rs
532 строки
13 KB
Leo Kettmeir
chore: update webgpu (#34319)
08 июн 2026, 23:29
Не верифицирован
08 июн 2026, 23:29
2b313e2
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. use std::borrow::Cow; use deno_core::WebIDL; use deno_core::cppgc::Ref; use deno_core::v8; use deno_core::webidl::ContextFn; use deno_core::webidl::IntOptions; use deno_core::webidl::WebIdlConverter; use deno_core::webidl::WebIdlError; use deno_core::webidl::WebIdlErrorKind; use deno_error::JsErrorBox; #[derive(WebIDL)] #[webidl(dictionary)] pub(crate) struct GPUExtent3DDict { #[options(enforce_range = true)] width: u32, #[webidl(default = 1)] #[options(enforce_range = true)] height: u32, #[webidl(default = 1)] #[options(enforce_range = true)] depth_or_array_layers: u32, } pub(crate) enum GPUExtent3D { Dict(GPUExtent3DDict), Sequence((u32, u32, u32)), } impl<'a> WebIdlConverter<'a> for GPUExtent3D { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, options: &Self::Options, ) -> Result<Self, WebIdlError> { if value.is_null_or_undefined() { return Ok(GPUExtent3D::Dict(GPUExtent3DDict::convert( scope, value, prefix, context.borrowed(), options, )?)); } if let Ok(obj) = value.try_cast::<v8::Object>() { let iter = v8::Symbol::get_iterator(scope); if let Some(iter) = obj.get(scope, iter.into()) && !iter.is_undefined() { let conv = <Vec<u32>>::convert( scope, value, prefix.clone(), context.borrowed(), &IntOptions { clamp: false, enforce_range: true, }, )?; if conv.is_empty() || conv.len() > 3 { return Err(WebIdlError::other( prefix, context, JsErrorBox::type_error(format!( "A sequence of number used as a GPUExtent3D must have between 1 and 3 elements, received {} elements", conv.len() )), )); } let mut iter = conv.into_iter(); return Ok(GPUExtent3D::Sequence(( iter.next().unwrap(), iter.next().unwrap_or(1), iter.next().unwrap_or(1), ))); } return Ok(GPUExtent3D::Dict(GPUExtent3DDict::convert( scope, value, prefix, context, options, )?)); } Err(WebIdlError::new( prefix, context, WebIdlErrorKind::ConvertToConverterType( "sequence<GPUIntegerCoordinate> or GPUExtent3DDict", ), )) } } impl From<GPUExtent3D> for wgpu_types::Extent3d { fn from(value: GPUExtent3D) -> Self { match value { GPUExtent3D::Dict(dict) => Self { width: dict.width, height: dict.height, depth_or_array_layers: dict.depth_or_array_layers, }, GPUExtent3D::Sequence((width, height, depth)) => Self { width, height, depth_or_array_layers: depth, }, } } } #[derive(WebIDL)] #[webidl(dictionary)] pub(crate) struct GPUOrigin3DDict { #[webidl(default = 0)] #[options(enforce_range = true)] x: u32, #[webidl(default = 0)] #[options(enforce_range = true)] y: u32, #[webidl(default = 0)] #[options(enforce_range = true)] z: u32, } pub(crate) enum GPUOrigin3D { Dict(GPUOrigin3DDict), Sequence((u32, u32, u32)), } impl Default for GPUOrigin3D { fn default() -> Self { GPUOrigin3D::Sequence((0, 0, 0)) } } impl<'a> WebIdlConverter<'a> for GPUOrigin3D { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, options: &Self::Options, ) -> Result<Self, WebIdlError> { if value.is_null_or_undefined() { return Ok(GPUOrigin3D::Dict(GPUOrigin3DDict::convert( scope, value, prefix, context.borrowed(), options, )?)); } if let Ok(obj) = value.try_cast::<v8::Object>() { let iter = v8::Symbol::get_iterator(scope); if let Some(iter) = obj.get(scope, iter.into()) && !iter.is_undefined() { let conv = <Vec<u32>>::convert( scope, value, prefix.clone(), context.borrowed(), &IntOptions { clamp: false, enforce_range: true, }, )?; if conv.len() > 3 { return Err(WebIdlError::other( prefix, context, JsErrorBox::type_error(format!( "A sequence of number used as a GPUOrigin3D must have at most 3 elements, received {} elements", conv.len() )), )); } let mut iter = conv.into_iter(); return Ok(GPUOrigin3D::Sequence(( iter.next().unwrap_or(0), iter.next().unwrap_or(0), iter.next().unwrap_or(0), ))); } return Ok(GPUOrigin3D::Dict(GPUOrigin3DDict::convert( scope, value, prefix, context, options, )?)); } Err(WebIdlError::new( prefix, context, WebIdlErrorKind::ConvertToConverterType( "sequence<GPUIntegerCoordinate> or GPUOrigin3DDict", ), )) } } impl From<GPUOrigin3D> for wgpu_types::Origin3d { fn from(value: GPUOrigin3D) -> Self { match value { GPUOrigin3D::Dict(dict) => Self { x: dict.x, y: dict.y, z: dict.z, }, GPUOrigin3D::Sequence((x, y, z)) => Self { x, y, z }, } } } #[derive(WebIDL)] #[webidl(dictionary)] pub(crate) struct GPUColorDict { r: f64, g: f64, b: f64, a: f64, } pub(crate) enum GPUColor { Dict(GPUColorDict), Sequence((f64, f64, f64, f64)), } impl<'a> WebIdlConverter<'a> for GPUColor { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, options: &Self::Options, ) -> Result<Self, WebIdlError> { if value.is_null_or_undefined() { return Ok(GPUColor::Dict(GPUColorDict::convert( scope, value, prefix, context.borrowed(), options, )?)); } if let Ok(obj) = value.try_cast::<v8::Object>() { let iter = v8::Symbol::get_iterator(scope); if let Some(iter) = obj.get(scope, iter.into()) && !iter.is_undefined() { let conv = <Vec<f64>>::convert( scope, value, prefix.clone(), context.borrowed(), options, )?; if conv.len() != 4 { return Err(WebIdlError::other( prefix, context, JsErrorBox::type_error(format!( "A sequence of number used as a GPUColor must have exactly 4 elements, received {} elements", conv.len() )), )); } let mut iter = conv.into_iter(); return Ok(GPUColor::Sequence(( iter.next().unwrap(), iter.next().unwrap(), iter.next().unwrap(), iter.next().unwrap(), ))); } return Ok(GPUColor::Dict(GPUColorDict::convert( scope, value, prefix, context, options, )?)); } Err(WebIdlError::new( prefix, context, WebIdlErrorKind::ConvertToConverterType( "sequence<GPUIntegerCoordinate> or GPUOrigin3DDict", ), )) } } impl From<GPUColor> for wgpu_types::Color { fn from(value: GPUColor) -> Self { match value { GPUColor::Dict(dict) => Self { r: dict.r, g: dict.g, b: dict.b, a: dict.a, }, GPUColor::Sequence((r, g, b, a)) => Self { r, g, b, a }, } } } #[derive(WebIDL)] #[webidl(enum)] pub(crate) enum GPUAutoLayoutMode { Auto, } pub(crate) enum GPUPipelineLayoutOrGPUAutoLayoutMode { PipelineLayout(Ref<crate::pipeline_layout::GPUPipelineLayout>), AutoLayoutMode(GPUAutoLayoutMode), } impl From<GPUPipelineLayoutOrGPUAutoLayoutMode> for Option<wgpu_core::id::PipelineLayoutId> { fn from(value: GPUPipelineLayoutOrGPUAutoLayoutMode) -> Self { match value { GPUPipelineLayoutOrGPUAutoLayoutMode::PipelineLayout(layout) => { Some(layout.id) } GPUPipelineLayoutOrGPUAutoLayoutMode::AutoLayoutMode( GPUAutoLayoutMode::Auto, ) => None, } } } impl<'a> WebIdlConverter<'a> for GPUPipelineLayoutOrGPUAutoLayoutMode { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, options: &Self::Options, ) -> Result<Self, WebIdlError> { if value.is_object() { Ok(Self::PipelineLayout(WebIdlConverter::convert( scope, value, prefix, context, options, )?)) } else { Ok(Self::AutoLayoutMode(WebIdlConverter::convert( scope, value, prefix, context, options, )?)) } } } impl<'a> WebIdlConverter<'a> for GPUFeatureName { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, _options: &Self::Options, ) -> Result<Self, WebIdlError> { let s = value.to_rust_string_lossy(scope); s.parse().map(Self).map_err(|()| { WebIdlError::new( prefix, context, WebIdlErrorKind::InvalidEnumVariant { converter: "GPUFeatureName", variant: s, }, ) }) } } /// A WebGPU optional feature. /// /// Named after the WebIDL enum, which represents features as strings, but we store the /// feature as bitflag, which must always have exactly one bit set (across both the WebGPU /// and wgpu native features). #[derive(Clone, Copy, Hash, Eq, PartialEq)] pub struct GPUFeatureName(wgpu_types::Features); impl From<GPUFeatureName> for wgpu_types::Features { fn from(value: GPUFeatureName) -> wgpu_types::Features { value.0 } } #[derive(Clone, Copy)] pub struct GPUTextureUsageFlags(pub wgpu_types::TextureUsages); impl<'a> WebIdlConverter<'a> for GPUTextureUsageFlags { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, _options: &Self::Options, ) -> Result<Self, WebIdlError> { let flags_value = u32::convert( scope, value, prefix.clone(), context.borrowed(), &IntOptions { clamp: false, enforce_range: true, }, )?; let flags = wgpu_types::TextureUsages::from_bits(flags_value).ok_or_else(|| { WebIdlError::other( prefix, context, JsErrorBox::type_error("usage is not valid"), ) })?; Ok(GPUTextureUsageFlags(flags)) } } impl From<GPUTextureUsageFlags> for wgpu_types::TextureUsages { fn from(value: GPUTextureUsageFlags) -> Self { value.0 } } impl GPUTextureUsageFlags { pub fn bits(&self) -> u32 { self.0.bits() } } #[derive(Clone, Copy)] pub(crate) struct GPUShaderStageFlags(pub(crate) wgpu_types::ShaderStages); impl<'a> WebIdlConverter<'a> for GPUShaderStageFlags { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, _options: &Self::Options, ) -> Result<Self, WebIdlError> { let flags_value = u32::convert( scope, value, prefix.clone(), context.borrowed(), &IntOptions { clamp: false, enforce_range: true, }, )?; let flags = wgpu_types::ShaderStages::from_bits(flags_value).ok_or_else(|| { WebIdlError::other( prefix, context, JsErrorBox::type_error("shader stage is not valid"), ) })?; Ok(GPUShaderStageFlags(flags)) } } impl From<GPUShaderStageFlags> for wgpu_types::ShaderStages { fn from(value: GPUShaderStageFlags) -> Self { value.0 } } #[derive(Clone, Copy)] pub(crate) struct GPUColorWriteFlags(pub(crate) wgpu_types::ColorWrites); impl<'a> WebIdlConverter<'a> for GPUColorWriteFlags { type Options = (); fn convert<'b>( scope: &mut v8::PinScope<'a, '_>, value: v8::Local<'a, v8::Value>, prefix: Cow<'static, str>, context: ContextFn<'b>, _options: &Self::Options, ) -> Result<Self, WebIdlError> { let flags_value = u32::convert( scope, value, prefix.clone(), context.borrowed(), &IntOptions { clamp: false, enforce_range: true, }, )?; // WebGPU specifies a validation error for invalid color write mask values. // We propagate invalid bits here; wgpu_core will validate it. Ok(GPUColorWriteFlags( wgpu_types::ColorWrites::from_bits_retain(flags_value), )) } } impl From<GPUColorWriteFlags> for wgpu_types::ColorWrites { fn from(value: GPUColorWriteFlags) -> Self { value.0 } }