1 module libwasm.types;
2 
3 nothrow:
4 
5 public import optional;
6 public import libwasm.sumtype;
7 public import libwasm.lodash;
8 public import libwasm.bindings.Console;
9 import memutils.vector;
10 import std.traits : hasMember, isCallable, isBasicType, isSomeString;
11 import libwasm.event : toTuple;
12 import libwasm.bindings.EventHandler;
13 
14 version (LDC)
15 {
16   public import ldc.attributes : assumeUsed;
17 }
18 else
19 {
20   enum assumeUsed;
21 }
22 
23 alias Handle = uint;
24 version (unittest)
25 {
26 @safe extern (C):
27   Handle libwasm_add__object()
28   {
29     return 0;
30   }
31 
32   void libwasm_removeObject(Handle)
33   {
34   }
35 
36   void Static_Call_Handle__void(string, string, Handle)
37   {
38   }
39 
40   string ldexec_Handle__string(Handle, string, bool delegate(), void delegate(Handle))
41   {
42     return "";
43   }
44 
45   long ldexec_Handle__long(Handle, string, bool delegate(), void delegate(Handle))
46   {
47     return 0;
48   }
49 
50   double ldexec_Handle__double(Handle, string, bool delegate(), void delegate(Handle))
51   {
52     return 0;
53   }
54 
55   Handle ldexec_Handle__Handle(Handle, string, bool delegate(), void delegate(Handle))
56   {
57     return Handle.init;
58   }
59 
60   string ldexec_string__string(string, string, bool delegate(), void delegate(Handle), bool)
61   {
62     return "";
63   }
64 
65   long ldexec_string__long(string, string, bool delegate(), void delegate(Handle), bool)
66   {
67     return 0;
68   }
69 
70   double ldexec_string__double(string, string, bool delegate(), void delegate(Handle), bool)
71   {
72     return 0;
73   }
74 
75   Handle ldexec_string__Handle(string, string, bool delegate(), void delegate(Handle), bool)
76   {
77     return Handle.init;
78   }
79 
80   long ldexec_long__long(long, string, bool delegate(), void delegate(Handle))
81   {
82     return 0;
83   }
84 
85   double ldexec_long__double(long, string, bool delegate(), void delegate(Handle))
86   {
87     return 0;
88   }
89 
90   string ldexec_long__string(long, string, bool delegate(), void delegate(Handle))
91   {
92     return "";
93   }
94 
95   Handle ldexec_long__Handle(long, string, bool delegate(), void delegate(Handle))
96   {
97     return Handle.init;
98   }
99 
100   Handle libwasm_add__string(scope ref string)
101   {
102     return Handle.init;
103   }
104 
105   int setTimeout(int ctx, int ptr, int ms)
106   {
107     return 0;
108   }
109 
110   Handle libwasm_add__bool(bool)
111   {
112     return Handle.init;
113   }
114 
115   void Object_VarArgCall__void(Handle, string, string, string)
116   {
117 
118   }
119 
120   Optional!Handle Object_Getter__OptionalHandle(Handle, string)
121   {
122     return Optional!Handle.init;
123   }
124 
125   string Object_Getter__string(Handle, string)
126   {
127     return "";
128   }
129 
130   Handle Object_Getter__Handle(Handle, string)
131   {
132     return Handle.init;
133   }
134   string libwasm_get__string(Handle) {
135     return "";
136   }
137   
138   void libwasm_set__function(string, int ctx, int ptr) {}
139   void Object_Call_EventHandler__void(Handle, string, bool, scope EventHandlerNonNull) {}
140 }
141 else
142 {
143   extern (C) @safe
144   {
145     Handle libwasm_add__object();
146     Handle libwasm_add__string(string);
147     void libwasm_removeObject(Handle);
148     void Static_Call_Handle__void(string, string, Handle);
149 
150     string ldexec_Handle__string(Handle, string, bool delegate(), void delegate(Handle));
151     long ldexec_Handle__long(Handle, string, bool delegate(), void delegate(Handle));
152     double ldexec_Handle__double(Handle, string, bool delegate(), void delegate(Handle));
153     Handle ldexec_Handle__Handle(Handle, string, bool delegate(), void delegate(Handle));
154 
155     string ldexec_string__string(string, string, bool delegate(), void delegate(Handle), bool);
156     long ldexec_string__long(string, string, bool delegate(), void delegate(Handle), bool);
157     double ldexec_string__double(string, string, bool delegate(), void delegate(Handle), bool);
158     Handle ldexec_string__Handle(string, string, bool delegate(), void delegate(Handle), bool);
159 
160     long ldexec_long__long(long, string, bool delegate(), void delegate(Handle));
161     double ldexec_long__double(long, string, bool delegate(), void delegate(Handle));
162     string ldexec_long__string(long, string, bool delegate(), void delegate(Handle));
163     Handle ldexec_long__Handle(long, string, bool delegate(), void delegate(Handle));
164     int setTimeout(int ctx, int ptr, int ms);
165     Handle libwasm_add__bool(bool);
166     void Object_VarArgCall__void(Handle, string, string, string);
167     Optional!Handle Object_Getter__OptionalHandle(Handle, string);
168     string Object_Getter__string(Handle, string);
169     Handle Object_Getter__Handle(Handle, string);
170     string libwasm_get__string(Handle);
171     void libwasm_set__function(string, int ctx, int ptr);
172     void Object_Call_EventHandler__void(Handle, string, bool, scope EventHandlerNonNull);
173 
174   }
175 }
176 
177 extern (C)
178 {
179 @safe:
180   void doLog(uint val);
181   void libwasm_await__void(Handle);
182   Handle libwasm_add__int(int);
183   Handle libwasm_add__uint(uint);
184   Handle libwasm_add__long(long);
185   Handle libwasm_add__ulong(ulong);
186   Handle libwasm_add__short(short);
187   Handle libwasm_add__ushort(ushort);
188   Handle libwasm_add__float(float);
189   Handle libwasm_add__double(double);
190   Handle libwasm_add__byte(byte);
191   Handle libwasm_add__ubyte(ubyte);
192   Handle libwasm_add__ints(int[]);
193   Handle libwasm_add__uints(uint[]);
194   Handle libwasm_copyObjectRef(Handle);
195   Handle libasync_promise_all__promise(Handle);
196   Handle libasync_promise_any__promise(Handle);
197   Handle libasync_promise_allsettled__promise(Handle);
198   void libwasm_unset__function(string);
199   Handle libwasm_get__field(Handle, string);
200   Handle libwasm_get_idx__field(Handle, uint);
201   bool libwasm_get__bool(Handle);
202   int libwasm_get__int(Handle);
203   uint libwasm_get__uint(Handle);
204   long libwasm_get__long(Handle);
205   ulong libwasm_get__ulong(Handle);
206   short libwasm_get__short(Handle);
207   ushort libwasm_get__ushort(Handle);
208   float libwasm_get__float(Handle);
209   double libwasm_get__double(Handle);
210   byte libwasm_get__byte(Handle);
211   ubyte libwasm_get__ubyte(Handle);
212   void Static_Call_string__void(string, string, string);
213   void Object_Call__void(Handle, string);
214   void Object_Call_string__void(Handle, string, string);
215   void Object_Call_uint__void(Handle, string, uint);
216   void Object_Call_int__void(Handle, string, int);
217   void Object_Call_bool__void(Handle, string, bool);
218   void Object_Call_double__void(Handle, string, double);
219   void Object_Call_float__void(Handle, string, float);
220   void Object_Call_Handle__void(Handle, string, Handle);
221   void Object_Call_string_string__void(Handle, string, string, string);
222   void Object_Call_double_double__void(Handle, string, double, double);
223   Handle Object_Call_string__Handle(Handle, string, string);
224   Handle Object_Call_uint__Handle(Handle, string, uint);
225   Handle Object_Call_int__Handle(Handle, string, int);
226   Handle Object_Call_bool__Handle(Handle, string, bool);
227   Handle Object_Call_Handle__Handle(Handle, string, Handle);
228   Handle Object_Call_string_string__Handle(Handle, string, string, string);
229   Optional!string Object_Getter__OptionalString(Handle, string);
230   Optional!uint Object_Getter__OptionalUint(Handle, string);
231   Optional!double Object_Getter__OptionalDouble(Handle, string);
232   Optional!bool Object_Getter__OptionalBool(Handle, string);
233   Optional!string Object_Call_string__OptionalString(Handle, string, string);
234   EventHandler Object_Getter__EventHandler(Handle, string);
235   Optional!Handle Object_Call_string__OptionalHandle(Handle, string, string);
236   Optional!Handle Object_Call_uint__OptionalHandle(Handle, string, uint);
237   Optional!Handle Object_Call_int__OptionalHandle(Handle, string, int);
238   Optional!Handle Object_Call_bool__OptionalHandle(Handle, string, bool);
239   int Object_Getter__int(Handle, string);
240   uint Object_Getter__uint(Handle, string);
241   ushort Object_Getter__ushort(Handle, string);
242   bool Object_Getter__bool(Handle, string);
243   float Object_Getter__float(Handle, string);
244   double Object_Getter__double(Handle, string);
245   bool Object_Call_string__bool(Handle, string, string);
246   string Object_Call_string__string(Handle, string, string);
247   string Object_Call_uint__string(Handle, string, uint);
248   string Object_Call_uint_uint__string(Handle, string, uint, uint);
249 
250   bool Object_VarArgCall__bool(Handle, string, string, string);
251   string Object_VarArgCall__string(Handle, string, string, string);
252   int Object_VarArgCall__int(Handle, string, string, string);
253   uint Object_VarArgCall__uint(Handle, string, string, string);
254   short Object_VarArgCall__short(Handle, string, string, string);
255   ushort Object_VarArgCall__ushort(Handle, string, string, string);
256   Handle Object_VarArgCall__Handle(Handle, string, string, string);
257   float Object_VarArgCall__float(Handle, string, string, string);
258   double Object_VarArgCall__double(Handle, string, string, string);
259   long Object_VarArgCall__long(Handle, string, string, string);
260   ulong Object_VarArgCall__ulong(Handle, string, string, string);
261   long getTimeStamp();
262 
263   Handle JSON_parse_string(string);
264   string JSON_stringify(Handle);
265 
266   int setInterval(int ctx, int ptr, int ms);
267   void clearTimeout(int id);
268   void clearInterval(int id);
269 
270 }
271 
272 int setTimeout(Delegate)(Delegate del, int ms)
273 {
274   return setTimeout(del.toTuple.expand, ms);
275 }
276 
277 int setInterval(Delegate)(Delegate del, int ms)
278 {
279   return setInterval(del.toTuple.expand, ms);
280 }
281 
282 void exportDelegate()(string name, auto ref void delegate(Handle) del) @trusted
283 {
284   //console.log("exportDelegate(Del)");
285   return libwasm_set__function(name, del.toTuple.expand);
286 }
287 
288 void exportDelegate()(string name, auto ref void function(Handle) fun) @trusted {  
289   auto del = (Handle hndl) {
290     fun(hndl);
291   };
292   //console.log("exportDelegate(Fun)");
293   return libwasm_set__function(name, del.toTuple.expand);
294 }
295 
296 void unexportDelegate()(string name)
297 {
298   return libwasm_unset__function(name);
299 }
300 
301 extern (C)
302 export
303 @assumeUsed
304 void jsCallback0(uint ctx, uint fun) @trusted
305 {
306   static struct Handler
307   {
308   nothrow:
309     union
310     {
311       void delegate() handle;
312       struct
313       {
314         void* contextPtr;
315         void* funcPtr;
316       }
317     }
318   }
319 
320   Handler c;
321   c.contextPtr = cast(void*) ctx;
322   c.funcPtr = cast(void*) fun;
323   c.handle();
324 }
325 
326 extern (C)
327 export
328 @assumeUsed
329 void jsCallback(uint ctx, uint fun, Handle arg) @trusted
330 {
331   static struct Handler
332   {
333   nothrow:
334     union
335     {
336       void delegate(Handle) handle;
337       struct
338       {
339         void* contextPtr;
340         void* funcPtr;
341       }
342     }
343   }
344 
345   Handler c;
346   c.contextPtr = cast(void*) ctx;
347   c.funcPtr = cast(void*) fun;
348   c.handle(arg);
349 }
350 
351 @trusted extern (C) export @assumeUsed ubyte* allocString(uint bytes);
352 
353 @trusted R Serialize_Object_VarArgCall(R, TupleArgs)(Handle hndl, string method, string argsdef, scope TupleArgs tupleArgs)
354 {
355   import fast.json;
356   import libwasm.rt.allocator;
357   import libwasm.bindings.Console;
358 
359   /*
360   console.log("Got args:");
361   foreach (scope arg; tupleArgs) {
362     import std.traits : isIterable;
363     static if (isIterable!(typeof(arg))) {
364     foreach (scope subarg; arg) {
365         console.log(subarg);
366       }
367     } else {
368       console.log(arg);
369     }
370   }*/
371   char[] buf = cast(char[]) ThreadMemAllocator.allocate(serializationLength(tupleArgs));
372   scope (exit)
373     ThreadMemAllocator.deallocate(buf);
374   auto args = cast(string) serializeJSON(buf, tupleArgs);
375   static if (is(R == string))
376     return Object_VarArgCall__string(hndl, method, argsdef, args);
377   else static if (is(R == void))
378     Object_VarArgCall__void(hndl, method, argsdef, args);
379   else static if (is(R == int))
380     return Object_VarArgCall__int(hndl, method, argsdef, args);
381   else static if (is(R == Handle))
382     return Object_VarArgCall__Handle(hndl, method, argsdef, args);
383   else static if (is(R == uint))
384     return Object_VarArgCall__uint(hndl, method, argsdef, args);
385   else static if (is(R == long))
386     return Object_VarArgCall__long(hndl, method, argsdef, args);
387   else static if (is(R == ulong))
388     return Object_VarArgCall__ulong(hndl, method, argsdef, args);
389   else static if (is(R == double))
390     return Object_VarArgCall__double(hndl, method, argsdef, args);
391   else static if (is(R == float))
392     return Object_VarArgCall__float(hndl, method, argsdef, args);
393   else static if (is(R == ushort))
394     return Object_VarArgCall__ushort(hndl, method, argsdef, args);
395   else static if (is(R == short))
396     return Object_VarArgCall__short(hndl, method, argsdef, args);
397   else static if (is(R == bool))
398     return Object_VarArgCall__bool(hndl, method, argsdef, args);
399 }
400 
401 Vector!char format(string fmt, ARGS...)(ARGS args) @trusted
402 {
403   import fast.format : formattedWrite, decCharsVal;
404   import std.traits : isIntegral, isSomeString, isFloatingPoint;
405 
406   size_t size_estimate = fmt.length + 16;
407 
408   foreach (arg; args)
409   {
410     static if (isSomeString!(typeof(arg)))
411     {
412       size_estimate += arg.length;
413     }
414     else static if (isIntegral!(typeof(arg)))
415     {
416       size_estimate += decCharsVal(arg);
417     }
418     else static if (isFloatingPoint!(typeof(arg)))
419     {
420       size_estimate += decChars!(typeof(arg));
421     }
422     else
423     {
424       static assert(false, "Format argument not implemented: " ~ typeof(arg).stringof);
425     }
426   }
427 
428   Vector!char vec = Vector!char(size_estimate);
429   char* buf = vec.ptr;
430   char[] ret = formattedWrite!fmt(buf, args);
431   vec.length = ret.length;
432 
433   return vec.move();
434 }
435 
436 @safe:
437 
438 struct Eval
439 {
440   string eval_str;
441 }
442 
443 // used for lodash
444 Eval eval(string eval_str)
445 {
446   return Eval(eval_str);
447 }
448 
449 struct JsHandle
450 {
451   import libwasm.bindings.Console;
452 
453 nothrow:
454   public Handle handle;
455   ~this()
456   {
457     if (handle > 2)
458     {
459       libwasm_removeObject(handle);
460     }
461   }
462 
463   void opAssign(ref Handle handle)
464   {
465     this.handle = handle;
466     handle = 0;
467   }
468 
469   auto lodash()()
470   {
471     return Lodash(this.handle, VarType.handle, 128);
472   }
473 
474   this()(typeof(this) rhs)
475   {
476     handle = libwasm_copyObjectRef(rhs.handle);
477   }
478 
479   this(int rhs)
480   {
481     handle = rhs;
482   }
483 
484   alias handle this;
485 }
486 
487 auto ptr(return scope ref JsHandle handle) @system
488 {
489   return &handle.handle;
490 }
491 
492 enum JsHandle invalidHandle = JsHandle(0);
493 alias EventHandle = uint;
494 
495 enum NodeType
496 {
497   a = 0,
498   abbr = 1,
499   address = 2,
500   area = 3,
501   article = 4,
502   aside = 5,
503   audio = 6,
504   b = 7,
505   base = 8,
506   bdi = 9,
507   bdo = 10,
508   blockquote = 11,
509   body_ = 12,
510   br = 13,
511   button = 14,
512   canvas = 15,
513   caption = 16,
514   cite = 17,
515   code = 18,
516   col = 19,
517   colgroup = 20,
518   data = 21,
519   datalist = 22,
520   dd = 23,
521   del = 24,
522   dfn = 25,
523   div = 26,
524   dl = 27,
525   dt = 28,
526   em = 29,
527   embed = 30,
528   fieldset = 31,
529   figcaption = 32,
530   figure = 33,
531   footer = 34,
532   form = 35,
533   h1 = 36,
534   h2 = 37,
535   h3 = 38,
536   h4 = 39,
537   h5 = 40,
538   h6 = 41,
539   head = 42,
540   header = 43,
541   hr = 44,
542   html = 45,
543   i = 46,
544   iframe = 47,
545   img = 48,
546   input = 49,
547   ins = 50,
548   kbd = 51,
549   keygen = 52,
550   label = 53,
551   legend = 54,
552   li = 55,
553   link = 56,
554   main = 57,
555   map = 58,
556   mark = 59,
557   meta = 60,
558   meter = 61,
559   nav = 62,
560   noscript = 63,
561   object = 64,
562   ol = 65,
563   optgroup = 66,
564   option = 67,
565   output = 68,
566   p = 69,
567   param = 70,
568   pre = 71,
569   progress = 72,
570   q = 73,
571   rb = 74,
572   rp = 75,
573   rt = 76,
574   rtc = 77,
575   ruby = 78,
576   s = 79,
577   samp = 80,
578   script = 81,
579   section = 82,
580   select = 83,
581   small = 84,
582   source = 85,
583   span = 86,
584   strong = 87,
585   style = 88,
586   sub = 89,
587   sup = 90,
588   table = 91,
589   tbody = 92,
590   td = 93,
591   template_ = 94,
592   textarea = 95,
593   tfoot = 96,
594   th = 97,
595   thead = 98,
596   time = 99,
597   title = 100,
598   tr = 101,
599   track = 102,
600   u = 103,
601   ul = 104,
602   var = 105,
603   video = 106,
604   wbr = 107,
605   root = 1024 // Special element used in unittests
606 }
607 
608 // deprecated("Use libwasm.types.Child instead") enum child;
609 enum child;
610 enum prop;
611 enum callback;
612 enum attr;
613 struct connect(field...)
614 {
615 };
616 struct visible(alias condition)
617 {
618 };
619 struct inject(alias parent_name)
620 {
621 };
622 struct entering(alias path)
623 {
624 };
625 struct leaving(alias path)
626 {
627 };
628 
629 template isTOrPointer(T, Target)
630 {
631   enum isTOrPointer = is(T : Target) || is(T : Target*);
632 }
633 
634 // TODO: implement others as well
635 enum ListenerType
636 {
637   click = 0,
638   change = 1,
639   input = 2,
640   keydown = 3,
641   keyup = 4,
642   dblclick = 5,
643   blur = 6,
644   mousemove = 7,
645   mouseup = 8,
646   mousedown = 9,
647   keypress = 10,
648   focus = 11
649 }
650 
651 enum EventType
652 {
653   animation = 0,
654   audioProcessing = 1,
655   beforeUnload = 2,
656   blob = 3,
657   clipboard = 4,
658   close = 5,
659   composition = 6,
660   custom = 7,
661   deviceLight = 8,
662   deviceMotion = 9,
663   deviceOrientation = 10,
664   deviceProximity = 11,
665   drag = 12,
666   error = 13,
667   fetch = 14,
668   focus = 15,
669   gamepad = 16,
670   hashChange = 17,
671   idbVersionChange = 18,
672   input = 19,
673   keyboard = 20,
674   mediaStream = 21,
675   message = 22,
676   mouse = 23,
677   mutation = 24,
678   offlineAudioCompletion = 25,
679   pageTransition = 26,
680   paymentRequestUpdate = 27,
681   pointer = 28,
682   popState = 29,
683   progress = 30,
684   rtcDataChannel = 31,
685   rtcIdentityError = 32,
686   rtcIdentity = 33,
687   rtcPeerConnectionIce = 34,
688   storage = 35,
689   svg = 36,
690   time = 37,
691   touch = 38,
692   trackTransition = 39,
693   ui = 40,
694   userProximity = 41,
695   webGlContext = 42,
696   wheel = 43,
697   event = 44
698 }
699 
700 @safe template as(Target)
701 {
702   static if (isBasicType!Target || is(Target : string))
703   {
704     auto as(Source)(auto ref Source s) if (hasMember!(Source, "handle"))
705     {
706       mixin("return libwasm_get__" ~ Target.stringof ~ "(s.handle);");
707     }
708   }
709   else static if (__traits(compiles, "Target.init.handle"))
710   {
711     @safe auto as(Source)(scope return ref Source s)
712     {
713       return cast(Target*)&s;
714     }
715 
716     @safe auto as(Source)(Source s) if (hasMember!(Source, "handle"))
717     {
718       Handle h = s.handle;
719       s.handle = 0;
720       return Target(h);
721     }
722   }
723 }
724 
725 auto toOpt(T)(return scope ref T item) @trusted
726 {
727   return Optional!(T*)(&item);
728 }
729 
730 auto recastOpt(T, U)(Optional!U item) @trusted
731 {
732   if (item.empty())
733   {
734     return Optional!T();
735   }
736   else
737   {
738     return Optional!T.construct(item.front);
739   }
740 }
741 
742 auto frontRef(T)(return scope ref T t) @trusted
743 {
744   static if (is(T : Optional!(Base*), Base))
745     return t.front;
746   else
747     return &t.front();
748 }
749 
750 Handle getOrCreateHandle(T)(scope ref T data) @trusted
751 {
752   static if (isBasicType!T || isSomeString!T && T.stringof != "typeof(null)")
753   {
754     static if (isSomeString!T && !is(T : string))
755       mixin("return libwasm_add__string(*cast(string*)&data);");
756     else static if (is(T == int[]))
757       mixin("return libwasm_add__ints(data);");
758     else static if (is(T == uint[]))
759       mixin("return libwasm_add__uints(data);");
760     else
761       mixin("return libwasm_add__" ~ T.stringof ~ "(data);");
762   }
763   else static if (is(T : Optional!U, U))
764   {
765     if (data.empty)
766       return 0;
767     return data.front;
768   }
769   else
770   {
771     return cast(Handle) data;
772   }
773 }
774 
775 auto dropHandle(T)(Handle data)
776 {
777   import std.traits : isBasicType;
778 
779   static if (isBasicType!T || is(T : string))
780   {
781     libwasm_removeObject(data);
782   }
783 }
784 
785 template libwasmMangle(T)
786 {
787   static if (hasMember!(T, "handle") || hasMember!(T, "_parent"))
788   {
789     enum libwasmMangle = "handle";
790   }
791   else
792   {
793     enum libwasmMangle = T.mangleof;
794   }
795 }
796 
797 template BridgeType(T)
798 {
799   static if (hasMember!(T, "handle") || hasMember!(T, "_parent"))
800   {
801     alias BridgeType = JsHandle;
802   }
803   else
804   {
805     alias BridgeType = T;
806   }
807 }
808 
809 mixin template ExternPromiseCallback(string funName, T, U)
810 {
811 nothrow:
812   static if (is(T == void))
813   {
814     pragma(mangle, funName)
815     mixin("extern(C) Handle " ~ funName ~ "(Handle, U delegate() nothrow);");
816   }
817   else
818   {
819     pragma(mangle, funName)
820     mixin("extern(C) Handle " ~ funName ~ "(Handle, U delegate(" ~ T.stringof ~ ") nothrow);");
821   }
822 }
823 
824 mixin template ExternPromiseCallback(string funName, T)
825 {
826 nothrow:
827   static if (is(T == void))
828   {
829     pragma(mangle, funName)
830     mixin("extern(C) Handle " ~ funName ~ "(Handle, void delegate() nothrow);");
831   }
832   else
833   {
834     pragma(mangle, funName)
835     mixin("extern(C) Handle " ~ funName ~ "(Handle, void delegate(" ~ T.stringof ~ ") nothrow);");
836   }
837 }
838 
839 auto all()(scope JsHandle[] args) {
840   Vector!Handle handles;
841   handles.reserve(args.length);
842   foreach (ref arg; args) {
843     handles ~= arg.handle;
844   }
845   
846   auto handle = JsObject(libwasm_add__uints(handles[]));
847   mixin("return JsPromise!Any(libasync_promise_all__promise(handle));");
848 }
849 auto allSettled()(scope JsHandle[] args) {  
850   Vector!Handle handles;
851   handles.reserve(args.length);
852   foreach (ref arg; args) {
853     handles ~= arg.handle;
854   } 
855   auto handle = JsObject(libwasm_add__uints(handles[]));
856   mixin("return JsPromise!Any(libasync_promise_allsettled__promise(handle));");
857 }
858 auto any()(scope JsHandle[] args) {   
859   Vector!Handle handles;
860   handles.reserve(args.length);
861   foreach (ref arg; args) {
862     handles ~= arg.handle;
863   }
864   auto handle = JsObject(libwasm_add__uints(handles[]));
865   mixin("return JsPromise!Any(libasync_promise_any__promise(handle));");
866 }
867 
868 struct JsPromise(T = Any)
869 {
870   alias U = Any;
871 nothrow:
872   JsHandle handle;
873   alias handle this;
874   this(Handle h)
875   {
876     this.handle = JsHandle(h);
877   }
878 
879   alias JoinedType = BridgeType!T;
880   enum ResultMangled = libwasmMangle!T;
881   static if (is(T == void))
882   {
883     alias FulfillCallback(P = void) = P delegate() nothrow;
884     alias JoinedCallback(P = void) = extern (C) P delegate() nothrow;
885     alias RejectCallback = extern (C) void delegate(U) nothrow;
886   }
887   else
888   {
889     alias FulfillCallback(P) = P delegate(T) nothrow;
890     alias JoinedCallback(P) = extern (C) P delegate(JoinedType) nothrow;
891     alias RejectCallback = extern (C) void delegate(U) nothrow;
892   }
893 
894   auto then(ResultType)(scope ResultType delegate(T) nothrow cb) return scope @trusted
895   {
896     enum TMangled = libwasmMangle!T;
897     enum ResultTypeMangled = libwasmMangle!ResultType;
898     enum funName = "promise_then_" ~ TMangled.length.stringof ~ TMangled ~ ResultTypeMangled;
899     mixin ExternPromiseCallback!(funName, JoinedType, BridgeType!ResultType);
900     mixin(
901       "return JsPromise!(ResultType)(" ~ funName ~ "(handle, cast(JoinedCallback!(BridgeType!ResultType))cb));");
902   }
903 
904   auto error()(scope void delegate(U) nothrow cb) return scope @trusted
905   {
906     enum TMangled = libwasmMangle!U;
907     enum funName = "promise_error_" ~ TMangled.length.stringof ~ TMangled;
908     mixin ExternPromiseCallback!(funName, U);
909     mixin("return JsPromise!(void)(" ~ funName ~ "(handle, cast(RejectCallback)cb));");
910   }
911 
912   // todo: .Finally(()=>
913   // todo: Promise.cancel(), Promise.state()
914 
915 }
916 
917 /// Waits for the promise to finish
918 void await(T)(auto ref T promise) {
919   libwasm_await__void(promise.handle.handle);
920 }
921 
922 struct Sequence(T)
923 {
924 nothrow:
925   JsHandle handle;
926   alias handle this;
927   this(Handle h)
928   {
929     this.handle = JsHandle(h);
930   }
931 }
932 
933 struct TypedArray(T)
934 {
935 nothrow:
936   JsHandle handle;
937   alias handle this;
938   this(Handle h)
939   {
940     this.handle = JsHandle(h);
941   }
942 }
943 
944 struct Int8Array
945 {
946 nothrow:
947   TypedArray!(byte) _array;
948   alias _array this;
949   this(Handle h)
950   {
951     _array = TypedArray!(byte)(h);
952   }
953 
954   static auto create()(const byte[] data)
955   {
956     return Int8Array(Int8Array_Create(data));
957   }
958 }
959 
960 struct Int16Array
961 {
962 nothrow:
963   TypedArray!(short) _array;
964   alias _array this;
965   this(Handle h)
966   {
967     _array = TypedArray!(short)(h);
968   }
969 }
970 
971 struct Int32Array
972 {
973 nothrow:
974   TypedArray!(int) _array;
975   alias _array this;
976   this(Handle h)
977   {
978     _array = TypedArray!(int)(h);
979   }
980 
981   static auto create()(const int[] data)
982   {
983     return Int32Array(Int32Array_Create(data));
984   }
985 }
986 
987 struct Uint8Array
988 {
989 nothrow:
990   TypedArray!(ubyte) _array;
991   alias _array this;
992   this(Handle h)
993   {
994     _array = TypedArray!(ubyte)(h);
995   }
996 
997   static auto create()(const ubyte[] data)
998   {
999     return Uint8Array(Uint8Array_Create(data));
1000   }
1001 }
1002 
1003 struct Uint16Array
1004 {
1005 nothrow:
1006   TypedArray!(ushort) _array;
1007   alias _array this;
1008   this(Handle h)
1009   {
1010     _array = TypedArray!(ushort)(h);
1011   }
1012 }
1013 
1014 struct Uint32Array
1015 {
1016 nothrow:
1017   TypedArray!(uint) _array;
1018   alias _array this;
1019   this(Handle h)
1020   {
1021     _array = TypedArray!(uint)(h);
1022   }
1023 }
1024 
1025 struct Float32Array
1026 {
1027 nothrow:
1028   TypedArray!(float) _array;
1029   alias _array this;
1030   this(Handle h)
1031   {
1032     _array = TypedArray!(float)(h);
1033   }
1034 
1035   static auto create()(const float[] data)
1036   {
1037     return Float32Array(Float32Array_Create(data));
1038   }
1039 }
1040 
1041 struct Float64Array
1042 {
1043 nothrow:
1044   TypedArray!(double) _array;
1045   alias _array this;
1046   this(Handle h)
1047   {
1048     _array = TypedArray!(double)(h);
1049   }
1050 }
1051 
1052 struct Uint8ClampedArray
1053 {
1054 nothrow:
1055   JsHandle handle;
1056   alias handle this;
1057   this(Handle h)
1058   {
1059     this.handle = JsHandle(h);
1060   }
1061 }
1062 
1063 struct DataView
1064 {
1065 nothrow:
1066   JsHandle handle;
1067   alias handle this;
1068   this(Handle h)
1069   {
1070     this.handle = JsHandle(h);
1071   }
1072 
1073   static auto create()(const ubyte[] data)
1074   {
1075     return DataView(DataView_Create(data));
1076   }
1077 }
1078 
1079 struct ArrayBuffer
1080 {
1081 nothrow:
1082   JsHandle handle;
1083   alias handle this;
1084   this(Handle h)
1085   {
1086     this.handle = JsHandle(h);
1087   }
1088 }
1089 
1090 struct InputStream
1091 {
1092 nothrow:
1093   JsHandle handle;
1094   alias handle this;
1095   this(Handle h)
1096   {
1097     this.handle = JsHandle(h);
1098   }
1099 }
1100 
1101 struct FrozenArray(T)
1102 {
1103 nothrow:
1104   JsHandle handle;
1105   alias handle this;
1106   this(Handle h)
1107   {
1108     this.handle = JsHandle(h);
1109   }
1110 }
1111 
1112 struct Iterator(T)
1113 {
1114 nothrow:
1115   JsHandle handle;
1116   alias handle this;
1117   this(Handle h)
1118   {
1119     this.handle = JsHandle(h);
1120   }
1121 }
1122 
1123 struct Record(T...)
1124 {
1125 nothrow:
1126   JsHandle handle;
1127   alias handle this;
1128   this(Handle h)
1129   {
1130     this.handle = JsHandle(h);
1131   }
1132 }
1133 
1134 struct ArrayPair(T, U)
1135 {
1136 nothrow:
1137   JsHandle handle;
1138   alias handle this;
1139   this(Handle h)
1140   {
1141     this.handle = JsHandle(h);
1142   }
1143 }
1144 
1145 struct Any
1146 {
1147 nothrow:
1148   JsHandle handle;
1149   alias handle this;
1150   this(Handle h)
1151   {
1152     this.handle = JsHandle(h);
1153   }
1154 }
1155 
1156 struct JsObject
1157 {
1158 nothrow:
1159   JsHandle handle;
1160   alias handle this;
1161   this(Handle h)
1162   {
1163     this.handle = JsHandle(h);
1164   }
1165 
1166   auto opDispatch(string name)()
1167   {
1168     return Any(libwasm_get__field(this.handle, name));
1169   }
1170   // opIndexAssign
1171 }
1172 
1173 struct JSON
1174 {
1175 nothrow:
1176   JsHandle handle;
1177   alias handle this;
1178   this(Handle h)
1179   {
1180     this.handle = JsHandle(h);
1181   }
1182 
1183   auto opIndex()(string name)
1184   {
1185     return JSON(libwasm_get__field(this.handle, name));
1186   }
1187 
1188   auto opIndex()(uint idx)
1189   {
1190     return JSON(libwasm_get_idx__field(this.handle, idx));
1191   }
1192 
1193   auto as(Target)() @trusted
1194   {
1195     return .as!(Target)(this);
1196   }
1197 
1198   static Handle parse()(string json)
1199   {
1200     return JSON_parse_string(json);
1201   }
1202 
1203   static string stringify()(ref JSON obj)
1204   {
1205     return JSON_stringify(obj.handle);
1206   }
1207 }
1208 
1209 struct BufferSource
1210 {
1211 nothrow:
1212   JsHandle handle;
1213   alias handle this;
1214   this(Handle h)
1215   {
1216     this.handle = JsHandle(h);
1217   }
1218 }
1219 
1220 struct MIDIInput
1221 {
1222 nothrow:
1223   JsHandle handle;
1224   alias handle this;
1225   this(Handle h)
1226   {
1227     this.handle = JsHandle(h);
1228   }
1229 }
1230 
1231 struct MIDIOutput
1232 {
1233 nothrow:
1234   JsHandle handle;
1235   alias handle this;
1236   this(Handle h)
1237   {
1238     this.handle = JsHandle(h);
1239   }
1240 }
1241 
1242 struct nsISupports
1243 {
1244 nothrow:
1245   JsHandle handle;
1246   alias handle this;
1247   this(Handle h)
1248   {
1249     this.handle = JsHandle(h);
1250   }
1251 }
1252 
1253 struct nsIVariant
1254 {
1255 nothrow:
1256   JsHandle handle;
1257   alias handle this;
1258   this(Handle h)
1259   {
1260     this.handle = JsHandle(h);
1261   }
1262 }
1263 
1264 struct ArrayBufferView
1265 {
1266 nothrow:
1267   JsHandle handle;
1268   alias handle this;
1269   this(Handle h)
1270   {
1271     this.handle = JsHandle(h);
1272   }
1273 }
1274 
1275 struct ReadableStream
1276 {
1277 nothrow:
1278   JsHandle handle;
1279   alias handle this;
1280   this(Handle h)
1281   {
1282     this.handle = JsHandle(h);
1283   }
1284 }
1285 
1286 struct AudioParam
1287 {
1288 nothrow:
1289   JsHandle handle;
1290   alias handle this;
1291   this(Handle h)
1292   {
1293     this.handle = JsHandle(h);
1294   }
1295 }
1296 
1297 import libwasm.bindings.Window : Window;
1298 
1299 alias WindowProxy = Window;
1300 
1301 extern (C)
1302 {
1303   Handle Int8Array_Create(const byte[]);
1304   Handle Int32Array_Create(const int[]);
1305   Handle Uint8Array_Create(const ubyte[]);
1306   Handle Float32Array_Create(const float[]);
1307   Handle DataView_Create(const ubyte[]);
1308 }