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 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 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 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 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 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 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 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 pub fn id(&self) -> Option<Id<WebidlCompoundType>> {
1447 match self {
1448 WebidlTypeRef::Id(id) => Some(*id),
1449 _ => None,
1450 }
1451 }
1452
1453 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 assert!(!map.is_expressible_in_js_without_webidl_bindings(
1762 &[WebidlScalarType::Long.into(), WebidlScalarType::Long.into(),],
1763 &[walrus::ValType::I32],
1764 ));
1765
1766 assert!(!map.is_expressible_in_js_without_webidl_bindings(&[], &[walrus::ValType::I32]));
1768
1769 assert!(!map.is_expressible_in_js_without_webidl_bindings(
1771 &[WebidlScalarType::Long.into()],
1772 &[walrus::ValType::I32, walrus::ValType::I32],
1773 ));
1774
1775 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 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 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 assert!(!map.is_expressible_in_js_without_webidl_bindings(
1838 &[walrus::ValType::I32],
1839 &[WebidlScalarType::Long.into(), WebidlScalarType::Long.into(),],
1840 ));
1841
1842 assert!(!map.is_expressible_in_js_without_webidl_bindings(&[walrus::ValType::I32], &[]));
1844
1845 assert!(!map.is_expressible_in_js_without_webidl_bindings(
1847 &[walrus::ValType::I32, walrus::ValType::I32],
1848 &[WebidlScalarType::Long.into()],
1849 ));
1850
1851 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 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 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}