wasm_webidl_bindings/
ast.rs

1#[cfg(feature = "text")]
2use crate::text;
3use id_arena::{Arena, Id};
4use std::borrow::Cow;
5use std::collections::HashMap;
6
7#[derive(Clone, Debug, Default)]
8pub struct WebidlBindings {
9    pub types: WebidlTypes,
10    pub bindings: FunctionBindings,
11    pub binds: Binds,
12}
13
14impl walrus::CustomSection for WebidlBindings {
15    fn name(&self) -> &str {
16        "webidl-bindings"
17    }
18
19    fn data(&self, ids_to_indices: &walrus::IdsToIndices) -> Cow<[u8]> {
20        let mut data = vec![];
21        crate::binary::encode(self, ids_to_indices, &mut data)
22            .expect("writing into a vec never fails");
23        data.into()
24    }
25}
26
27macro_rules! id_newtypes {
28    ( $( $name:ident($inner:ty), )* ) => {
29        $(
30            #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
31            pub struct $name(pub(crate) Id<$inner>);
32
33            impl From<$name> for Id<$inner> {
34                #[inline]
35                fn from(id: $name) -> Id<$inner> {
36                    id.0
37                }
38            }
39        )*
40    }
41}
42
43id_newtypes! {
44    WebidlFunctionId(WebidlCompoundType),
45    WebidlDictionaryId(WebidlCompoundType),
46    WebidlEnumerationId(WebidlCompoundType),
47    WebidlUnionId(WebidlCompoundType),
48
49    ImportBindingId(FunctionBinding),
50    ExportBindingId(FunctionBinding),
51}
52
53#[derive(Clone, Debug, Default)]
54pub struct WebidlTypes {
55    pub(crate) names: HashMap<String, Id<WebidlCompoundType>>,
56    indices: Vec<Id<WebidlCompoundType>>,
57    pub(crate) arena: Arena<WebidlCompoundType>,
58}
59
60pub trait WebidlTypeId: Into<WebidlCompoundType> {
61    type Id: Into<Id<WebidlCompoundType>>;
62
63    #[doc(hidden)]
64    fn wrap(id: Id<WebidlCompoundType>) -> Self::Id;
65    #[doc(hidden)]
66    fn get(ty: &WebidlCompoundType) -> Option<&Self>;
67    #[doc(hidden)]
68    fn get_mut(ty: &mut WebidlCompoundType) -> Option<&mut Self>;
69}
70
71macro_rules! impl_webidl_type_id {
72    ( $( $id:ident => $variant:ident($ty:ty); )* ) => {
73        $(
74            impl WebidlTypeId for $ty {
75                type Id = $id;
76
77                fn wrap(id: Id<WebidlCompoundType>) -> Self::Id {
78                    $id(id)
79                }
80
81                fn get(ty: &WebidlCompoundType) -> Option<&Self> {
82                    if let WebidlCompoundType::$variant(x) = ty {
83                        Some(x)
84                    } else {
85                        None
86                    }
87                }
88
89                fn get_mut(ty: &mut WebidlCompoundType) -> Option<&mut Self> {
90                    if let WebidlCompoundType::$variant(x) = ty {
91                        Some(x)
92                    } else {
93                        None
94                    }
95                }
96            }
97
98            impl From<$id> for WebidlTypeRef {
99                fn from(x: $id) -> WebidlTypeRef {
100                    WebidlTypeRef::Id(x.into())
101                }
102            }
103        )*
104    }
105}
106
107impl_webidl_type_id! {
108    WebidlFunctionId => Function(WebidlFunction);
109    WebidlDictionaryId => Dictionary(WebidlDictionary);
110    WebidlEnumerationId => Enumeration(WebidlEnumeration);
111    WebidlUnionId => Union(WebidlUnion);
112}
113
114impl WebidlTypeId for WebidlCompoundType {
115    type Id = Id<WebidlCompoundType>;
116
117    fn wrap(id: Id<WebidlCompoundType>) -> Self::Id {
118        id
119    }
120
121    fn get(ty: &WebidlCompoundType) -> Option<&Self> {
122        Some(ty)
123    }
124
125    fn get_mut(ty: &mut WebidlCompoundType) -> Option<&mut Self> {
126        Some(ty)
127    }
128}
129
130impl WebidlTypes {
131    pub fn by_name(&self, name: &str) -> Option<Id<WebidlCompoundType>> {
132        self.names.get(name).cloned()
133    }
134
135    pub fn by_index(&self, index: u32) -> Option<Id<WebidlCompoundType>> {
136        self.indices.get(index as usize).cloned()
137    }
138
139    pub fn get<T>(&self, id: T::Id) -> Option<&T>
140    where
141        T: WebidlTypeId,
142    {
143        self.arena.get(id.into()).and_then(T::get)
144    }
145
146    pub fn get_mut<T>(&mut self, id: T::Id) -> Option<&mut T>
147    where
148        T: WebidlTypeId,
149    {
150        self.arena.get_mut(id.into()).and_then(T::get_mut)
151    }
152
153    pub fn insert<T>(&mut self, ty: T) -> T::Id
154    where
155        T: WebidlTypeId,
156    {
157        let id = self.arena.alloc(ty.into());
158        self.indices.push(id);
159        T::wrap(id)
160    }
161}
162
163#[derive(Clone, Debug, Default)]
164pub struct FunctionBindings {
165    pub(crate) names: HashMap<String, Id<FunctionBinding>>,
166    indices: Vec<Id<FunctionBinding>>,
167    pub(crate) arena: Arena<FunctionBinding>,
168}
169
170pub trait FunctionBindingId: Into<FunctionBinding> {
171    type Id: Into<Id<FunctionBinding>>;
172
173    #[doc(hidden)]
174    fn wrap(id: Id<FunctionBinding>) -> Self::Id;
175    #[doc(hidden)]
176    fn get(b: &FunctionBinding) -> Option<&Self>;
177    #[doc(hidden)]
178    fn get_mut(b: &mut FunctionBinding) -> Option<&mut Self>;
179}
180
181macro_rules! impl_function_binding_id {
182    ( $( $id:ident => $variant:ident($ty:ident); )* ) => {
183        $(
184            impl FunctionBindingId for $ty {
185                type Id = $id;
186
187                fn wrap(id: Id<FunctionBinding>) -> Self::Id {
188                    $id(id)
189                }
190
191                fn get(ty: &FunctionBinding) -> Option<&Self> {
192                    if let FunctionBinding::$variant(x) = ty {
193                        Some(x)
194                    } else {
195                        None
196                    }
197                }
198
199                fn get_mut(ty: &mut FunctionBinding) -> Option<&mut Self> {
200                    if let FunctionBinding::$variant(x) = ty {
201                        Some(x)
202                    } else {
203                        None
204                    }
205                }
206            }
207        )*
208    }
209}
210
211impl FunctionBindingId for FunctionBinding {
212    type Id = Id<FunctionBinding>;
213
214    fn wrap(id: Id<FunctionBinding>) -> Self::Id {
215        id
216    }
217
218    fn get(ty: &FunctionBinding) -> Option<&Self> {
219        Some(ty)
220    }
221
222    fn get_mut(ty: &mut FunctionBinding) -> Option<&mut Self> {
223        Some(ty)
224    }
225}
226
227impl_function_binding_id! {
228    ImportBindingId => Import(ImportBinding);
229    ExportBindingId => Export(ExportBinding);
230}
231
232impl FunctionBindings {
233    pub fn by_name(&self, name: &str) -> Option<Id<FunctionBinding>> {
234        self.names.get(name).cloned()
235    }
236
237    pub fn by_index(&self, index: u32) -> Option<Id<FunctionBinding>> {
238        self.indices.get(index as usize).cloned()
239    }
240
241    pub fn get<T>(&self, id: T::Id) -> Option<&T>
242    where
243        T: FunctionBindingId,
244    {
245        self.arena.get(id.into()).and_then(T::get)
246    }
247
248    pub fn get_mut<T>(&mut self, id: T::Id) -> Option<&mut T>
249    where
250        T: FunctionBindingId,
251    {
252        self.arena.get_mut(id.into()).and_then(T::get_mut)
253    }
254
255    pub fn insert<T>(&mut self, binding: T) -> T::Id
256    where
257        T: FunctionBindingId,
258    {
259        let id = self.arena.alloc(binding.into());
260        self.indices.push(id);
261        T::wrap(id)
262    }
263}
264
265#[derive(Clone, Debug, Default)]
266pub struct Binds {
267    pub(crate) arena: id_arena::Arena<Bind>,
268}
269
270impl Binds {
271    pub fn get(&self, id: Id<Bind>) -> Option<&Bind> {
272        self.arena.get(id.into())
273    }
274
275    pub fn get_mut(&mut self, id: Id<Bind>) -> Option<&mut Bind> {
276        self.arena.get_mut(id.into())
277    }
278
279    pub fn insert(&mut self, bind: Bind) -> Id<Bind> {
280        self.arena.alloc(bind)
281    }
282
283    pub fn iter<'a>(&'a self) -> impl Iterator<Item = (Id<Bind>, &'a Bind)> + 'a {
284        self.arena.iter()
285    }
286}
287
288#[derive(Debug)]
289pub struct BuildAstActions<'a> {
290    section: &'a mut WebidlBindings,
291    module: &'a walrus::Module,
292    ids: &'a walrus::IndicesToIds,
293}
294
295impl<'a> BuildAstActions<'a> {
296    pub fn new(
297        section: &'a mut WebidlBindings,
298        module: &'a walrus::Module,
299        ids: &'a walrus::IndicesToIds,
300    ) -> Self {
301        BuildAstActions {
302            section,
303            module,
304            ids,
305        }
306    }
307}
308
309#[cfg(feature = "text")]
310impl<'a> text::Actions for BuildAstActions<'a> {
311    type WebidlBindingsSection = ();
312    fn webidl_bindings_section(&mut self, _types: (), _bindings: ()) {}
313
314    type WebidlTypeSubsection = ();
315    fn webidl_type_subsection(&mut self, _types: Vec<()>) {}
316
317    type WebidlType = ();
318    fn webidl_type(&mut self, name: Option<&str>, ty: Id<WebidlCompoundType>) {
319        if let Some(name) = name {
320            self.section.types.names.insert(name.to_string(), ty);
321        }
322    }
323
324    type WebidlCompoundType = Id<WebidlCompoundType>;
325
326    type WebidlFunction = WebidlFunctionId;
327    fn webidl_function(
328        &mut self,
329        kind: Option<WebidlFunctionKind>,
330        params: Option<Vec<WebidlTypeRef>>,
331        result: Option<WebidlTypeRef>,
332    ) -> WebidlFunctionId {
333        let kind = kind.unwrap_or(WebidlFunctionKind::Static);
334        let params = params.unwrap_or(vec![]);
335        self.section.types.insert(WebidlFunction {
336            kind,
337            params,
338            result,
339        })
340    }
341
342    type WebidlFunctionKind = WebidlFunctionKind;
343
344    type WebidlFunctionKindMethod = WebidlFunctionKindMethod;
345    fn webidl_function_kind_method(&mut self, ty: WebidlTypeRef) -> WebidlFunctionKindMethod {
346        WebidlFunctionKindMethod { ty }
347    }
348
349    type WebidlFunctionKindConstructor = WebidlFunctionKind;
350    fn webidl_function_kind_constructor_default_new_target(&mut self) -> WebidlFunctionKind {
351        WebidlFunctionKind::Constructor
352    }
353
354    type WebidlFunctionParams = Vec<WebidlTypeRef>;
355    fn webidl_function_params(&mut self, tys: Vec<WebidlTypeRef>) -> Vec<WebidlTypeRef> {
356        tys
357    }
358
359    type WebidlFunctionResult = WebidlTypeRef;
360    fn webidl_function_result(&mut self, ty: WebidlTypeRef) -> WebidlTypeRef {
361        ty
362    }
363
364    type WebidlDictionary = WebidlDictionaryId;
365    fn webidl_dictionary(&mut self, fields: Vec<WebidlDictionaryField>) -> WebidlDictionaryId {
366        self.section.types.insert(WebidlDictionary { fields })
367    }
368
369    type WebidlDictionaryField = WebidlDictionaryField;
370    fn webidl_dictionary_field(
371        &mut self,
372        name: String,
373        ty: WebidlTypeRef,
374    ) -> WebidlDictionaryField {
375        WebidlDictionaryField { name, ty }
376    }
377
378    type WebidlDictionaryFieldName = String;
379    fn webidl_dictionary_field_name(&mut self, name: &str) -> String {
380        name.into()
381    }
382
383    type WebidlEnumeration = WebidlEnumerationId;
384    fn webidl_enumeration(&mut self, values: Vec<String>) -> WebidlEnumerationId {
385        self.section.types.insert(WebidlEnumeration { values })
386    }
387
388    type WebidlEnumerationValue = String;
389    fn webidl_enumeration_value(&mut self, value: &str) -> String {
390        value.into()
391    }
392
393    type WebidlUnion = WebidlUnionId;
394    fn webidl_union(&mut self, members: Vec<WebidlTypeRef>) -> WebidlUnionId {
395        self.section.types.insert(WebidlUnion { members })
396    }
397
398    type WebidlFunctionBindingsSubsection = ();
399    fn webidl_function_bindings_subsection(&mut self, _bindings: Vec<()>, _binds: Vec<()>) {}
400
401    type FunctionBinding = ();
402
403    type ImportBinding = ();
404    fn import_binding(
405        &mut self,
406        name: Option<&str>,
407        wasm_ty: walrus::TypeId,
408        webidl_ty: WebidlTypeRef,
409        params: Option<OutgoingBindingMap>,
410        result: Option<IncomingBindingMap>,
411    ) {
412        let id: ImportBindingId = self.section.bindings.insert(ImportBinding {
413            wasm_ty,
414            webidl_ty,
415            params: params.unwrap_or_else(|| OutgoingBindingMap { bindings: vec![] }),
416            result: result.unwrap_or_else(|| IncomingBindingMap { bindings: vec![] }),
417        });
418        if let Some(name) = name {
419            self.section
420                .bindings
421                .names
422                .insert(name.to_string(), id.into());
423        }
424    }
425
426    type ExportBinding = ();
427    fn export_binding(
428        &mut self,
429        name: Option<&str>,
430        wasm_ty: walrus::TypeId,
431        webidl_ty: WebidlTypeRef,
432        params: Option<IncomingBindingMap>,
433        result: Option<OutgoingBindingMap>,
434    ) {
435        let id: ExportBindingId = self.section.bindings.insert(ExportBinding {
436            wasm_ty,
437            webidl_ty,
438            params: params.unwrap_or_else(|| IncomingBindingMap { bindings: vec![] }),
439            result: result.unwrap_or_else(|| OutgoingBindingMap { bindings: vec![] }),
440        });
441        if let Some(name) = name {
442            self.section
443                .bindings
444                .names
445                .insert(name.to_string(), id.into());
446        }
447    }
448
449    type Bind = ();
450    fn bind(&mut self, func: walrus::FunctionId, binding: Id<FunctionBinding>) {
451        self.section.binds.insert(Bind { func, binding });
452    }
453
454    type OutgoingBindingMap = OutgoingBindingMap;
455    fn outgoing_binding_map(
456        &mut self,
457        bindings: Vec<OutgoingBindingExpression>,
458    ) -> OutgoingBindingMap {
459        OutgoingBindingMap { bindings }
460    }
461
462    type IncomingBindingMap = IncomingBindingMap;
463    fn incoming_binding_map(
464        &mut self,
465        bindings: Vec<IncomingBindingExpression>,
466    ) -> IncomingBindingMap {
467        IncomingBindingMap { bindings }
468    }
469
470    type OutgoingBindingExpression = OutgoingBindingExpression;
471
472    type OutgoingBindingExpressionAs = OutgoingBindingExpressionAs;
473    fn outgoing_binding_expression_as(
474        &mut self,
475        ty: WebidlTypeRef,
476        idx: u32,
477    ) -> OutgoingBindingExpressionAs {
478        OutgoingBindingExpressionAs { ty, idx }
479    }
480
481    type OutgoingBindingExpressionUtf8Str = OutgoingBindingExpressionUtf8Str;
482    fn outgoing_binding_expression_utf8_str(
483        &mut self,
484        ty: WebidlTypeRef,
485        offset: u32,
486        length: u32,
487    ) -> OutgoingBindingExpressionUtf8Str {
488        OutgoingBindingExpressionUtf8Str { ty, offset, length }
489    }
490
491    type OutgoingBindingExpressionUtf8CStr = OutgoingBindingExpressionUtf8CStr;
492    fn outgoing_binding_expression_utf8_c_str(
493        &mut self,
494        ty: WebidlTypeRef,
495        offset: u32,
496    ) -> OutgoingBindingExpressionUtf8CStr {
497        OutgoingBindingExpressionUtf8CStr { ty, offset }
498    }
499
500    type OutgoingBindingExpressionI32ToEnum = OutgoingBindingExpressionI32ToEnum;
501    fn outgoing_binding_expression_i32_to_enum(
502        &mut self,
503        ty: WebidlTypeRef,
504        idx: u32,
505    ) -> OutgoingBindingExpressionI32ToEnum {
506        OutgoingBindingExpressionI32ToEnum { ty, idx }
507    }
508
509    type OutgoingBindingExpressionView = OutgoingBindingExpressionView;
510    fn outgoing_binding_expression_view(
511        &mut self,
512        ty: WebidlTypeRef,
513        offset: u32,
514        length: u32,
515    ) -> OutgoingBindingExpressionView {
516        OutgoingBindingExpressionView { ty, offset, length }
517    }
518
519    type OutgoingBindingExpressionCopy = OutgoingBindingExpressionCopy;
520    fn outgoing_binding_expression_copy(
521        &mut self,
522        ty: WebidlTypeRef,
523        offset: u32,
524        length: u32,
525    ) -> OutgoingBindingExpressionCopy {
526        OutgoingBindingExpressionCopy { ty, offset, length }
527    }
528
529    type OutgoingBindingExpressionDict = OutgoingBindingExpressionDict;
530    fn outgoing_binding_expression_dict(
531        &mut self,
532        ty: WebidlTypeRef,
533        fields: Vec<OutgoingBindingExpression>,
534    ) -> OutgoingBindingExpressionDict {
535        OutgoingBindingExpressionDict { ty, fields }
536    }
537
538    type OutgoingBindingExpressionBindExport = OutgoingBindingExpressionBindExport;
539    fn outgoing_binding_expression_bind_export(
540        &mut self,
541        ty: WebidlTypeRef,
542        binding: Id<FunctionBinding>,
543        idx: u32,
544    ) -> OutgoingBindingExpressionBindExport {
545        OutgoingBindingExpressionBindExport { ty, binding, idx }
546    }
547
548    type IncomingBindingExpression = IncomingBindingExpression;
549
550    type IncomingBindingExpressionGet = IncomingBindingExpressionGet;
551    fn incoming_binding_expression_get(&mut self, idx: u32) -> IncomingBindingExpressionGet {
552        IncomingBindingExpressionGet { idx }
553    }
554
555    type IncomingBindingExpressionAs = IncomingBindingExpressionAs;
556    fn incoming_binding_expression_as(
557        &mut self,
558        ty: walrus::ValType,
559        expr: IncomingBindingExpression,
560    ) -> IncomingBindingExpressionAs {
561        let expr = Box::new(expr);
562        IncomingBindingExpressionAs { ty, expr }
563    }
564
565    type IncomingBindingExpressionAllocUtf8Str = IncomingBindingExpressionAllocUtf8Str;
566    fn incoming_binding_expression_alloc_utf8_str(
567        &mut self,
568        alloc_func_name: &str,
569        expr: IncomingBindingExpression,
570    ) -> IncomingBindingExpressionAllocUtf8Str {
571        let alloc_func_name = alloc_func_name.into();
572        let expr = Box::new(expr);
573        IncomingBindingExpressionAllocUtf8Str {
574            alloc_func_name,
575            expr,
576        }
577    }
578
579    type IncomingBindingExpressionAllocCopy = IncomingBindingExpressionAllocCopy;
580    fn incoming_binding_expression_alloc_copy(
581        &mut self,
582        alloc_func_name: &str,
583        expr: IncomingBindingExpression,
584    ) -> IncomingBindingExpressionAllocCopy {
585        let alloc_func_name = alloc_func_name.into();
586        let expr = Box::new(expr);
587        IncomingBindingExpressionAllocCopy {
588            alloc_func_name,
589            expr,
590        }
591    }
592
593    type IncomingBindingExpressionEnumToI32 = IncomingBindingExpressionEnumToI32;
594    fn incoming_binding_expression_enum_to_i32(
595        &mut self,
596        ty: WebidlTypeRef,
597        expr: IncomingBindingExpression,
598    ) -> IncomingBindingExpressionEnumToI32 {
599        let expr = Box::new(expr);
600        IncomingBindingExpressionEnumToI32 { ty, expr }
601    }
602
603    type IncomingBindingExpressionField = IncomingBindingExpressionField;
604    fn incoming_binding_expression_field(
605        &mut self,
606        idx: u32,
607        expr: IncomingBindingExpression,
608    ) -> IncomingBindingExpressionField {
609        let expr = Box::new(expr);
610        IncomingBindingExpressionField { idx, expr }
611    }
612
613    type IncomingBindingExpressionBindImport = IncomingBindingExpressionBindImport;
614    fn incoming_binding_expression_bind_import(
615        &mut self,
616        ty: walrus::TypeId,
617        binding: Id<FunctionBinding>,
618        expr: IncomingBindingExpression,
619    ) -> IncomingBindingExpressionBindImport {
620        let expr = Box::new(expr);
621        IncomingBindingExpressionBindImport { ty, binding, expr }
622    }
623
624    type WebidlTypeRef = WebidlTypeRef;
625
626    type WebidlTypeRefNamed = WebidlTypeRef;
627    fn webidl_type_ref_named(&mut self, name: &str) -> Option<WebidlTypeRef> {
628        self.section.types.by_name(name).map(Into::into)
629    }
630
631    type WebidlTypeRefIndexed = WebidlTypeRef;
632    fn webidl_type_ref_indexed(&mut self, idx: u32) -> Option<WebidlTypeRef> {
633        self.section.types.by_index(idx).map(Into::into)
634    }
635
636    type WebidlScalarType = WebidlScalarType;
637    fn webidl_scalar_type_any(&mut self) -> WebidlScalarType {
638        WebidlScalarType::Any
639    }
640    fn webidl_scalar_type_boolean(&mut self) -> WebidlScalarType {
641        WebidlScalarType::Boolean
642    }
643    fn webidl_scalar_type_byte(&mut self) -> WebidlScalarType {
644        WebidlScalarType::Byte
645    }
646    fn webidl_scalar_type_octet(&mut self) -> WebidlScalarType {
647        WebidlScalarType::Octet
648    }
649    fn webidl_scalar_type_long(&mut self) -> WebidlScalarType {
650        WebidlScalarType::Long
651    }
652    fn webidl_scalar_type_unsigned_long(&mut self) -> WebidlScalarType {
653        WebidlScalarType::UnsignedLong
654    }
655    fn webidl_scalar_type_short(&mut self) -> WebidlScalarType {
656        WebidlScalarType::Short
657    }
658    fn webidl_scalar_type_unsigned_short(&mut self) -> WebidlScalarType {
659        WebidlScalarType::UnsignedShort
660    }
661    fn webidl_scalar_type_long_long(&mut self) -> WebidlScalarType {
662        WebidlScalarType::LongLong
663    }
664    fn webidl_scalar_type_unsigned_long_long(&mut self) -> WebidlScalarType {
665        WebidlScalarType::UnsignedLongLong
666    }
667    fn webidl_scalar_type_float(&mut self) -> WebidlScalarType {
668        WebidlScalarType::Float
669    }
670    fn webidl_scalar_type_unrestricted_float(&mut self) -> WebidlScalarType {
671        WebidlScalarType::UnrestrictedFloat
672    }
673    fn webidl_scalar_type_double(&mut self) -> WebidlScalarType {
674        WebidlScalarType::Double
675    }
676    fn webidl_scalar_type_unrestricted_double(&mut self) -> WebidlScalarType {
677        WebidlScalarType::UnrestrictedDouble
678    }
679    fn webidl_scalar_type_dom_string(&mut self) -> WebidlScalarType {
680        WebidlScalarType::DomString
681    }
682    fn webidl_scalar_type_byte_string(&mut self) -> WebidlScalarType {
683        WebidlScalarType::ByteString
684    }
685    fn webidl_scalar_type_usv_string(&mut self) -> WebidlScalarType {
686        WebidlScalarType::UsvString
687    }
688    fn webidl_scalar_type_object(&mut self) -> WebidlScalarType {
689        WebidlScalarType::Object
690    }
691    fn webidl_scalar_type_symbol(&mut self) -> WebidlScalarType {
692        WebidlScalarType::Symbol
693    }
694    fn webidl_scalar_type_array_buffer(&mut self) -> WebidlScalarType {
695        WebidlScalarType::ArrayBuffer
696    }
697    fn webidl_scalar_type_data_view(&mut self) -> WebidlScalarType {
698        WebidlScalarType::DataView
699    }
700    fn webidl_scalar_type_int8_array(&mut self) -> WebidlScalarType {
701        WebidlScalarType::Int8Array
702    }
703    fn webidl_scalar_type_int16_array(&mut self) -> WebidlScalarType {
704        WebidlScalarType::Int16Array
705    }
706    fn webidl_scalar_type_int32_array(&mut self) -> WebidlScalarType {
707        WebidlScalarType::Int32Array
708    }
709    fn webidl_scalar_type_uint8_array(&mut self) -> WebidlScalarType {
710        WebidlScalarType::Uint8Array
711    }
712    fn webidl_scalar_type_uint16_array(&mut self) -> WebidlScalarType {
713        WebidlScalarType::Uint16Array
714    }
715    fn webidl_scalar_type_uint32_array(&mut self) -> WebidlScalarType {
716        WebidlScalarType::Uint32Array
717    }
718    fn webidl_scalar_type_uint8_clamped_array(&mut self) -> WebidlScalarType {
719        WebidlScalarType::Uint8ClampedArray
720    }
721    fn webidl_scalar_type_float32_array(&mut self) -> WebidlScalarType {
722        WebidlScalarType::Float32Array
723    }
724    fn webidl_scalar_type_float64_array(&mut self) -> WebidlScalarType {
725        WebidlScalarType::Float64Array
726    }
727
728    type WasmValType = walrus::ValType;
729    fn wasm_val_type_i32(&mut self) -> walrus::ValType {
730        walrus::ValType::I32
731    }
732    fn wasm_val_type_i64(&mut self) -> walrus::ValType {
733        walrus::ValType::I64
734    }
735    fn wasm_val_type_f32(&mut self) -> walrus::ValType {
736        walrus::ValType::F32
737    }
738    fn wasm_val_type_f64(&mut self) -> walrus::ValType {
739        walrus::ValType::F64
740    }
741    fn wasm_val_type_v128(&mut self) -> walrus::ValType {
742        walrus::ValType::V128
743    }
744    fn wasm_val_type_anyref(&mut self) -> walrus::ValType {
745        walrus::ValType::Anyref
746    }
747
748    type WasmFuncTypeRef = walrus::TypeId;
749
750    type WasmFuncTypeRefNamed = walrus::TypeId;
751    fn wasm_func_type_ref_named(&mut self, name: &str) -> Option<walrus::TypeId> {
752        self.module.types.by_name(name)
753    }
754
755    type WasmFuncTypeRefIndexed = walrus::TypeId;
756    fn wasm_func_type_ref_indexed(&mut self, idx: u32) -> Option<walrus::TypeId> {
757        self.ids.get_type(idx).ok()
758    }
759
760    type WasmFuncRef = walrus::FunctionId;
761
762    type WasmFuncRefNamed = walrus::FunctionId;
763    fn wasm_func_ref_named(&mut self, name: &str) -> Option<walrus::FunctionId> {
764        self.module.funcs.by_name(name)
765    }
766
767    type WasmFuncRefIndexed = walrus::FunctionId;
768    fn wasm_func_ref_indexed(&mut self, idx: u32) -> Option<walrus::FunctionId> {
769        self.ids.get_func(idx).ok()
770    }
771
772    type BindingRef = Id<FunctionBinding>;
773
774    type BindingRefNamed = Id<FunctionBinding>;
775    fn binding_ref_named(&mut self, name: &str) -> Option<Id<FunctionBinding>> {
776        self.section.bindings.by_name(name)
777    }
778
779    type BindingRefIndexed = Id<FunctionBinding>;
780    fn binding_ref_indexed(&mut self, idx: u32) -> Option<Id<FunctionBinding>> {
781        self.section.bindings.by_index(idx)
782    }
783}
784
785#[derive(Clone, Debug, PartialEq, Eq)]
786pub struct WebidlType {
787    pub name: Option<String>,
788    pub ty: WebidlCompoundType,
789}
790
791#[derive(Clone, Debug, PartialEq, Eq)]
792pub enum WebidlCompoundType {
793    Function(WebidlFunction),
794    Dictionary(WebidlDictionary),
795    Enumeration(WebidlEnumeration),
796    Union(WebidlUnion),
797}
798
799impl From<WebidlFunction> for WebidlCompoundType {
800    fn from(a: WebidlFunction) -> Self {
801        WebidlCompoundType::Function(a)
802    }
803}
804
805impl From<WebidlDictionary> for WebidlCompoundType {
806    fn from(a: WebidlDictionary) -> Self {
807        WebidlCompoundType::Dictionary(a)
808    }
809}
810
811impl From<WebidlEnumeration> for WebidlCompoundType {
812    fn from(a: WebidlEnumeration) -> Self {
813        WebidlCompoundType::Enumeration(a)
814    }
815}
816
817impl From<WebidlUnion> for WebidlCompoundType {
818    fn from(a: WebidlUnion) -> Self {
819        WebidlCompoundType::Union(a)
820    }
821}
822
823#[derive(Clone, Debug, PartialEq, Eq)]
824pub struct WebidlFunction {
825    pub kind: WebidlFunctionKind,
826    pub params: Vec<WebidlTypeRef>,
827    pub result: Option<WebidlTypeRef>,
828}
829
830#[derive(Clone, Debug, PartialEq, Eq)]
831pub enum WebidlFunctionKind {
832    Static,
833    Method(WebidlFunctionKindMethod),
834    Constructor,
835}
836
837impl From<WebidlFunctionKindMethod> for WebidlFunctionKind {
838    fn from(a: WebidlFunctionKindMethod) -> Self {
839        WebidlFunctionKind::Method(a)
840    }
841}
842
843#[derive(Clone, Debug, PartialEq, Eq)]
844pub struct WebidlFunctionKindMethod {
845    pub ty: WebidlTypeRef,
846}
847
848#[derive(Clone, Debug, PartialEq, Eq)]
849pub struct WebidlDictionary {
850    pub fields: Vec<WebidlDictionaryField>,
851}
852
853#[derive(Clone, Debug, PartialEq, Eq)]
854pub struct WebidlDictionaryField {
855    pub name: String,
856    pub ty: WebidlTypeRef,
857}
858
859#[derive(Clone, Debug, PartialEq, Eq)]
860pub struct WebidlEnumeration {
861    pub values: Vec<String>,
862}
863
864#[derive(Clone, Debug, PartialEq, Eq)]
865pub struct WebidlUnion {
866    pub members: Vec<WebidlTypeRef>,
867}
868
869#[derive(Clone, Debug, PartialEq, Eq)]
870pub enum FunctionBinding {
871    Import(ImportBinding),
872    Export(ExportBinding),
873}
874
875impl FunctionBinding {
876    /// In the context of a JS embedder that does *not* implement the Web IDL
877    /// bindings proposal, are this binding's ingoing and outgoing conversions
878    /// losslessly expressible with the default conversions of the WebAssembly
879    /// JavaScript interface and the ECMAScript bindings for Web IDL?
880    ///
881    /// This is primarily a question that is only relevant to polyfills for Web
882    /// IDL bindings, such as `wasm-bindgen`.
883    ///
884    /// For both incoming and outgoing values, the conversions are not
885    /// expressible if each value is referenced more than once in the binding
886    /// map, or the values are referenced out of order. Failure to meet this
887    /// criteria would result in swapped, garbage, extra, or not enough
888    /// parameters/results.
889    ///
890    /// In addition to the arity and usage requirements, each value's type must
891    /// also be trivially convertible. This property depends on whether the
892    /// value is incoming or outgoing.
893    ///
894    /// ## Outgoing Values
895    ///
896    /// When passing outgoing Wasm values to Web IDL, first they are converted
897    /// to JS values via the [`ToJSValue` algorithm defined by the WebAssembly
898    /// JavaScript
899    /// interface](https://webassembly.github.io/spec/js-api/index.html#tojsvalue). Next,
900    /// these JS values then they are converted into Web IDL values via [Web
901    /// IDL's ECMAScript type
902    /// mapping](https://heycam.github.io/webidl/#es-type-mapping).
903    ///
904    /// ```text
905    /// +------------+                                 +----------+                                        +---------------+
906    /// | Wasm value | ---WebAssembly-JS-interface---> | JS value | ---ECMAScript-bindings-for-Web-IDL---> | Web IDL value |
907    /// +------------+                                 +----------+                                        +---------------+
908    /// ```
909    ///
910    /// For outgoing values to be expressible without Web IDL bindings, nor
911    /// extra glue or conversions, they must be an `as` operator performing on
912    /// of the following conversions from a Wasm value type to a Web IDL type:
913    ///
914    /// | From Wasm valtype             | To Web IDL Type     |
915    /// |-------------------------------|---------------------|
916    /// | `i32`, `f32`, `f64`, `anyref` | `any`                                                                               |
917    /// | `i32`                         | `long`, `long long`, `float`, `unrestricted float`, `double`, `unrestricted double` |
918    /// | `f32`                   | `unrestricted float`, `unrestricted double`                                               |
919    /// | `f64`                   | `unrestricted double`                                                                     |
920    ///
921    /// ## Incoming Values
922    ///
923    /// When passing Web IDL values to Wasm, first they are converted to JS
924    /// values via the [Web IDL's ECMAScript type
925    /// mapping](https://heycam.github.io/webidl/#es-type-mapping), and then
926    /// those JS values are converted into Wasm values according to the
927    /// [`ToWebAssemblyValue` algorithm defined by the WebAssembly JavaScript
928    /// interface](https://webassembly.github.io/spec/js-api/index.html#towebassemblyvalue).
929    ///
930    /// ```text
931    /// +---------------+                                         +----------+                                 +---------------+
932    /// | Web IDL value |  ---ECMAScript-bindings-for-Web-IDL---> | JS value | ---WebAssembly-JS-interface---> | Web IDL value |
933    /// +---------------+                                         +----------+                                 +---------------+
934    /// ```
935    ///
936    /// For incoming values to be expressible without Web IDL bindings, nor
937    /// extra glue or conversions, they must be an incoming binding expression
938    /// of the form `(as (get <i>))` that is performing one of the following
939    /// conversions from a Web IDL type to a Wasm type:
940    ///
941    /// | From Web IDL Type | To Wasm valtype |
942    /// |-------------------|-----------------|
943    /// | `any`                                                                                                                               | `anyref`        |
944    /// | `byte`, `short`, `long`                                                                                                             | `i32`           |
945    /// | `byte`, `octet`, `short`, `unsigned short`, `float`, `unrestricted float`                                                           | `f32`           |
946    /// | `byte`, `octet`, `short`, `unsigned short`, `long`, `unsigned long`, `float`, `unrestricted float`, `double`, `unrestricted double` | `f64`           |
947    pub fn is_expressible_in_js_without_webidl_bindings(
948        &self,
949        module: &walrus::Module,
950        wb: &WebidlBindings,
951    ) -> bool {
952        match self {
953            FunctionBinding::Import(i) => {
954                i.is_expressible_in_js_without_webidl_bindings(module, wb)
955            }
956            FunctionBinding::Export(e) => {
957                e.is_expressible_in_js_without_webidl_bindings(module, wb)
958            }
959        }
960    }
961}
962
963impl From<ImportBinding> for FunctionBinding {
964    fn from(a: ImportBinding) -> Self {
965        FunctionBinding::Import(a)
966    }
967}
968
969impl From<ExportBinding> for FunctionBinding {
970    fn from(a: ExportBinding) -> Self {
971        FunctionBinding::Export(a)
972    }
973}
974
975#[derive(Clone, Debug, PartialEq, Eq)]
976pub struct ImportBinding {
977    pub wasm_ty: walrus::TypeId,
978    pub webidl_ty: WebidlTypeRef,
979    pub params: OutgoingBindingMap,
980    pub result: IncomingBindingMap,
981}
982
983impl ImportBinding {
984    /// Is this import binding expressible in JS without Web IDL bindings, and
985    /// without a polyfill for them?
986    ///
987    /// See `FunctionBinding::is_expressible_in_js_without_webidl_bindings` for
988    /// details.
989    pub fn is_expressible_in_js_without_webidl_bindings(
990        &self,
991        module: &walrus::Module,
992        wb: &WebidlBindings,
993    ) -> bool {
994        let wasm_ty = module.types.get(self.wasm_ty);
995        let webidl_ty = match self.webidl_ty.id().and_then(|id| wb.types.get(id)) {
996            Some(WebidlCompoundType::Function(f)) if f.kind == WebidlFunctionKind::Static => f,
997            _ => return false,
998        };
999        self.params
1000            .is_expressible_in_js_without_webidl_bindings(wasm_ty.params(), &webidl_ty.params)
1001            && self.result.is_expressible_in_js_without_webidl_bindings(
1002                &webidl_ty.result.into_iter().collect::<Vec<_>>(),
1003                wasm_ty.results(),
1004            )
1005    }
1006}
1007
1008#[derive(Clone, Debug, PartialEq, Eq)]
1009pub struct ExportBinding {
1010    pub wasm_ty: walrus::TypeId,
1011    pub webidl_ty: WebidlTypeRef,
1012    pub params: IncomingBindingMap,
1013    pub result: OutgoingBindingMap,
1014}
1015
1016impl ExportBinding {
1017    /// Is this export binding expressible in JS without Web IDL bindings, and
1018    /// without a polyfill for them?
1019    ///
1020    /// See `FunctionBinding::is_expressible_in_js_without_webidl_bindings` for
1021    /// details.
1022    pub fn is_expressible_in_js_without_webidl_bindings(
1023        &self,
1024        module: &walrus::Module,
1025        wb: &WebidlBindings,
1026    ) -> bool {
1027        let wasm_ty = module.types.get(self.wasm_ty);
1028        let webidl_ty = match self.webidl_ty.id().and_then(|id| wb.types.get(id)) {
1029            Some(WebidlCompoundType::Function(f)) if f.kind == WebidlFunctionKind::Static => f,
1030            _ => return false,
1031        };
1032        self.params
1033            .is_expressible_in_js_without_webidl_bindings(&webidl_ty.params, wasm_ty.params())
1034            && self.result.is_expressible_in_js_without_webidl_bindings(
1035                wasm_ty.results(),
1036                &webidl_ty.result.into_iter().collect::<Vec<_>>(),
1037            )
1038    }
1039}
1040
1041#[derive(Clone, Debug, PartialEq, Eq)]
1042pub struct Bind {
1043    pub func: walrus::FunctionId,
1044    pub binding: Id<FunctionBinding>,
1045}
1046
1047#[derive(Clone, Debug, PartialEq, Eq)]
1048pub struct OutgoingBindingMap {
1049    pub bindings: Vec<OutgoingBindingExpression>,
1050}
1051
1052impl OutgoingBindingMap {
1053    /// Is this outgoing binding map expressible in JS without Web IDL bindings,
1054    /// and without a polyfill for them?
1055    ///
1056    /// See `FunctionBinding::is_expressible_in_js_without_webidl_bindings` for
1057    /// details.
1058    pub fn is_expressible_in_js_without_webidl_bindings(
1059        &self,
1060        from_wasm_tys: &[walrus::ValType],
1061        to_webidl_tys: &[WebidlTypeRef],
1062    ) -> bool {
1063        if self.bindings.len() != from_wasm_tys.len() || self.bindings.len() != to_webidl_tys.len()
1064        {
1065            return false;
1066        }
1067
1068        self.bindings
1069            .iter()
1070            .zip(from_wasm_tys)
1071            .zip(to_webidl_tys)
1072            .enumerate()
1073            .all(|(i, ((expr, from_wasm_ty), to_webidl_ty))| {
1074                expr.is_expressible_in_js_without_webidl_bindings(
1075                    *from_wasm_ty,
1076                    *to_webidl_ty,
1077                    i as u32,
1078                )
1079            })
1080    }
1081}
1082
1083#[derive(Clone, Debug, PartialEq, Eq)]
1084pub struct IncomingBindingMap {
1085    pub bindings: Vec<IncomingBindingExpression>,
1086}
1087
1088impl IncomingBindingMap {
1089    /// Is this incoming binding map expressible in JS without Web IDL bindings,
1090    /// and without a polyfill for them?
1091    ///
1092    /// See `FunctionBinding::is_expressible_in_js_without_webidl_bindings` for
1093    /// details.
1094    pub fn is_expressible_in_js_without_webidl_bindings(
1095        &self,
1096        from_webidl_tys: &[WebidlTypeRef],
1097        to_wasm_tys: &[walrus::ValType],
1098    ) -> bool {
1099        if self.bindings.len() != from_webidl_tys.len() || self.bindings.len() != to_wasm_tys.len()
1100        {
1101            return false;
1102        }
1103
1104        self.bindings
1105            .iter()
1106            .zip(from_webidl_tys)
1107            .zip(to_wasm_tys)
1108            .enumerate()
1109            .all(|(i, ((expr, from_webidl_ty), to_wasm_ty))| {
1110                expr.is_expressible_in_js_without_webidl_bindings(
1111                    *from_webidl_ty,
1112                    *to_wasm_ty,
1113                    i as u32,
1114                )
1115            })
1116    }
1117}
1118
1119#[derive(Clone, Debug, PartialEq, Eq)]
1120pub enum OutgoingBindingExpression {
1121    As(OutgoingBindingExpressionAs),
1122    Utf8Str(OutgoingBindingExpressionUtf8Str),
1123    Utf8CStr(OutgoingBindingExpressionUtf8CStr),
1124    I32ToEnum(OutgoingBindingExpressionI32ToEnum),
1125    View(OutgoingBindingExpressionView),
1126    Copy(OutgoingBindingExpressionCopy),
1127    Dict(OutgoingBindingExpressionDict),
1128    BindExport(OutgoingBindingExpressionBindExport),
1129}
1130
1131impl From<OutgoingBindingExpressionAs> for OutgoingBindingExpression {
1132    fn from(a: OutgoingBindingExpressionAs) -> Self {
1133        OutgoingBindingExpression::As(a)
1134    }
1135}
1136
1137impl From<OutgoingBindingExpressionUtf8Str> for OutgoingBindingExpression {
1138    fn from(s: OutgoingBindingExpressionUtf8Str) -> Self {
1139        OutgoingBindingExpression::Utf8Str(s)
1140    }
1141}
1142
1143impl From<OutgoingBindingExpressionUtf8CStr> for OutgoingBindingExpression {
1144    fn from(s: OutgoingBindingExpressionUtf8CStr) -> Self {
1145        OutgoingBindingExpression::Utf8CStr(s)
1146    }
1147}
1148
1149impl From<OutgoingBindingExpressionI32ToEnum> for OutgoingBindingExpression {
1150    fn from(s: OutgoingBindingExpressionI32ToEnum) -> Self {
1151        OutgoingBindingExpression::I32ToEnum(s)
1152    }
1153}
1154
1155impl From<OutgoingBindingExpressionView> for OutgoingBindingExpression {
1156    fn from(s: OutgoingBindingExpressionView) -> Self {
1157        OutgoingBindingExpression::View(s)
1158    }
1159}
1160
1161impl From<OutgoingBindingExpressionCopy> for OutgoingBindingExpression {
1162    fn from(s: OutgoingBindingExpressionCopy) -> Self {
1163        OutgoingBindingExpression::Copy(s)
1164    }
1165}
1166
1167impl From<OutgoingBindingExpressionDict> for OutgoingBindingExpression {
1168    fn from(s: OutgoingBindingExpressionDict) -> Self {
1169        OutgoingBindingExpression::Dict(s)
1170    }
1171}
1172
1173impl From<OutgoingBindingExpressionBindExport> for OutgoingBindingExpression {
1174    fn from(s: OutgoingBindingExpressionBindExport) -> Self {
1175        OutgoingBindingExpression::BindExport(s)
1176    }
1177}
1178
1179impl OutgoingBindingExpression {
1180    /// Is this outgoing binding expression expressible in JS without Web IDL
1181    /// bindings, and without a polyfill for them?
1182    ///
1183    /// See `FunctionBinding::is_expressible_in_js_without_webidl_bindings` for
1184    /// details.
1185    pub fn is_expressible_in_js_without_webidl_bindings(
1186        &self,
1187        from_wasm_ty: walrus::ValType,
1188        to_webidl_ty: WebidlTypeRef,
1189        at_index: u32,
1190    ) -> bool {
1191        if let OutgoingBindingExpression::As(a) = self {
1192            if a.idx != at_index || a.ty != to_webidl_ty {
1193                return false;
1194            }
1195
1196            let to_webidl_ty = match to_webidl_ty {
1197                WebidlTypeRef::Scalar(s) => s,
1198                _ => return false,
1199            };
1200
1201            match (from_wasm_ty, to_webidl_ty) {
1202                (_, WebidlScalarType::Any)
1203                | (walrus::ValType::I32, WebidlScalarType::Byte)
1204                | (walrus::ValType::I32, WebidlScalarType::Octet)
1205                | (walrus::ValType::I32, WebidlScalarType::Short)
1206                | (walrus::ValType::I32, WebidlScalarType::UnsignedShort)
1207                | (walrus::ValType::I32, WebidlScalarType::Long)
1208                | (walrus::ValType::I32, WebidlScalarType::LongLong)
1209                | (walrus::ValType::I32, WebidlScalarType::Float)
1210                | (walrus::ValType::I32, WebidlScalarType::UnrestrictedFloat)
1211                | (walrus::ValType::I32, WebidlScalarType::Double)
1212                | (walrus::ValType::I32, WebidlScalarType::UnrestrictedDouble)
1213                | (walrus::ValType::F32, WebidlScalarType::Float)
1214                | (walrus::ValType::F32, WebidlScalarType::UnrestrictedFloat)
1215                | (walrus::ValType::F32, WebidlScalarType::Double)
1216                | (walrus::ValType::F32, WebidlScalarType::UnrestrictedDouble)
1217                | (walrus::ValType::F64, WebidlScalarType::Double)
1218                | (walrus::ValType::F64, WebidlScalarType::UnrestrictedDouble) => true,
1219                _ => false,
1220            }
1221        } else {
1222            false
1223        }
1224    }
1225}
1226
1227#[derive(Clone, Debug, PartialEq, Eq)]
1228pub struct OutgoingBindingExpressionAs {
1229    pub ty: WebidlTypeRef,
1230    pub idx: u32,
1231}
1232
1233#[derive(Clone, Debug, PartialEq, Eq)]
1234pub struct OutgoingBindingExpressionUtf8Str {
1235    pub ty: WebidlTypeRef,
1236    pub offset: u32,
1237    pub length: u32,
1238}
1239
1240#[derive(Clone, Debug, PartialEq, Eq)]
1241pub struct OutgoingBindingExpressionUtf8CStr {
1242    pub ty: WebidlTypeRef,
1243    pub offset: u32,
1244}
1245
1246#[derive(Clone, Debug, PartialEq, Eq)]
1247pub struct OutgoingBindingExpressionI32ToEnum {
1248    pub ty: WebidlTypeRef,
1249    pub idx: u32,
1250}
1251
1252#[derive(Clone, Debug, PartialEq, Eq)]
1253pub struct OutgoingBindingExpressionView {
1254    pub ty: WebidlTypeRef,
1255    pub offset: u32,
1256    pub length: u32,
1257}
1258
1259#[derive(Clone, Debug, PartialEq, Eq)]
1260pub struct OutgoingBindingExpressionCopy {
1261    pub ty: WebidlTypeRef,
1262    pub offset: u32,
1263    pub length: u32,
1264}
1265
1266#[derive(Clone, Debug, PartialEq, Eq)]
1267pub struct OutgoingBindingExpressionDict {
1268    pub ty: WebidlTypeRef,
1269    pub fields: Vec<OutgoingBindingExpression>,
1270}
1271
1272#[derive(Clone, Debug, PartialEq, Eq)]
1273pub struct OutgoingBindingExpressionBindExport {
1274    pub ty: WebidlTypeRef,
1275    pub binding: Id<FunctionBinding>,
1276    pub idx: u32,
1277}
1278
1279#[derive(Clone, Debug, PartialEq, Eq)]
1280pub enum IncomingBindingExpression {
1281    Get(IncomingBindingExpressionGet),
1282    As(IncomingBindingExpressionAs),
1283    AllocUtf8Str(IncomingBindingExpressionAllocUtf8Str),
1284    AllocCopy(IncomingBindingExpressionAllocCopy),
1285    EnumToI32(IncomingBindingExpressionEnumToI32),
1286    Field(IncomingBindingExpressionField),
1287    BindImport(IncomingBindingExpressionBindImport),
1288}
1289
1290impl From<IncomingBindingExpressionGet> for IncomingBindingExpression {
1291    fn from(a: IncomingBindingExpressionGet) -> Self {
1292        IncomingBindingExpression::Get(a)
1293    }
1294}
1295
1296impl From<IncomingBindingExpressionAs> for IncomingBindingExpression {
1297    fn from(a: IncomingBindingExpressionAs) -> Self {
1298        IncomingBindingExpression::As(a)
1299    }
1300}
1301
1302impl From<IncomingBindingExpressionAllocUtf8Str> for IncomingBindingExpression {
1303    fn from(a: IncomingBindingExpressionAllocUtf8Str) -> Self {
1304        IncomingBindingExpression::AllocUtf8Str(a)
1305    }
1306}
1307
1308impl From<IncomingBindingExpressionAllocCopy> for IncomingBindingExpression {
1309    fn from(a: IncomingBindingExpressionAllocCopy) -> Self {
1310        IncomingBindingExpression::AllocCopy(a)
1311    }
1312}
1313
1314impl From<IncomingBindingExpressionEnumToI32> for IncomingBindingExpression {
1315    fn from(a: IncomingBindingExpressionEnumToI32) -> Self {
1316        IncomingBindingExpression::EnumToI32(a)
1317    }
1318}
1319
1320impl From<IncomingBindingExpressionField> for IncomingBindingExpression {
1321    fn from(a: IncomingBindingExpressionField) -> Self {
1322        IncomingBindingExpression::Field(a)
1323    }
1324}
1325
1326impl From<IncomingBindingExpressionBindImport> for IncomingBindingExpression {
1327    fn from(a: IncomingBindingExpressionBindImport) -> Self {
1328        IncomingBindingExpression::BindImport(a)
1329    }
1330}
1331
1332impl IncomingBindingExpression {
1333    /// Is this incoming binding expression expressible in JS without Web IDL
1334    /// bindings, and without a polyfill for them?
1335    ///
1336    /// See `FunctionBinding::is_expressible_in_js_without_webidl_bindings` for
1337    /// details.
1338    pub fn is_expressible_in_js_without_webidl_bindings(
1339        &self,
1340        from_webidl_ty: WebidlTypeRef,
1341        to_wasm_ty: walrus::ValType,
1342        at_index: u32,
1343    ) -> bool {
1344        if let IncomingBindingExpression::As(a) = self {
1345            if a.ty != to_wasm_ty {
1346                return false;
1347            }
1348
1349            if let IncomingBindingExpression::Get(g) = &*a.expr {
1350                if g.idx != at_index {
1351                    return false;
1352                }
1353
1354                let from_webidl_ty = match from_webidl_ty {
1355                    WebidlTypeRef::Scalar(s) => s,
1356                    _ => return false,
1357                };
1358
1359                match (from_webidl_ty, to_wasm_ty) {
1360                    (WebidlScalarType::Any, walrus::ValType::Anyref)
1361                    | (WebidlScalarType::Boolean, walrus::ValType::I32)
1362                    | (WebidlScalarType::Byte, walrus::ValType::I32)
1363                    | (WebidlScalarType::Octet, walrus::ValType::I32)
1364                    | (WebidlScalarType::Short, walrus::ValType::I32)
1365                    | (WebidlScalarType::UnsignedShort, walrus::ValType::I32)
1366                    | (WebidlScalarType::Long, walrus::ValType::I32)
1367                    | (WebidlScalarType::UnsignedLong, walrus::ValType::I32)
1368                    | (WebidlScalarType::Byte, walrus::ValType::F32)
1369                    | (WebidlScalarType::Octet, walrus::ValType::F32)
1370                    | (WebidlScalarType::Short, walrus::ValType::F32)
1371                    | (WebidlScalarType::UnsignedShort, walrus::ValType::F32)
1372                    | (WebidlScalarType::Float, walrus::ValType::F32)
1373                    | (WebidlScalarType::UnrestrictedFloat, walrus::ValType::F32)
1374                    | (WebidlScalarType::Byte, walrus::ValType::F64)
1375                    | (WebidlScalarType::Octet, walrus::ValType::F64)
1376                    | (WebidlScalarType::Short, walrus::ValType::F64)
1377                    | (WebidlScalarType::UnsignedShort, walrus::ValType::F64)
1378                    | (WebidlScalarType::Long, walrus::ValType::F64)
1379                    | (WebidlScalarType::UnsignedLong, walrus::ValType::F64)
1380                    | (WebidlScalarType::Float, walrus::ValType::F64)
1381                    | (WebidlScalarType::UnrestrictedFloat, walrus::ValType::F64)
1382                    | (WebidlScalarType::Double, walrus::ValType::F64)
1383                    | (WebidlScalarType::UnrestrictedDouble, walrus::ValType::F64) => true,
1384                    _ => false,
1385                }
1386            } else {
1387                false
1388            }
1389        } else {
1390            false
1391        }
1392    }
1393}
1394
1395#[derive(Clone, Debug, PartialEq, Eq)]
1396pub struct IncomingBindingExpressionGet {
1397    pub idx: u32,
1398}
1399
1400#[derive(Clone, Debug, PartialEq, Eq)]
1401pub struct IncomingBindingExpressionAs {
1402    pub ty: walrus::ValType,
1403    pub expr: Box<IncomingBindingExpression>,
1404}
1405
1406#[derive(Clone, Debug, PartialEq, Eq)]
1407pub struct IncomingBindingExpressionAllocUtf8Str {
1408    pub alloc_func_name: String,
1409    pub expr: Box<IncomingBindingExpression>,
1410}
1411
1412#[derive(Clone, Debug, PartialEq, Eq)]
1413pub struct IncomingBindingExpressionAllocCopy {
1414    pub alloc_func_name: String,
1415    pub expr: Box<IncomingBindingExpression>,
1416}
1417
1418#[derive(Clone, Debug, PartialEq, Eq)]
1419pub struct IncomingBindingExpressionEnumToI32 {
1420    pub ty: WebidlTypeRef,
1421    pub expr: Box<IncomingBindingExpression>,
1422}
1423
1424#[derive(Clone, Debug, PartialEq, Eq)]
1425pub struct IncomingBindingExpressionField {
1426    pub idx: u32,
1427    pub expr: Box<IncomingBindingExpression>,
1428}
1429
1430#[derive(Clone, Debug, PartialEq, Eq)]
1431pub struct IncomingBindingExpressionBindImport {
1432    pub ty: walrus::TypeId,
1433    pub binding: Id<FunctionBinding>,
1434    pub expr: Box<IncomingBindingExpression>,
1435}
1436
1437#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1438pub enum WebidlTypeRef {
1439    Id(Id<WebidlCompoundType>),
1440    Scalar(WebidlScalarType),
1441}
1442
1443impl WebidlTypeRef {
1444    /// Get this `WebidlTypeRef` as an id of a `WebidlCompoundType`, or `None`
1445    /// if it is actually a scalar.
1446    pub fn id(&self) -> Option<Id<WebidlCompoundType>> {
1447        match self {
1448            WebidlTypeRef::Id(id) => Some(*id),
1449            _ => None,
1450        }
1451    }
1452
1453    /// Get this `WebidlTypeRef` as a `WebidlScalarType`, or `None` if it is
1454    /// actually a compound type.
1455    pub fn scalar(&self) -> Option<WebidlScalarType> {
1456        match self {
1457            WebidlTypeRef::Scalar(s) => Some(*s),
1458            _ => None,
1459        }
1460    }
1461}
1462
1463impl From<WebidlScalarType> for WebidlTypeRef {
1464    fn from(s: WebidlScalarType) -> Self {
1465        WebidlTypeRef::Scalar(s)
1466    }
1467}
1468
1469impl From<Id<WebidlCompoundType>> for WebidlTypeRef {
1470    fn from(i: Id<WebidlCompoundType>) -> Self {
1471        WebidlTypeRef::Id(i)
1472    }
1473}
1474
1475#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1476pub enum WebidlScalarType {
1477    Any,
1478    Boolean,
1479    Byte,
1480    Octet,
1481    Long,
1482    UnsignedLong,
1483    Short,
1484    UnsignedShort,
1485    LongLong,
1486    UnsignedLongLong,
1487    Float,
1488    UnrestrictedFloat,
1489    Double,
1490    UnrestrictedDouble,
1491    DomString,
1492    ByteString,
1493    UsvString,
1494    Object,
1495    Symbol,
1496    ArrayBuffer,
1497    DataView,
1498    Int8Array,
1499    Int16Array,
1500    Int32Array,
1501    Uint8Array,
1502    Uint16Array,
1503    Uint32Array,
1504    Uint8ClampedArray,
1505    Float32Array,
1506    Float64Array,
1507}
1508
1509#[cfg(test)]
1510mod tests {
1511    use super::*;
1512
1513    #[test]
1514    fn imports_expressible_without_webidl_bindings() {
1515        let mut m = walrus::Module::default();
1516        let wasm_ty = m
1517            .types
1518            .add(&[walrus::ValType::I32], &[walrus::ValType::I32]);
1519
1520        let mut wb = WebidlBindings::default();
1521
1522        let webidl_ty = wb
1523            .types
1524            .insert(WebidlCompoundType::Function(WebidlFunction {
1525                kind: WebidlFunctionKind::Static,
1526                params: vec![WebidlScalarType::Long.into()],
1527                result: Some(WebidlScalarType::Long.into()),
1528            }));
1529
1530        let binding = wb.bindings.insert(FunctionBinding::Import(ImportBinding {
1531            wasm_ty,
1532            webidl_ty: webidl_ty.into(),
1533            params: OutgoingBindingMap {
1534                bindings: vec![OutgoingBindingExpressionAs {
1535                    ty: WebidlScalarType::Long.into(),
1536                    idx: 0,
1537                }
1538                .into()],
1539            },
1540            result: IncomingBindingMap {
1541                bindings: vec![IncomingBindingExpressionAs {
1542                    ty: walrus::ValType::I32,
1543                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1544                }
1545                .into()],
1546            },
1547        }));
1548
1549        let binding: &FunctionBinding = wb.bindings.get(binding).unwrap();
1550        assert!(binding.is_expressible_in_js_without_webidl_bindings(&m, &wb));
1551    }
1552
1553    #[test]
1554    fn imports_not_expressible_without_webidl_bindings() {
1555        let mut m = walrus::Module::default();
1556        let wasm_ty = m.types.add(
1557            &[walrus::ValType::I32, walrus::ValType::I32],
1558            &[walrus::ValType::I32],
1559        );
1560
1561        let mut wb = WebidlBindings::default();
1562
1563        let webidl_ty = wb
1564            .types
1565            .insert(WebidlCompoundType::Function(WebidlFunction {
1566                kind: WebidlFunctionKind::Static,
1567                params: vec![WebidlScalarType::DomString.into()],
1568                result: Some(WebidlScalarType::Long.into()),
1569            }));
1570
1571        let binding = wb.bindings.insert(FunctionBinding::Import(ImportBinding {
1572            wasm_ty,
1573            webidl_ty: webidl_ty.into(),
1574            params: OutgoingBindingMap {
1575                bindings: vec![OutgoingBindingExpressionUtf8Str {
1576                    ty: WebidlScalarType::DomString.into(),
1577                    offset: 0,
1578                    length: 1,
1579                }
1580                .into()],
1581            },
1582            result: IncomingBindingMap {
1583                bindings: vec![IncomingBindingExpressionAs {
1584                    ty: walrus::ValType::I32,
1585                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1586                }
1587                .into()],
1588            },
1589        }));
1590
1591        let binding: &FunctionBinding = wb.bindings.get(binding).unwrap();
1592        assert!(!binding.is_expressible_in_js_without_webidl_bindings(&m, &wb));
1593    }
1594
1595    #[test]
1596    fn imports_function_kind_not_expressible_without_webidl_bindings() {
1597        let mut m = walrus::Module::default();
1598        let wasm_ty = m.types.add(&[walrus::ValType::Anyref], &[]);
1599
1600        let mut wb = WebidlBindings::default();
1601
1602        let webidl_ty = wb
1603            .types
1604            .insert(WebidlCompoundType::Function(WebidlFunction {
1605                kind: WebidlFunctionKind::Method(WebidlFunctionKindMethod {
1606                    ty: WebidlScalarType::Any.into(),
1607                }),
1608                params: vec![],
1609                result: None,
1610            }));
1611
1612        let binding = wb.bindings.insert(FunctionBinding::Import(ImportBinding {
1613            wasm_ty,
1614            webidl_ty: webidl_ty.into(),
1615            params: OutgoingBindingMap {
1616                bindings: vec![OutgoingBindingExpressionAs {
1617                    ty: WebidlScalarType::Any.into(),
1618                    idx: 0,
1619                }
1620                .into()],
1621            },
1622            result: IncomingBindingMap { bindings: vec![] },
1623        }));
1624
1625        let binding: &FunctionBinding = wb.bindings.get(binding).unwrap();
1626        assert!(!binding.is_expressible_in_js_without_webidl_bindings(&m, &wb));
1627    }
1628
1629    #[test]
1630    fn exports_expressible_without_webidl_bindings() {
1631        let mut m = walrus::Module::default();
1632        let wasm_ty = m
1633            .types
1634            .add(&[walrus::ValType::I32], &[walrus::ValType::I32]);
1635
1636        let mut wb = WebidlBindings::default();
1637
1638        let webidl_ty = wb
1639            .types
1640            .insert(WebidlCompoundType::Function(WebidlFunction {
1641                kind: WebidlFunctionKind::Static,
1642                params: vec![WebidlScalarType::Long.into()],
1643                result: Some(WebidlScalarType::Long.into()),
1644            }));
1645
1646        let binding = wb.bindings.insert(FunctionBinding::Export(ExportBinding {
1647            wasm_ty,
1648            webidl_ty: webidl_ty.into(),
1649            params: IncomingBindingMap {
1650                bindings: vec![IncomingBindingExpressionAs {
1651                    ty: walrus::ValType::I32,
1652                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1653                }
1654                .into()],
1655            },
1656            result: OutgoingBindingMap {
1657                bindings: vec![OutgoingBindingExpressionAs {
1658                    ty: WebidlScalarType::Long.into(),
1659                    idx: 0,
1660                }
1661                .into()],
1662            },
1663        }));
1664
1665        let binding: &FunctionBinding = wb.bindings.get(binding).unwrap();
1666        assert!(binding.is_expressible_in_js_without_webidl_bindings(&m, &wb));
1667    }
1668
1669    #[test]
1670    fn exports_not_expressible_without_webidl_bindings() {
1671        let mut m = walrus::Module::default();
1672        let wasm_ty = m.types.add(
1673            &[walrus::ValType::I32, walrus::ValType::I32],
1674            &[walrus::ValType::I32],
1675        );
1676
1677        let mut wb = WebidlBindings::default();
1678
1679        let webidl_ty = wb
1680            .types
1681            .insert(WebidlCompoundType::Function(WebidlFunction {
1682                kind: WebidlFunctionKind::Static,
1683                params: vec![WebidlScalarType::DomString.into()],
1684                result: Some(WebidlScalarType::Long.into()),
1685            }));
1686
1687        let binding = wb.bindings.insert(FunctionBinding::Export(ExportBinding {
1688            wasm_ty,
1689            webidl_ty: webidl_ty.into(),
1690            params: IncomingBindingMap {
1691                bindings: vec![IncomingBindingExpressionAllocUtf8Str {
1692                    alloc_func_name: "malloc".into(),
1693                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1694                }
1695                .into()],
1696            },
1697            result: OutgoingBindingMap {
1698                bindings: vec![OutgoingBindingExpressionAs {
1699                    ty: WebidlScalarType::Long.into(),
1700                    idx: 0,
1701                }
1702                .into()],
1703            },
1704        }));
1705
1706        let binding: &FunctionBinding = wb.bindings.get(binding).unwrap();
1707        assert!(!binding.is_expressible_in_js_without_webidl_bindings(&m, &wb));
1708    }
1709
1710    #[test]
1711    fn exports_function_kind_not_expressible_without_webidl_bindings() {
1712        let mut m = walrus::Module::default();
1713        let wasm_ty = m.types.add(&[walrus::ValType::Anyref], &[]);
1714
1715        let mut wb = WebidlBindings::default();
1716
1717        let webidl_ty = wb
1718            .types
1719            .insert(WebidlCompoundType::Function(WebidlFunction {
1720                kind: WebidlFunctionKind::Method(WebidlFunctionKindMethod {
1721                    ty: WebidlScalarType::Any.into(),
1722                }),
1723                params: vec![],
1724                result: None,
1725            }));
1726
1727        let binding = wb.bindings.insert(FunctionBinding::Export(ExportBinding {
1728            wasm_ty,
1729            webidl_ty: webidl_ty.into(),
1730            params: IncomingBindingMap {
1731                bindings: vec![IncomingBindingExpressionAs {
1732                    ty: walrus::ValType::Anyref,
1733                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1734                }
1735                .into()],
1736            },
1737            result: OutgoingBindingMap { bindings: vec![] },
1738        }));
1739
1740        let binding: &FunctionBinding = wb.bindings.get(binding).unwrap();
1741        assert!(!binding.is_expressible_in_js_without_webidl_bindings(&m, &wb));
1742    }
1743
1744    #[test]
1745    fn incoming_empty_trivially_expressible_without_webidl_bindings() {
1746        let map = IncomingBindingMap { bindings: vec![] };
1747        assert!(map.is_expressible_in_js_without_webidl_bindings(&[], &[]));
1748    }
1749
1750    #[test]
1751    fn incoming_arity_not_expressible_without_webidl_bindings() {
1752        let map = IncomingBindingMap {
1753            bindings: vec![IncomingBindingExpressionAs {
1754                ty: walrus::ValType::I32,
1755                expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1756            }
1757            .into()],
1758        };
1759
1760        // Too many Web IDL types.
1761        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1762            &[WebidlScalarType::Long.into(), WebidlScalarType::Long.into(),],
1763            &[walrus::ValType::I32],
1764        ));
1765
1766        // Not enough Web IDL types.
1767        assert!(!map.is_expressible_in_js_without_webidl_bindings(&[], &[walrus::ValType::I32]));
1768
1769        // Too many wasm valtypes.
1770        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1771            &[WebidlScalarType::Long.into()],
1772            &[walrus::ValType::I32, walrus::ValType::I32],
1773        ));
1774
1775        // Not enough wasm valtypes.
1776        assert!(!map
1777            .is_expressible_in_js_without_webidl_bindings(&[WebidlScalarType::Long.into()], &[]));
1778    }
1779
1780    #[test]
1781    fn incoming_usage_order_not_expressible_without_webidl_bindings() {
1782        // Attempts to use param at index 1 before param at index 0.
1783        let map = IncomingBindingMap {
1784            bindings: vec![
1785                IncomingBindingExpressionAs {
1786                    ty: walrus::ValType::I32,
1787                    expr: Box::new(IncomingBindingExpressionGet { idx: 1 }.into()),
1788                }
1789                .into(),
1790                IncomingBindingExpressionAs {
1791                    ty: walrus::ValType::I32,
1792                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1793                }
1794                .into(),
1795            ],
1796        };
1797
1798        // And therefore, is not expressible even though arity and types work out.
1799        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1800            &[WebidlScalarType::Long.into(), WebidlScalarType::Long.into()],
1801            &[walrus::ValType::I32, walrus::ValType::I32],
1802        ));
1803    }
1804
1805    #[test]
1806    fn incoming_binding_operator_not_expressible_without_webidl_bindings() {
1807        let map = IncomingBindingMap {
1808            bindings: vec![IncomingBindingExpressionAllocUtf8Str {
1809                alloc_func_name: "malloc".into(),
1810                expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1811            }
1812            .into()],
1813        };
1814        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1815            &[WebidlScalarType::DomString.into()],
1816            &[walrus::ValType::I32, walrus::ValType::I32],
1817        ));
1818    }
1819
1820    #[test]
1821    fn outgoing_empty_trivially_expressible_without_webidl_bindings() {
1822        let map = OutgoingBindingMap { bindings: vec![] };
1823        assert!(map.is_expressible_in_js_without_webidl_bindings(&[], &[]));
1824    }
1825
1826    #[test]
1827    fn outgoing_arity_not_expressible_without_webidl_bindings() {
1828        let map = OutgoingBindingMap {
1829            bindings: vec![OutgoingBindingExpressionAs {
1830                ty: WebidlScalarType::Long.into(),
1831                idx: 0,
1832            }
1833            .into()],
1834        };
1835
1836        // Too many Web IDL types.
1837        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1838            &[walrus::ValType::I32],
1839            &[WebidlScalarType::Long.into(), WebidlScalarType::Long.into(),],
1840        ));
1841
1842        // Not enough Web IDL types.
1843        assert!(!map.is_expressible_in_js_without_webidl_bindings(&[walrus::ValType::I32], &[]));
1844
1845        // Too many wasm valtypes.
1846        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1847            &[walrus::ValType::I32, walrus::ValType::I32],
1848            &[WebidlScalarType::Long.into()],
1849        ));
1850
1851        // Not enough wasm valtypes.
1852        assert!(!map
1853            .is_expressible_in_js_without_webidl_bindings(&[], &[WebidlScalarType::Long.into()]));
1854    }
1855
1856    #[test]
1857    fn outgoing_usage_order_not_expressible_without_webidl_bindings() {
1858        // Attempts to use param at index 1 before param at index 0.
1859        let map = OutgoingBindingMap {
1860            bindings: vec![
1861                OutgoingBindingExpressionAs {
1862                    ty: WebidlScalarType::Long.into(),
1863                    idx: 1,
1864                }
1865                .into(),
1866                OutgoingBindingExpressionAs {
1867                    ty: WebidlScalarType::Long.into(),
1868                    idx: 0,
1869                }
1870                .into(),
1871            ],
1872        };
1873
1874        // And therefore, is not expressible even though arity and types work out.
1875        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1876            &[walrus::ValType::I32, walrus::ValType::I32],
1877            &[WebidlScalarType::Long.into(), WebidlScalarType::Long.into()],
1878        ));
1879    }
1880
1881    #[test]
1882    fn outgoing_binding_operator_not_expressible_without_webidl_bindings() {
1883        let map = OutgoingBindingMap {
1884            bindings: vec![OutgoingBindingExpressionUtf8Str {
1885                ty: WebidlScalarType::DomString.into(),
1886                offset: 0,
1887                length: 1,
1888            }
1889            .into()],
1890        };
1891        assert!(!map.is_expressible_in_js_without_webidl_bindings(
1892            &[walrus::ValType::I32, walrus::ValType::I32],
1893            &[WebidlScalarType::DomString.into()],
1894        ));
1895    }
1896
1897    const WEBIDL_SCALARS: &[WebidlTypeRef] = &[
1898        WebidlTypeRef::Scalar(WebidlScalarType::Any),
1899        WebidlTypeRef::Scalar(WebidlScalarType::Boolean),
1900        WebidlTypeRef::Scalar(WebidlScalarType::Byte),
1901        WebidlTypeRef::Scalar(WebidlScalarType::Octet),
1902        WebidlTypeRef::Scalar(WebidlScalarType::Long),
1903        WebidlTypeRef::Scalar(WebidlScalarType::UnsignedLong),
1904        WebidlTypeRef::Scalar(WebidlScalarType::Short),
1905        WebidlTypeRef::Scalar(WebidlScalarType::UnsignedShort),
1906        WebidlTypeRef::Scalar(WebidlScalarType::LongLong),
1907        WebidlTypeRef::Scalar(WebidlScalarType::UnsignedLongLong),
1908        WebidlTypeRef::Scalar(WebidlScalarType::Float),
1909        WebidlTypeRef::Scalar(WebidlScalarType::UnrestrictedFloat),
1910        WebidlTypeRef::Scalar(WebidlScalarType::Double),
1911        WebidlTypeRef::Scalar(WebidlScalarType::UnrestrictedDouble),
1912        WebidlTypeRef::Scalar(WebidlScalarType::DomString),
1913        WebidlTypeRef::Scalar(WebidlScalarType::ByteString),
1914        WebidlTypeRef::Scalar(WebidlScalarType::UsvString),
1915        WebidlTypeRef::Scalar(WebidlScalarType::Object),
1916        WebidlTypeRef::Scalar(WebidlScalarType::Symbol),
1917        WebidlTypeRef::Scalar(WebidlScalarType::ArrayBuffer),
1918        WebidlTypeRef::Scalar(WebidlScalarType::DataView),
1919        WebidlTypeRef::Scalar(WebidlScalarType::Int8Array),
1920        WebidlTypeRef::Scalar(WebidlScalarType::Int16Array),
1921        WebidlTypeRef::Scalar(WebidlScalarType::Int32Array),
1922        WebidlTypeRef::Scalar(WebidlScalarType::Uint8Array),
1923        WebidlTypeRef::Scalar(WebidlScalarType::Uint16Array),
1924        WebidlTypeRef::Scalar(WebidlScalarType::Uint32Array),
1925        WebidlTypeRef::Scalar(WebidlScalarType::Uint8ClampedArray),
1926        WebidlTypeRef::Scalar(WebidlScalarType::Float32Array),
1927        WebidlTypeRef::Scalar(WebidlScalarType::Float64Array),
1928    ];
1929
1930    const WASM_VALTYPES: &[walrus::ValType] = &[
1931        walrus::ValType::I32,
1932        walrus::ValType::I64,
1933        walrus::ValType::F32,
1934        walrus::ValType::F64,
1935        walrus::ValType::V128,
1936        walrus::ValType::Anyref,
1937    ];
1938
1939    #[test]
1940    fn check_whether_all_outgoing_types_expressible_without_webidl_bindings() {
1941        for to in WEBIDL_SCALARS.iter().cloned() {
1942            let map = OutgoingBindingMap {
1943                bindings: vec![OutgoingBindingExpressionAs { ty: to, idx: 0 }.into()],
1944            };
1945            for from in WASM_VALTYPES.iter().cloned() {
1946                let _ = map.is_expressible_in_js_without_webidl_bindings(&[from], &[to]);
1947            }
1948        }
1949    }
1950
1951    #[test]
1952    fn check_whether_all_incoming_types_expressible_without_webidl_bindings() {
1953        for to in WASM_VALTYPES.iter().cloned() {
1954            let map = IncomingBindingMap {
1955                bindings: vec![IncomingBindingExpressionAs {
1956                    ty: to,
1957                    expr: Box::new(IncomingBindingExpressionGet { idx: 0 }.into()),
1958                }
1959                .into()],
1960            };
1961            for from in WEBIDL_SCALARS.iter().cloned() {
1962                let _ = map.is_expressible_in_js_without_webidl_bindings(&[from], &[to]);
1963            }
1964        }
1965    }
1966}