[wasm] Add support for pinvokes in user assemblies. (#14253)
[mono-project.git] / sdks / wasm / binding_support.js
blob1c77fa41d7b285ed1edc16ce025987c5095d5bc1
2 var BindingSupportLib = {
3         $BINDING__postset: 'BINDING.export_functions (Module);',
4         $BINDING: {
5                 BINDING_ASM: "[WebAssembly.Bindings]WebAssembly.Runtime",
6                 mono_wasm_object_registry: [],
7                 mono_wasm_ref_counter: 0,
8                 mono_wasm_free_list: [],
9                 mono_wasm_marshal_enum_as_int: false,
10                 mono_bindings_init: function (binding_asm) {
11                         this.BINDING_ASM = binding_asm;
12                 },
14                 export_functions: function (module) {
15                         module ["mono_bindings_init"] = BINDING.mono_bindings_init.bind(BINDING);
16                         module ["mono_method_invoke"] = BINDING.call_method.bind(BINDING);
17                         module ["mono_method_get_call_signature"] = BINDING.mono_method_get_call_signature.bind(BINDING);
18                         module ["mono_method_resolve"] = BINDING.resolve_method_fqn.bind(BINDING);
19                         module ["mono_bind_static_method"] = BINDING.bind_static_method.bind(BINDING);
20                         module ["mono_call_static_method"] = BINDING.call_static_method.bind(BINDING);
21                 },
23                 bindings_lazy_init: function () {
24                         if (this.init)
25                                 return;
26                 
27                         this.assembly_load = Module.cwrap ('mono_wasm_assembly_load', 'number', ['string']);
28                         this.find_class = Module.cwrap ('mono_wasm_assembly_find_class', 'number', ['number', 'string', 'string']);
29                         this.find_method = Module.cwrap ('mono_wasm_assembly_find_method', 'number', ['number', 'string', 'number']);
30                         this.invoke_method = Module.cwrap ('mono_wasm_invoke_method', 'number', ['number', 'number', 'number', 'number']);
31                         this.mono_string_get_utf8 = Module.cwrap ('mono_wasm_string_get_utf8', 'number', ['number']);
32                         this.js_string_to_mono_string = Module.cwrap ('mono_wasm_string_from_js', 'number', ['string']);
33                         this.mono_get_obj_type = Module.cwrap ('mono_wasm_get_obj_type', 'number', ['number']);
34                         this.mono_unbox_int = Module.cwrap ('mono_unbox_int', 'number', ['number']);
35                         this.mono_unbox_float = Module.cwrap ('mono_wasm_unbox_float', 'number', ['number']);
36                         this.mono_array_length = Module.cwrap ('mono_wasm_array_length', 'number', ['number']);
37                         this.mono_array_get = Module.cwrap ('mono_wasm_array_get', 'number', ['number', 'number']);
38                         this.mono_obj_array_new = Module.cwrap ('mono_wasm_obj_array_new', 'number', ['number']);
39                         this.mono_obj_array_set = Module.cwrap ('mono_wasm_obj_array_set', 'void', ['number', 'number', 'number']);
40                         this.mono_unbox_enum = Module.cwrap ('mono_wasm_unbox_enum', 'number', ['number']);
42                         // receives a byteoffset into allocated Heap with a size.
43                         this.mono_typed_array_new = Module.cwrap ('mono_wasm_typed_array_new', 'number', ['number','number','number','number']);
45                         var binding_fqn_asm = this.BINDING_ASM.substring(this.BINDING_ASM.indexOf ("[") + 1, this.BINDING_ASM.indexOf ("]")).trim();
46                         var binding_fqn_class = this.BINDING_ASM.substring (this.BINDING_ASM.indexOf ("]") + 1).trim();
47                         
48                         this.binding_module = this.assembly_load (binding_fqn_asm);
49                         if (!this.binding_module)
50                                 throw "Can't find bindings module assembly: " + binding_fqn_asm;
52                         if (binding_fqn_class !== null && typeof binding_fqn_class !== "undefined")
53                         {
54                                 var namespace = "WebAssembly";
55                                 var classname = binding_fqn_class.length > 0 ? binding_fqn_class : "Runtime";
56                                 if (binding_fqn_class.indexOf(".") != -1) {
57                                         var idx = binding_fqn_class.lastIndexOf(".");
58                                         namespace = binding_fqn_class.substring (0, idx);
59                                         classname = binding_fqn_class.substring (idx + 1);
60                                 }
61                         }
63                         var wasm_runtime_class = this.find_class (this.binding_module, namespace, classname)
64                         if (!wasm_runtime_class)
65                                 throw "Can't find " + binding_fqn_class + " class";
67                         var get_method = function(method_name) {
68                                 var res = BINDING.find_method (wasm_runtime_class, method_name, -1)
69                                 if (!res)
70                                         throw "Can't find method " + namespace + "." + classname + ":" + method_name;
71                                 return res;
72                         }
73                         this.bind_js_obj = get_method ("BindJSObject");
74                         this.bind_core_clr_obj = get_method ("BindCoreCLRObject");
75                         this.bind_existing_obj = get_method ("BindExistingObject");
76                         this.unbind_js_obj = get_method ("UnBindJSObject");
77                         this.unbind_js_obj_and_free = get_method ("UnBindJSObjectAndFree");                     
78                         this.unbind_raw_obj_and_free = get_method ("UnBindRawJSObjectAndFree");                 
79                         this.get_js_id = get_method ("GetJSObjectId");
80                         this.get_raw_mono_obj = get_method ("GetMonoObject");
82                         this.box_js_int = get_method ("BoxInt");
83                         this.box_js_double = get_method ("BoxDouble");
84                         this.box_js_bool = get_method ("BoxBool");
85                         this.is_simple_array = get_method ("IsSimpleArray");
86                         this.get_core_type = get_method ("GetCoreType");
87                         this.setup_js_cont = get_method ("SetupJSContinuation");
89                         this.create_tcs = get_method ("CreateTaskSource");
90                         this.set_tcs_result = get_method ("SetTaskSourceResult");
91                         this.set_tcs_failure = get_method ("SetTaskSourceFailure");
92                         this.tcs_get_task_and_bind = get_method ("GetTaskAndBind");
93                         this.get_call_sig = get_method ("GetCallSignature");
95                         this.object_to_string = get_method ("ObjectToString");
97                         this.object_to_enum = get_method ("ObjectToEnum");
98                         this.init = true;
99                 },              
101                 get_js_obj: function (js_handle) {
102                         if (js_handle > 0)
103                                 return this.mono_wasm_require_handle(js_handle);
104                         return null;
105                 },
106                 
107                 //FIXME this is wastefull, we could remove the temp malloc by going the UTF16 route
108                 //FIXME this is unsafe, cuz raw objects could be GC'd.
109                 conv_string: function (mono_obj) {
110                         if (mono_obj == 0)
111                                 return null;
112                         var raw = this.mono_string_get_utf8 (mono_obj);
113                         var res = Module.UTF8ToString (raw);
114                         Module._free (raw);
116                         return res;
117                 },
119                 is_nested_array: function (ele) {
120                         return this.call_method (this.is_simple_array, null, "mi", [ ele ]);
121                 },
123                 mono_array_to_js_array: function (mono_array) {
124                         if (mono_array == 0)
125                                 return null;
127                         var res = [];
128                         var len = this.mono_array_length (mono_array);
129                         for (var i = 0; i < len; ++i)
130                         {
131                                 var ele = this.mono_array_get (mono_array, i);
132                                 if (this.is_nested_array(ele))
133                                         res.push(this.mono_array_to_js_array(ele));
134                                 else
135                                         res.push (this.unbox_mono_obj (ele));
136                         }
138                         return res;
139                 },
141                 js_array_to_mono_array: function (js_array) {
142                         var mono_array = this.mono_obj_array_new (js_array.length);
143                         for (var i = 0; i < js_array.length; ++i) {
144                                 this.mono_obj_array_set (mono_array, i, this.js_to_mono_obj (js_array [i]));
145                         }
146                         return mono_array;
147                 },
149                 unbox_mono_obj: function (mono_obj) {
150                         if (mono_obj == 0)
151                                 return undefined;
152                         var type = this.mono_get_obj_type (mono_obj);
153                         //See MARSHAL_TYPE_ defines in driver.c
154                         switch (type) {
155                         case 1: // int
156                                 return this.mono_unbox_int (mono_obj);
157                         case 2: // float
158                                 return this.mono_unbox_float (mono_obj);
159                         case 3: //string
160                                 return this.conv_string (mono_obj);
161                         case 4: //vts
162                                 throw new Error ("no idea on how to unbox value types");
163                         case 5: { // delegate
164                                 var obj = this.extract_js_obj (mono_obj);
165                                 return function () {
166                                         return BINDING.invoke_delegate (obj, arguments);
167                                 };
168                         }
169                         case 6: {// Task
171                                 if (typeof Promise === "undefined" || typeof Promise.resolve === "undefined")
172                                         throw new Error ("Promises are not supported thus C# Tasks can not work in this context.");
174                                 var obj = this.extract_js_obj (mono_obj);
175                                 var cont_obj = null;
176                                 var promise = new Promise (function (resolve, reject) {
177                                         cont_obj = {
178                                                 resolve: resolve,
179                                                 reject: reject
180                                         };
181                                 });
183                                 this.call_method (this.setup_js_cont, null, "mo", [ mono_obj, cont_obj ]);
184                                 obj.__mono_js_cont__ = cont_obj.__mono_gchandle__;
185                                 cont_obj.__mono_js_task__ = obj.__mono_gchandle__;
186                                 return promise;
187                         }
189                         case 7: // ref type
190                                 return this.extract_js_obj (mono_obj);
192                         case 8: // bool
193                                 return this.mono_unbox_int (mono_obj) != 0;
195                         case 9: // enum
197                                 if(this.mono_wasm_marshal_enum_as_int)
198                                 {
199                                         return this.mono_unbox_enum (mono_obj);
200                                 }
201                                 else
202                                 {
203                                         enumValue = this.call_method(this.object_to_string, null, "m", [ mono_obj ]);
204                                 }
206                                 return enumValue;
209                         case 11: 
210                         case 12: 
211                         case 13: 
212                         case 14: 
213                         case 15: 
214                         case 16: 
215                         case 17: 
216                         case 18:
217                         {
218                                 throw new Error ("Marshalling of primitive arrays are not supported.  Use the corresponding TypedArray instead.");
219                         }                       
220         
221                         default:
222                                 throw new Error ("no idea on how to unbox object kind " + type);
223                         }
224                 },
226                 create_task_completion_source: function () {
227                         return this.call_method (this.create_tcs, null, "i", [ -1 ]);
228                 },
230                 set_task_result: function (tcs, result) {
231                         tcs.is_mono_tcs_result_set = true;
232                         this.call_method (this.set_tcs_result, null, "oo", [ tcs, result ]);
233                         if (tcs.is_mono_tcs_task_bound)
234                                 this.free_task_completion_source(tcs);
235                 },
237                 set_task_failure: function (tcs, reason) {
238                         tcs.is_mono_tcs_result_set = true;
239                         this.call_method (this.set_tcs_failure, null, "os", [ tcs, reason.toString () ]);
240                         if (tcs.is_mono_tcs_task_bound)
241                                 this.free_task_completion_source(tcs);
242                 },
244                 // https://github.com/Planeshifter/emscripten-examples/blob/master/01_PassingArrays/sum_post.js
245                 js_typedarray_to_heap: function(typedArray){
246                         var numBytes = typedArray.length * typedArray.BYTES_PER_ELEMENT;
247                         var ptr = Module._malloc(numBytes);
248                         var heapBytes = new Uint8Array(Module.HEAPU8.buffer, ptr, numBytes);
249                         heapBytes.set(new Uint8Array(typedArray.buffer, typedArray.byteOffset, numBytes));
250                         return heapBytes;
251                 },
252                 js_to_mono_obj: function (js_obj) {
253                         this.bindings_lazy_init ();
255                         if (js_obj == null || js_obj == undefined)
256                                 return 0;
257                         if (typeof js_obj === 'number') {
258                                 if (parseInt(js_obj) == js_obj)
259                                         return this.call_method (this.box_js_int, null, "im", [ js_obj ]);
260                                 return this.call_method (this.box_js_double, null, "dm", [ js_obj ]);
261                         }
262                         if (typeof js_obj === 'string')
263                                 return this.js_string_to_mono_string (js_obj);
265                         if (typeof js_obj === 'boolean')
266                                 return this.call_method (this.box_js_bool, null, "im", [ js_obj ]);
268                         if (Promise.resolve(js_obj) === js_obj) {
269                                 var the_task = this.try_extract_mono_obj (js_obj);
270                                 if (the_task)
271                                         return the_task;
272                                 var tcs = this.create_task_completion_source ();
274                                 js_obj.then (function (result) {
275                                         BINDING.set_task_result (tcs, result);
276                                 }, function (reason) {
277                                         BINDING.set_task_failure (tcs, reason);
278                                 })
280                                 return this.get_task_and_bind (tcs, js_obj);
281                         }
283                         return this.extract_mono_obj (js_obj);
284                 },
285                 js_typed_array_to_array : function (js_obj) {
287                         // JavaScript typed arrays are array-like objects and provide a mechanism for accessing 
288                         // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays 
289                         // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
290                         //  is an object representing a chunk of data; it has no format to speak of, and offers no 
291                         // mechanism for accessing its contents. In order to access the memory contained in a buffer, 
292                         // you need to use a view. A view provides a context â€” that is, a data type, starting offset, 
293                         // and number of elements â€” that turns the data into an actual typed array.
294                         // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
295                         if (!!(js_obj.buffer instanceof ArrayBuffer && js_obj.BYTES_PER_ELEMENT)) 
296                         {
297                                 var arrayType = 0;      
298                                 if (js_obj instanceof Int8Array)
299                                         arrayType = 11;
300                                 if (js_obj instanceof Uint8Array)
301                                         arrayType = 12;
302                                 if (js_obj instanceof Uint8ClampedArray)
303                                         arrayType = 12;
304                                 if (js_obj instanceof Int16Array)
305                                         arrayType = 13;
306                                 if (js_obj instanceof Uint16Array)
307                                         arrayType = 14;
308                                 if (js_obj instanceof Int32Array)
309                                         arrayType = 15;
310                                 if (js_obj instanceof Uint32Array)
311                                         arrayType = 16;
312                                 if (js_obj instanceof Float32Array)
313                                         arrayType = 17;
314                                 if (js_obj instanceof Float64Array)
315                                         arrayType = 18;
317                                 var heapBytes = this.js_typedarray_to_heap(js_obj);
318                                 var bufferArray = this.mono_typed_array_new(heapBytes.byteOffset, js_obj.length, js_obj.BYTES_PER_ELEMENT, arrayType);
319                                 Module._free(heapBytes.byteOffset);
320                                 return bufferArray;
321                         }
322                         else {
323                                 throw new Error("Object '" + js_obj + "' is not a typed array");
324                         } 
327                 },
328                 // Copy the existing typed array to the heap pointed to by the pinned array address
329                 //       typed array memory -> copy to heap -> address of managed pinned array
330                 typedarray_copy_to : function (typed_array, pinned_array, begin, end, bytes_per_element) {
332                         // JavaScript typed arrays are array-like objects and provide a mechanism for accessing 
333                         // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays 
334                         // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
335                         //  is an object representing a chunk of data; it has no format to speak of, and offers no 
336                         // mechanism for accessing its contents. In order to access the memory contained in a buffer, 
337                         // you need to use a view. A view provides a context â€” that is, a data type, starting offset, 
338                         // and number of elements â€” that turns the data into an actual typed array.
339                         // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
340                         if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT)) 
341                         {
342                                 // Some sanity checks of what is being asked of us
343                                 // lets play it safe and throw an error here instead of assuming to much.
344                                 // Better safe than sorry later
345                                 if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
346                                         throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
348                                 // how much space we have to work with
349                                 var num_of_bytes = (end - begin) * bytes_per_element;
350                                 // how much typed buffer space are we talking about
351                                 var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
352                                 // only use what is needed.
353                                 if (num_of_bytes > view_bytes)
354                                         num_of_bytes = view_bytes;
356                                 // offset index into the view
357                                 var offset = begin * bytes_per_element;
359                                 // Create a view over the heap pointed to by the pinned array address
360                                 var heapBytes = new Uint8Array(Module.HEAPU8.buffer, pinned_array + offset, num_of_bytes);
361                                 // Copy the bytes of the typed array to the heap.
362                                 heapBytes.set(new Uint8Array(typed_array.buffer, typed_array.byteOffset, num_of_bytes));
364                                 return num_of_bytes;
365                         }
366                         else {
367                                 throw new Error("Object '" + typed_array + "' is not a typed array");
368                         } 
370                 },      
371                 // Copy the pinned array address from pinned_array allocated on the heap to the typed array.
372                 //       adress of managed pinned array -> copy from heap -> typed array memory
373                 typedarray_copy_from : function (typed_array, pinned_array, begin, end, bytes_per_element) {
375                         // JavaScript typed arrays are array-like objects and provide a mechanism for accessing 
376                         // raw binary data. (...) To achieve maximum flexibility and efficiency, JavaScript typed arrays 
377                         // split the implementation into buffers and views. A buffer (implemented by the ArrayBuffer object)
378                         //  is an object representing a chunk of data; it has no format to speak of, and offers no 
379                         // mechanism for accessing its contents. In order to access the memory contained in a buffer, 
380                         // you need to use a view. A view provides a context â€” that is, a data type, starting offset, 
381                         // and number of elements â€” that turns the data into an actual typed array.
382                         // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays
383                         if (!!(typed_array.buffer instanceof ArrayBuffer && typed_array.BYTES_PER_ELEMENT)) 
384                         {
385                                 // Some sanity checks of what is being asked of us
386                                 // lets play it safe and throw an error here instead of assuming to much.
387                                 // Better safe than sorry later
388                                 if (bytes_per_element !== typed_array.BYTES_PER_ELEMENT)
389                                         throw new Error("Inconsistent element sizes: TypedArray.BYTES_PER_ELEMENT '" + typed_array.BYTES_PER_ELEMENT + "' sizeof managed element: '" + bytes_per_element + "'");
391                                 // how much space we have to work with
392                                 var num_of_bytes = (end - begin) * bytes_per_element;
393                                 // how much typed buffer space are we talking about
394                                 var view_bytes = typed_array.length * typed_array.BYTES_PER_ELEMENT;
395                                 // only use what is needed.
396                                 if (num_of_bytes > view_bytes)
397                                         num_of_bytes = view_bytes;
399                                 // Create a new view for mapping
400                                 var typedarrayBytes = new Uint8Array(typed_array.buffer, 0, num_of_bytes);
401                                 // offset index into the view
402                                 var offset = begin * bytes_per_element;
403                                 // Set view bytes to value from HEAPU8
404                                 typedarrayBytes.set(Module.HEAPU8.subarray(pinned_array + offset, pinned_array + offset + num_of_bytes));
405                                 return num_of_bytes;
406                         }
407                         else {
408                                 throw new Error("Object '" + typed_array + "' is not a typed array");
409                         } 
411                 },      
412                 // Creates a new typed array from pinned array address from pinned_array allocated on the heap to the typed array.
413                 //       adress of managed pinned array -> copy from heap -> typed array memory
414                 typed_array_from : function (pinned_array, begin, end, bytes_per_element, type) {
416                         // typed array
417                         var newTypedArray = 0;
419                         switch (type)
420                         {
421                                 case 5: 
422                                         newTypedArray = new Int8Array(end - begin);
423                                         break;
424                                 case 6: 
425                                         newTypedArray = new Uint8Array(end - begin);
426                                         break;
427                                 case 7: 
428                                         newTypedArray = new Int16Array(end - begin);
429                                         break;
430                                 case 8: 
431                                         newTypedArray = new Uint16Array(end - begin);
432                                         break;
433                                 case 9: 
434                                         newTypedArray = new Int32Array(end - begin);
435                                         break;
436                                 case 10: 
437                                         newTypedArray = new Uint32Array(end - begin);
438                                         break;
439                                 case 13: 
440                                         newTypedArray = new Float32Array(end - begin);
441                                         break;
442                                 case 14:
443                                         newTypedArray = new Float64Array(end - begin);
444                                         break;
445                                 case 15:  // This is a special case because the typed array is also byte[]
446                                         newTypedArray = new Uint8ClampedArray(end - begin);
447                                         break;
448                         }
450                         this.typedarray_copy_from(newTypedArray, pinned_array, begin, end, bytes_per_element);
451                         return newTypedArray;
452                 },              
453                 js_to_mono_enum: function (method, parmIdx, js_obj) {
454                         this.bindings_lazy_init ();
455     
456                         if (js_obj === null || typeof js_obj === "undefined")
457                                 return 0;
459                         var monoObj = this.js_to_mono_obj(js_obj);
460                         // Check enum contract
461                         var monoEnum = this.call_method(this.object_to_enum, null, "iimm", [ method, parmIdx, monoObj ])
462                         // return the unboxed enum value.
463                         return this.mono_unbox_enum(monoEnum);
464                 },
465                 wasm_binding_obj_new: function (js_obj_id, type)
466                 {
467                         return this.call_method (this.bind_js_obj, null, "io", [js_obj_id, type]);
468                 },
469                 wasm_bind_existing: function (mono_obj, js_id)
470                 {
471                         return this.call_method (this.bind_existing_obj, null, "mi", [mono_obj, js_id]);
472                 },
474                 wasm_bind_core_clr_obj: function (js_id, gc_handle)
475                 {
476                         return this.call_method (this.bind_core_clr_obj, null, "ii", [js_id, gc_handle]);
477                 },
479                 wasm_unbind_js_obj: function (js_obj_id)
480                 {
481                         this.call_method (this.unbind_js_obj, null, "i", [js_obj_id]);
482                 },              
484                 wasm_unbind_js_obj_and_free: function (js_obj_id)
485                 {
486                         this.call_method (this.unbind_js_obj_and_free, null, "i", [js_obj_id]);
487                 },              
489                 wasm_get_js_id: function (mono_obj)
490                 {
491                         return this.call_method (this.get_js_id, null, "m", [mono_obj]);
492                 },
494                 wasm_get_raw_obj: function (gchandle)
495                 {
496                         return this.call_method (this.get_raw_mono_obj, null, "im", [gchandle]);
497                 },
499                 try_extract_mono_obj:function (js_obj) {
500                         if (js_obj === null || typeof js_obj === "undefined" || typeof js_obj.__mono_gchandle__ === "undefined")
501                                 return 0;
502                         return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
503                 },
505                 mono_method_get_call_signature: function(method) {
506                         this.bindings_lazy_init ();
508                         return this.call_method (this.get_call_sig, null, "i", [ method ]);
509                 },
511                 get_task_and_bind: function (tcs, js_obj) {
512                         var gc_handle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
513                         var task_gchandle = this.call_method (this.tcs_get_task_and_bind, null, "oi", [ tcs, gc_handle + 1 ]);
514                         js_obj.__mono_gchandle__ = task_gchandle;
515                         this.mono_wasm_object_registry[gc_handle] = js_obj;
516                         this.free_task_completion_source(tcs);
517                         tcs.is_mono_tcs_task_bound = true;
518                         js_obj.__mono_bound_tcs__ = tcs.__mono_gchandle__;
519                         tcs.__mono_bound_task__ = js_obj.__mono_gchandle__;
520                         return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
521                 },
523                 free_task_completion_source: function (tcs) {
524                         if (tcs.is_mono_tcs_result_set)
525                         {
526                                 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_gchandle__ ]);
527                         }
528                         if (tcs.__mono_bound_task__)
529                         {
530                                 this.call_method (this.unbind_raw_obj_and_free, null, "ii", [ tcs.__mono_bound_task__ ]);
531                         }
532                 },
534                 extract_mono_obj: function (js_obj) {
536                         if (js_obj === null || typeof js_obj === "undefined")
537                                 return 0;
539                         if (!js_obj.is_mono_bridged_obj) {
540                                 var gc_handle = this.mono_wasm_register_obj(js_obj);
541                                 return this.wasm_get_raw_obj (gc_handle);
542                         }
545                         return this.wasm_get_raw_obj (js_obj.__mono_gchandle__);
546                 },
548                 extract_js_obj: function (mono_obj) {
549                         if (mono_obj == 0)
550                                 return null;
552                         var js_id = this.wasm_get_js_id (mono_obj);
553                         if (js_id > 0)
554                                 return this.mono_wasm_require_handle(js_id);
556                         var gcHandle = this.mono_wasm_free_list.length ? this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
557                         var js_obj = {
558                                 __mono_gchandle__: this.wasm_bind_existing(mono_obj, gcHandle + 1),
559                                 is_mono_bridged_obj: true
560                         };
562                         this.mono_wasm_object_registry[gcHandle] = js_obj;
563                         return js_obj;
564                 },
566                 /*
567                 args_marshal is a string with one character per parameter that tells how to marshal it, here are the valid values:
569                 i: int32
570                 j: int32 - Enum with underlying type of int32
571                 l: int64 
572                 k: int64 - Enum with underlying type of int64
573                 f: float
574                 d: double
575                 s: string
576                 o: js object will be converted to a C# object (this will box numbers/bool/promises)
577                 m: raw mono object. Don't use it unless you know what you're doing
579                 additionally you can append 'm' to args_marshal beyond `args.length` if you don't want the return value marshaled
580                 */
581                 call_method: function (method, this_arg, args_marshal, args) {
582                         this.bindings_lazy_init ();
584                         var extra_args_mem = 0;
585                         for (var i = 0; i < args.length; ++i) {
586                                 //long/double memory must be 8 bytes aligned and I'm being lazy here
587                                 if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd' || args_marshal[i] == 'j' || args_marshal[i] == 'k')
588                                         extra_args_mem += 8;
589                         }
591                         var extra_args_mem = extra_args_mem ? Module._malloc (extra_args_mem) : 0;
592                         var extra_arg_idx = 0;
593                         var args_mem = Module._malloc (args.length * 4);
594                         var eh_throw = Module._malloc (4);
595                         for (var i = 0; i < args.length; ++i) {
596                                 if (args_marshal[i] == 's') {
597                                         Module.setValue (args_mem + i * 4, this.js_string_to_mono_string (args [i]), "i32");
598                                 } else if (args_marshal[i] == 'm') {
599                                         Module.setValue (args_mem + i * 4, args [i], "i32");
600                                 } else if (args_marshal[i] == 'o') {
601                                         Module.setValue (args_mem + i * 4, this.js_to_mono_obj (args [i]), "i32");
602                                 } else if (args_marshal[i] == 'j'  || args_marshal[i] == 'k') {
603                                         var enumVal = this.js_to_mono_enum(method, i, args[i]);
604                 
605                                         var extra_cell = extra_args_mem + extra_arg_idx;
606                                         extra_arg_idx += 8;
608                                         if (args_marshal[i] == 'j')
609                                                 Module.setValue (extra_cell, enumVal, "i32");
610                                         else if (args_marshal[i] == 'k')
611                                                 Module.setValue (extra_cell, enumVal, "i64");
613                                         Module.setValue (args_mem + i * 4, extra_cell, "i32");
614                                 } else if (args_marshal[i] == 'i' || args_marshal[i] == 'f' || args_marshal[i] == 'l' || args_marshal[i] == 'd') {
615                                         var extra_cell = extra_args_mem + extra_arg_idx;
616                                         extra_arg_idx += 8;
618                                         if (args_marshal[i] == 'i')
619                                                 Module.setValue (extra_cell, args [i], "i32");
620                                         else if (args_marshal[i] == 'l')
621                                                 Module.setValue (extra_cell, args [i], "i64");
622                                         else if (args_marshal[i] == 'f')
623                                                 Module.setValue (extra_cell, args [i], "float");
624                                         else
625                                                 Module.setValue (extra_cell, args [i], "double");
627                                         Module.setValue (args_mem + i * 4, extra_cell, "i32");
628                                 }
629                         }
630                         Module.setValue (eh_throw, 0, "i32");
632                         var res = this.invoke_method (method, this_arg, args_mem, eh_throw);
634                         var eh_res = Module.getValue (eh_throw, "i32");
636                         if (extra_args_mem)
637                                 Module._free (extra_args_mem);
638                         Module._free (args_mem);
639                         Module._free (eh_throw);
641                         if (eh_res != 0) {
642                                 var msg = this.conv_string (res);
643                                 throw new Error (msg); //the convention is that invoke_method ToString () any outgoing exception
644                         }
646                         if (args_marshal !== null && typeof args_marshal !== "undefined") 
647                         {
648                                 if (args_marshal.length >= args.length && args_marshal [args.length] === "m")
649                                         return res;
650                         }
652                         return this.unbox_mono_obj (res);
653                 },
655                 invoke_delegate: function (delegate_obj, js_args) {
656                         this.bindings_lazy_init ();
658                         if (!this.delegate_dynamic_invoke) {
659                                 if (!this.corlib)
660                                         this.corlib = this.assembly_load ("mscorlib");
661                                 if (!this.delegate_class)
662                                         this.delegate_class = this.find_class (this.corlib, "System", "Delegate");
663                                 if (!this.delegate_class)
664                                 {
665                                         throw new Error("System.Delegate class can not be resolved.");
666                                 }
667                                 this.delegate_dynamic_invoke = this.find_method (this.delegate_class, "DynamicInvoke", -1);
668                         }
669                         var mono_args = this.js_array_to_mono_array (js_args);
670                         if (!this.delegate_dynamic_invoke)
671                                 throw new Error("System.Delegate.DynamicInvoke method can not be resolved.");
672                         // Note: the single 'm' passed here is causing problems with AOT.  Changed to "mo" again.  
673                         // This may need more analysis if causes problems again.
674                         return this.call_method (this.delegate_dynamic_invoke, this.extract_mono_obj (delegate_obj), "mo", [ mono_args ]);
675                 },
676                 
677                 resolve_method_fqn: function (fqn) {
678                         var assembly = fqn.substring(fqn.indexOf ("[") + 1, fqn.indexOf ("]")).trim();
679                         fqn = fqn.substring (fqn.indexOf ("]") + 1).trim();
681                         var methodname = fqn.substring(fqn.indexOf (":") + 1);
682                         fqn = fqn.substring (0, fqn.indexOf (":")).trim ();
684                         var namespace = "";
685                         var classname = fqn;
686                         if (fqn.indexOf(".") != -1) {
687                                 var idx = fqn.lastIndexOf(".");
688                                 namespace = fqn.substring (0, idx);
689                                 classname = fqn.substring (idx + 1);
690                         }
692                         var asm = this.assembly_load (assembly);
693                         if (!asm)
694                                 throw new Error ("Could not find assembly: " + assembly);
696                         var klass = this.find_class(asm, namespace, classname);
697                         if (!klass)
698                                 throw new Error ("Could not find class: " + namespace + ":" +classname);
700                         var method = this.find_method (klass, methodname, -1);
701                         if (!method)
702                                 throw new Error ("Could not find method: " + methodname);
703                         return method;
704                 },
706                 call_static_method: function (fqn, args, signature) {
707                         this.bindings_lazy_init ();
709                         var method = this.resolve_method_fqn (fqn);
711                         if (typeof signature === "undefined")
712                                 signature = Module.mono_method_get_call_signature (method);
714                         return this.call_method (method, null, signature, args);
715                 },
717                 bind_static_method: function (fqn, signature) {
718                         this.bindings_lazy_init ();
720                         var method = this.resolve_method_fqn (fqn);
722                         if (typeof signature === "undefined")
723                                 signature = Module.mono_method_get_call_signature (method);
725                         return function() {
726                                 return BINDING.call_method (method, null, signature, arguments);
727                         };
728                 },
729                 wasm_get_core_type: function (obj)
730                 {
731                         return this.call_method (this.get_core_type, null, "so", [ "WebAssembly.Core."+obj.constructor.name ]);
732                 },
733                 get_wasm_type: function(obj) {
734                         var coreType = obj[Symbol.for("wasm type")];
735                         if (typeof coreType === "undefined") {
736                                 switch (obj.constructor.name) {
737                                         case "Array":
738                                                 coreType = this.wasm_get_core_type(obj);
739                                                 if (typeof coreType !== "undefined") {
740                                                         Array.prototype[Symbol.for("wasm type")] = coreType
741                                                 }
742                                                 break;
743                                         case "ArrayBuffer":
744                                                 coreType = this.wasm_get_core_type(obj);
745                                                 if (typeof coreType !== "undefined") {
746                                                         ArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
747                                                 }
748                                                 break;
749                                         case "Int8Array":
750                                                 coreType = this.wasm_get_core_type(obj);
751                                                 if (typeof coreType !== "undefined") {
752                                                         Int8Array.prototype[Symbol.for("wasm type")] = coreType
753                                                 }
754                                                 break;
755                                         case "Uint8Array":
756                                                 coreType = this.wasm_get_core_type(obj);
757                                                 if (typeof coreType !== "undefined") {
758                                                         Uint8Array.prototype[Symbol.for("wasm type")] = coreType
759                                                 }
760                                                 break;
761                                         case "Uint8ClampedArray":
762                                                 coreType = this.wasm_get_core_type(obj);
763                                                 if (typeof coreType !== "undefined") {
764                                                         Uint8ClampedArray.prototype[Symbol.for("wasm type")] = coreType
765                                                 }
766                                                 break;
767                                         case "Int16Array":
768                                                 coreType = this.wasm_get_core_type(obj);
769                                                 if (typeof coreType !== "undefined") {
770                                                         Int16Array.prototype[Symbol.for("wasm type")] = coreType
771                                                 }
772                                                 break;
773                                         case "Uint16Array":
774                                                 coreType = this.wasm_get_core_type(obj);
775                                                 if (typeof coreType !== "undefined") {
776                                                         Uint16Array.prototype[Symbol.for("wasm type")] = coreType
777                                                 }
778                                                 break;
779                                         case "Int32Array":
780                                                 coreType = this.wasm_get_core_type(obj);
781                                                 if (typeof coreType !== "undefined") {
782                                                         Int32Array.prototype[Symbol.for("wasm type")] = coreType
783                                                 }
784                                                 break;
785                                         case "Uint32Array":
786                                                 coreType = this.wasm_get_core_type(obj);
787                                                 if (typeof coreType !== "undefined") {
788                                                         Uint32Array.prototype[Symbol.for("wasm type")] = coreType
789                                                 }
790                                                 return coreType;
791                                         case "Float32Array":
792                                                 coreType = this.wasm_get_core_type(obj);
793                                                 if (typeof coreType !== "undefined") {
794                                                         Float32Array.prototype[Symbol.for("wasm type")] = coreType
795                                                 }
796                                                 break;
797                                         case "Float64Array":
798                                                 coreType = this.wasm_get_core_type(obj);
799                                                 if (typeof coreType !== "undefined") {
800                                                         Float64Array.prototype[Symbol.for("wasm type")] = coreType
801                                                 }
802                                                 break;
803                                         case "Function":
804                                                 coreType = this.wasm_get_core_type(obj);
805                                                 if (typeof coreType !== "undefined") {
806                                                         Function.prototype[Symbol.for("wasm type")] = coreType
807                                                 }
808                                                 break;
809                                         case "SharedArrayBuffer":
810                                                 coreType = this.wasm_get_core_type(obj);
811                                                 if (typeof coreType !== "undefined") {
812                                                         SharedArrayBuffer.prototype[Symbol.for("wasm type")] = coreType
813                                                 }
814                                                 break;
815                                 }
816                         }
817                         return coreType;
818                 },
819                 // Object wrapping helper functions to handle reference handles that will
820                 // be used in managed code.
821                 mono_wasm_register_obj: function(obj) {
823                         var gc_handle = undefined;
824                         if (obj !== null && typeof obj !== "undefined") 
825                         {
826                                 gc_handle = obj.__mono_gchandle__;
828                                 if (typeof gc_handle === "undefined") {
829                                         var handle = this.mono_wasm_free_list.length ?
830                                                                 this.mono_wasm_free_list.pop() : this.mono_wasm_ref_counter++;
831                                         obj.__mono_jshandle__ = handle;
832                                         // Obtain the JS -> C# type mapping.
833                                         var wasm_type = this.get_wasm_type(obj);
834                                         gc_handle = obj.__mono_gchandle__ = this.wasm_binding_obj_new(handle + 1, wasm_type);
835                                         this.mono_wasm_object_registry[handle] = obj;
836                                                 
837                                 }
838                         }
839                         return gc_handle;
840                 },
841                 mono_wasm_require_handle: function(handle) {
842                         if (handle > 0)
843                                 return this.mono_wasm_object_registry[handle - 1];
844                         return null;
845                 },
846                 mono_wasm_unregister_obj: function(js_id) {
847                         var obj = this.mono_wasm_object_registry[js_id - 1];
848                         if (typeof obj  !== "undefined" && obj !== null) {
849                                 // if this is the global object then do not
850                                 // unregister it.
851                                 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj)
852                                         return obj;
854                                 var gc_handle = obj.__mono_gchandle__;
855                                 if (typeof gc_handle  !== "undefined") {
856                                         this.wasm_unbind_js_obj_and_free(js_id);
858                                         obj.__mono_gchandle__ = undefined;
859                                         obj.__mono_jshandle__ = undefined;
861                                         this.mono_wasm_object_registry[js_id - 1] = undefined;
862                                         this.mono_wasm_free_list.push(js_id - 1);
863                                 }
864                         }
865                         return obj;
866                 },
867                 mono_wasm_free_handle: function(handle) {
868                         this.mono_wasm_unregister_obj(handle);
869                 },
870                 mono_wasm_free_raw_object: function(js_id) {
871                         var obj = this.mono_wasm_object_registry[js_id - 1];
872                         if (typeof obj  !== "undefined" && obj !== null) {
873                                 // if this is the global object then do not
874                                 // unregister it.
875                                 if (typeof ___mono_wasm_global___ !== "undefined" && ___mono_wasm_global___ === obj)
876                                         return obj;
878                                 var gc_handle = obj.__mono_gchandle__;
879                                 if (typeof gc_handle  !== "undefined") {
881                                         obj.__mono_gchandle__ = undefined;
882                                         obj.__mono_jshandle__ = undefined;
884                                         this.mono_wasm_object_registry[js_id - 1] = undefined;
885                                         this.mono_wasm_free_list.push(js_id - 1);
886                                 }
887                         }
888                         return obj;
889                 },
890                 mono_wasm_get_global: function() {
891                         function testGlobal(obj) {
892                                 obj['___mono_wasm_global___'] = obj;
893                                 var success = typeof ___mono_wasm_global___ === 'object' && obj['___mono_wasm_global___'] === obj;
894                                 if (!success) {
895                                         delete obj['___mono_wasm_global___'];
896                                 }
897                                 return success;
898                         }
899                         if (typeof ___mono_wasm_global___ === 'object') {
900                                 return ___mono_wasm_global___;
901                         }
902                         if (typeof global === 'object' && testGlobal(global)) {
903                                 ___mono_wasm_global___ = global;
904                         } else if (typeof window === 'object' && testGlobal(window)) {
905                                 ___mono_wasm_global___ = window;
906                         } else if (testGlobal((function(){return Function;})()('return this')())) {
908                                 ___mono_wasm_global___ = (function(){return Function;})()('return this')();
910                         }
911                         if (typeof ___mono_wasm_global___ === 'object') {
912                                 return ___mono_wasm_global___;
913                         }
914                         throw Error('unable to get mono wasm global object.');
915                 },
916         
917         },
919         mono_wasm_invoke_js_with_args: function(js_handle, method_name, args, is_exception) {
920                 BINDING.bindings_lazy_init ();
922                 var obj = BINDING.get_js_obj (js_handle);
923                 if (!obj) {
924                         setValue (is_exception, 1, "i32");
925                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
926                 }
928                 var js_name = BINDING.conv_string (method_name);
929                 if (!js_name) {
930                         setValue (is_exception, 1, "i32");
931                         return BINDING.js_string_to_mono_string ("Invalid method name object '" + method_name + "'");
932                 }
934                 var js_args = BINDING.mono_array_to_js_array(args);
936                 var res;
937                 try {
938                         var m = obj [js_name];
939                         if (typeof m === "undefined")
940                                 throw new Error("Method: '" + js_name + "' not found for: '" + Object.prototype.toString.call(obj) + "'");
941                         var res = m.apply (obj, js_args);
942                         return BINDING.js_to_mono_obj (res);
943                 } catch (e) {
944                         var res = e.toString ();
945                         setValue (is_exception, 1, "i32");
946                         if (res === null || res === undefined)
947                                 res = "unknown exception";
948                         return BINDING.js_string_to_mono_string (res);
949                 }
950         },
951         mono_wasm_get_object_property: function(js_handle, property_name, is_exception) {
952                 BINDING.bindings_lazy_init ();
954                 var obj = BINDING.mono_wasm_require_handle (js_handle);
955                 if (!obj) {
956                         setValue (is_exception, 1, "i32");
957                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
958                 }
960                 var js_name = BINDING.conv_string (property_name);
961                 if (!js_name) {
962                         setValue (is_exception, 1, "i32");
963                         return BINDING.js_string_to_mono_string ("Invalid property name object '" + js_name + "'");
964                 }
966                 var res;
967                 try {
968                         var m = obj [js_name];
969                         if (m === Object(m) && obj.__is_mono_proxied__)
970                                 m.__is_mono_proxied__ = true;
971                                 
972                         return BINDING.js_to_mono_obj (m);
973                 } catch (e) {
974                         var res = e.toString ();
975                         setValue (is_exception, 1, "i32");
976                         if (res === null || typeof res === "undefined")
977                                 res = "unknown exception";
978                         return BINDING.js_string_to_mono_string (res);
979                 }
980         },
981     mono_wasm_set_object_property: function (js_handle, property_name, value, createIfNotExist, hasOwnProperty, is_exception) {
983                 BINDING.bindings_lazy_init ();
985                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
986                 if (!requireObject) {
987                         setValue (is_exception, 1, "i32");
988                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
989                 }
991                 var property = BINDING.conv_string (property_name);
992                 if (!property) {
993                         setValue (is_exception, 1, "i32");
994                         return BINDING.js_string_to_mono_string ("Invalid property name object '" + property_name + "'");
995                 }
997         var result = false;
999                 var js_value = BINDING.unbox_mono_obj(value);
1001         if (createIfNotExist) {
1002             requireObject[property] = js_value;
1003             result = true;
1004         }
1005         else {
1006                         result = false;
1007                         if (!createIfNotExist)
1008                         {
1009                                 if (!requireObject.hasOwnProperty(property))
1010                                         return false;
1011                         }
1012             if (hasOwnProperty === true) {
1013                 if (requireObject.hasOwnProperty(property)) {
1014                     requireObject[property] = js_value;
1015                     result = true;
1016                 }
1017             }
1018             else {
1019                 requireObject[property] = js_value;
1020                 result = true;
1021             }
1022         
1023         }
1024         return BINDING.call_method (BINDING.box_js_bool, null, "im", [ result ]);
1025         },
1026         mono_wasm_get_by_index: function(js_handle, property_index, is_exception) {
1027                 BINDING.bindings_lazy_init ();
1029                 var obj = BINDING.mono_wasm_require_handle (js_handle);
1030                 if (!obj) {
1031                         setValue (is_exception, 1, "i32");
1032                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1033                 }
1035                 try {
1036                         var m = obj [property_index];
1037                         return BINDING.js_to_mono_obj (m);
1038                 } catch (e) {
1039                         var res = e.toString ();
1040                         setValue (is_exception, 1, "i32");
1041                         if (res === null || typeof res === "undefined")
1042                                 res = "unknown exception";
1043                         return BINDING.js_string_to_mono_string (res);
1044                 }
1045         },
1046         mono_wasm_set_by_index: function(js_handle, property_index, value, is_exception) {
1047                 BINDING.bindings_lazy_init ();
1049                 var obj = BINDING.mono_wasm_require_handle (js_handle);
1050                 if (!obj) {
1051                         setValue (is_exception, 1, "i32");
1052                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1053                 }
1055                 var js_value = BINDING.unbox_mono_obj(value);
1057                 try {
1058                         obj [property_index] = js_value;
1059                         return true;
1060                 } catch (e) {
1061                         var res = e.toString ();
1062                         setValue (is_exception, 1, "i32");
1063                         if (res === null || typeof res === "undefined")
1064                                 res = "unknown exception";
1065                         return BINDING.js_string_to_mono_string (res);
1066                 }
1067         },
1068         mono_wasm_get_global_object: function(global_name, is_exception) {
1069                 BINDING.bindings_lazy_init ();
1071                 var js_name = BINDING.conv_string (global_name);
1073                 var globalObj = undefined;
1075                 if (!js_name) {
1076                         globalObj = BINDING.mono_wasm_get_global();
1077                 }
1078                 else {
1079                         globalObj = BINDING.mono_wasm_get_global()[js_name];
1080                 }
1082                 if (globalObj === null || typeof globalObj === undefined) {
1083                         setValue (is_exception, 1, "i32");
1084                         return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1085                 }
1087                 return BINDING.js_to_mono_obj (globalObj);
1088         },
1089         mono_wasm_release_handle: function(js_handle, is_exception) {
1090                 BINDING.bindings_lazy_init ();
1092                 BINDING.mono_wasm_free_handle(js_handle);
1093         },      
1094         mono_wasm_release_object: function(js_handle, is_exception) {
1095                 BINDING.bindings_lazy_init ();
1097                 BINDING.mono_wasm_free_raw_object(js_handle);
1098         },      
1099         mono_wasm_bind_core_object: function(js_handle, gc_handle, is_exception) {
1100                 BINDING.bindings_lazy_init ();
1102                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1103                 if (!requireObject) {
1104                         setValue (is_exception, 1, "i32");
1105                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1106                 }
1108                 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1109                 requireObject.__mono_gchandle__ = gc_handle;
1110                 return gc_handle;
1111         },
1112         mono_wasm_bind_host_object: function(js_handle, gc_handle, is_exception) {
1113                 BINDING.bindings_lazy_init ();
1115                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1116                 if (!requireObject) {
1117                         setValue (is_exception, 1, "i32");
1118                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1119                 }
1121                 BINDING.wasm_bind_core_clr_obj(js_handle, gc_handle );
1122                 requireObject.__mono_gchandle__ = gc_handle;
1123                 return gc_handle;
1124         },
1125         mono_wasm_new: function (core_name, args, is_exception) {
1126                 
1127                 var js_name = BINDING.conv_string (core_name);
1129                 if (!js_name) {
1130                         setValue (is_exception, 1, "i32");
1131                         return BINDING.js_string_to_mono_string ("Core object '" + js_name + "' not found.");
1132                 }
1134                 var coreObj = BINDING.mono_wasm_get_global()[js_name];
1136                 if (coreObj === null || typeof coreObj === undefined) {
1137                         setValue (is_exception, 1, "i32");
1138                         return BINDING.js_string_to_mono_string ("Global object '" + js_name + "' not found.");
1139                 }
1141                 var js_args = BINDING.mono_array_to_js_array(args);
1142                 
1143                 try {
1144                         
1145                         // This is all experimental !!!!!!
1146                         var allocator = function(constructor, js_args) {
1147                                 // Not sure if we should be checking for anything here
1148                                 var argsList = new Array();
1149                                 argsList[0] = constructor;
1150                                 if (js_args)
1151                                         argsList = argsList.concat(js_args);
1152                                 var obj = new (constructor.bind.apply(constructor, argsList ));
1153                                 return obj;
1154                         };
1155         
1156                         var res = allocator(coreObj, js_args);
1157                         var gc_handle = BINDING.mono_wasm_free_list.length ? BINDING.mono_wasm_free_list.pop() : BINDING.mono_wasm_ref_counter++;
1158                         BINDING.mono_wasm_object_registry[gc_handle] = res;
1159                         return BINDING.js_to_mono_obj (gc_handle + 1);
1160                 } catch (e) {
1161                         var res = e.toString ();
1162                         setValue (is_exception, 1, "i32");
1163                         if (res === null || res === undefined)
1164                                 res = "Error allocating object.";
1165                         return BINDING.js_string_to_mono_string (res);
1166                 }       
1168         },
1169         mono_wasm_new_object: function(object_handle_or_function, args, is_exception) {
1170                 BINDING.bindings_lazy_init ();
1172                 if (!object_handle_or_function) {
1173                         return BINDING.js_to_mono_obj ({});
1174                 }
1175                 else {
1177                         var requireObject;
1178                         if (typeof object_handle_or_function === 'function')
1179                                 requireObject = object_handle_or_function;
1180                         else
1181                                 requireObject = BINDING.mono_wasm_require_handle (object_handle_or_function);
1183                         if (!requireObject) {
1184                                 setValue (is_exception, 1, "i32");
1185                                 return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + object_handle_or_function + "'");
1186                         }
1188                         var js_args = BINDING.mono_array_to_js_array(args);
1189                         
1190                         try {
1191                                 
1192                                 // This is all experimental !!!!!!
1193                                 var allocator = function(constructor, js_args) {
1194                                         // Not sure if we should be checking for anything here
1195                                         var argsList = new Array();
1196                                         argsList[0] = constructor;
1197                                         if (js_args)
1198                                                 argsList = argsList.concat(js_args);
1199                                         var obj = new (constructor.bind.apply(constructor, argsList ));
1200                                         return obj;
1201                                 };
1202                 
1203                                 var res = allocator(requireObject, js_args);
1204                                 return BINDING.extract_mono_obj (res);
1205                         } catch (e) {
1206                                 var res = e.toString ();
1207                                 setValue (is_exception, 1, "i32");
1208                                 if (res === null || res === undefined)
1209                                         res = "Error allocating object.";
1210                                 return BINDING.js_string_to_mono_string (res);
1211                         }       
1212                 }
1214         },
1215         mono_wasm_typed_array_to_array: function(js_handle, is_exception) {
1216                 BINDING.bindings_lazy_init ();
1218                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1219                 if (!requireObject) {
1220                         setValue (is_exception, 1, "i32");
1221                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1222                 }
1224                 return BINDING.js_typed_array_to_array(requireObject);
1225         },
1226         mono_wasm_typed_array_copy_to: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1227                 BINDING.bindings_lazy_init ();
1229                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1230                 if (!requireObject) {
1231                         setValue (is_exception, 1, "i32");
1232                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1233                 }
1235                 var res = BINDING.typedarray_copy_to(requireObject, pinned_array, begin, end, bytes_per_element);
1236                 return BINDING.js_to_mono_obj (res)
1237         },
1238         mono_wasm_typed_array_from: function(pinned_array, begin, end, bytes_per_element, type, is_exception) {
1239                 BINDING.bindings_lazy_init ();
1240                 var res = BINDING.typed_array_from(pinned_array, begin, end, bytes_per_element, type);
1241                 return BINDING.js_to_mono_obj (res)
1242         },
1243         mono_wasm_typed_array_copy_from: function(js_handle, pinned_array, begin, end, bytes_per_element, is_exception) {
1244                 BINDING.bindings_lazy_init ();
1246                 var requireObject = BINDING.mono_wasm_require_handle (js_handle);
1247                 if (!requireObject) {
1248                         setValue (is_exception, 1, "i32");
1249                         return BINDING.js_string_to_mono_string ("Invalid JS object handle '" + js_handle + "'");
1250                 }
1252                 var res = BINDING.typedarray_copy_from(requireObject, pinned_array, begin, end, bytes_per_element);
1253                 return BINDING.js_to_mono_obj (res)
1254         },
1259 autoAddDeps(BindingSupportLib, '$BINDING')
1260 mergeInto(LibraryManager.library, BindingSupportLib)